15b37fcf3Sryker /* crypto/bn/bn_gcd.c */ 25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 35b37fcf3Sryker * All rights reserved. 45b37fcf3Sryker * 55b37fcf3Sryker * This package is an SSL implementation written 65b37fcf3Sryker * by Eric Young (eay@cryptsoft.com). 75b37fcf3Sryker * The implementation was written so as to conform with Netscapes SSL. 85b37fcf3Sryker * 95b37fcf3Sryker * This library is free for commercial and non-commercial use as long as 105b37fcf3Sryker * the following conditions are aheared to. The following conditions 115b37fcf3Sryker * apply to all code found in this distribution, be it the RC4, RSA, 125b37fcf3Sryker * lhash, DES, etc., code; not just the SSL code. The SSL documentation 135b37fcf3Sryker * included with this distribution is covered by the same copyright terms 145b37fcf3Sryker * except that the holder is Tim Hudson (tjh@cryptsoft.com). 155b37fcf3Sryker * 165b37fcf3Sryker * Copyright remains Eric Young's, and as such any Copyright notices in 175b37fcf3Sryker * the code are not to be removed. 185b37fcf3Sryker * If this package is used in a product, Eric Young should be given attribution 195b37fcf3Sryker * as the author of the parts of the library used. 205b37fcf3Sryker * This can be in the form of a textual message at program startup or 215b37fcf3Sryker * in documentation (online or textual) provided with the package. 225b37fcf3Sryker * 235b37fcf3Sryker * Redistribution and use in source and binary forms, with or without 245b37fcf3Sryker * modification, are permitted provided that the following conditions 255b37fcf3Sryker * are met: 265b37fcf3Sryker * 1. Redistributions of source code must retain the copyright 275b37fcf3Sryker * notice, this list of conditions and the following disclaimer. 285b37fcf3Sryker * 2. Redistributions in binary form must reproduce the above copyright 295b37fcf3Sryker * notice, this list of conditions and the following disclaimer in the 305b37fcf3Sryker * documentation and/or other materials provided with the distribution. 315b37fcf3Sryker * 3. All advertising materials mentioning features or use of this software 325b37fcf3Sryker * must display the following acknowledgement: 335b37fcf3Sryker * "This product includes cryptographic software written by 345b37fcf3Sryker * Eric Young (eay@cryptsoft.com)" 355b37fcf3Sryker * The word 'cryptographic' can be left out if the rouines from the library 365b37fcf3Sryker * being used are not cryptographic related :-). 375b37fcf3Sryker * 4. If you include any Windows specific code (or a derivative thereof) from 385b37fcf3Sryker * the apps directory (application code) you must include an acknowledgement: 395b37fcf3Sryker * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 405b37fcf3Sryker * 415b37fcf3Sryker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 425b37fcf3Sryker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 435b37fcf3Sryker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 445b37fcf3Sryker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 455b37fcf3Sryker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 465b37fcf3Sryker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 475b37fcf3Sryker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 485b37fcf3Sryker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 495b37fcf3Sryker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 505b37fcf3Sryker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 515b37fcf3Sryker * SUCH DAMAGE. 525b37fcf3Sryker * 535b37fcf3Sryker * The licence and distribution terms for any publically available version or 545b37fcf3Sryker * derivative of this code cannot be changed. i.e. this code cannot simply be 555b37fcf3Sryker * copied and put under another distribution licence 565b37fcf3Sryker * [including the GNU Public Licence.] 575b37fcf3Sryker */ 585b37fcf3Sryker 595b37fcf3Sryker #include <stdio.h> 605b37fcf3Sryker #include "cryptlib.h" 615b37fcf3Sryker #include "bn_lcl.h" 625b37fcf3Sryker 635b37fcf3Sryker static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); 64*913ec974Sbeck int BN_gcd(BIGNUM *r, BIGNUM *in_a, BIGNUM *in_b, BN_CTX *ctx) 655b37fcf3Sryker { 665b37fcf3Sryker BIGNUM *a,*b,*t; 675b37fcf3Sryker int ret=0; 685b37fcf3Sryker 69*913ec974Sbeck bn_check_top(in_a); 70*913ec974Sbeck bn_check_top(in_b); 71*913ec974Sbeck 72*913ec974Sbeck a= &(ctx->bn[ctx->tos]); 73*913ec974Sbeck b= &(ctx->bn[ctx->tos+1]); 745b37fcf3Sryker 755b37fcf3Sryker if (BN_copy(a,in_a) == NULL) goto err; 765b37fcf3Sryker if (BN_copy(b,in_b) == NULL) goto err; 775b37fcf3Sryker 785b37fcf3Sryker if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; } 795b37fcf3Sryker t=euclid(a,b); 805b37fcf3Sryker if (t == NULL) goto err; 815b37fcf3Sryker 825b37fcf3Sryker if (BN_copy(r,t) == NULL) goto err; 835b37fcf3Sryker ret=1; 845b37fcf3Sryker err: 855b37fcf3Sryker return(ret); 865b37fcf3Sryker } 875b37fcf3Sryker 88*913ec974Sbeck static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) 895b37fcf3Sryker { 905b37fcf3Sryker BIGNUM *t; 915b37fcf3Sryker int shifts=0; 925b37fcf3Sryker 93*913ec974Sbeck bn_check_top(a); 94*913ec974Sbeck bn_check_top(b); 95*913ec974Sbeck 965b37fcf3Sryker for (;;) 975b37fcf3Sryker { 985b37fcf3Sryker if (BN_is_zero(b)) 995b37fcf3Sryker break; 1005b37fcf3Sryker 1015b37fcf3Sryker if (BN_is_odd(a)) 1025b37fcf3Sryker { 1035b37fcf3Sryker if (BN_is_odd(b)) 1045b37fcf3Sryker { 1055b37fcf3Sryker if (!BN_sub(a,a,b)) goto err; 1065b37fcf3Sryker if (!BN_rshift1(a,a)) goto err; 1075b37fcf3Sryker if (BN_cmp(a,b) < 0) 1085b37fcf3Sryker { t=a; a=b; b=t; } 1095b37fcf3Sryker } 1105b37fcf3Sryker else /* a odd - b even */ 1115b37fcf3Sryker { 1125b37fcf3Sryker if (!BN_rshift1(b,b)) goto err; 1135b37fcf3Sryker if (BN_cmp(a,b) < 0) 1145b37fcf3Sryker { t=a; a=b; b=t; } 1155b37fcf3Sryker } 1165b37fcf3Sryker } 1175b37fcf3Sryker else /* a is even */ 1185b37fcf3Sryker { 1195b37fcf3Sryker if (BN_is_odd(b)) 1205b37fcf3Sryker { 1215b37fcf3Sryker if (!BN_rshift1(a,a)) goto err; 1225b37fcf3Sryker if (BN_cmp(a,b) < 0) 1235b37fcf3Sryker { t=a; a=b; b=t; } 1245b37fcf3Sryker } 1255b37fcf3Sryker else /* a even - b even */ 1265b37fcf3Sryker { 1275b37fcf3Sryker if (!BN_rshift1(a,a)) goto err; 1285b37fcf3Sryker if (!BN_rshift1(b,b)) goto err; 1295b37fcf3Sryker shifts++; 1305b37fcf3Sryker } 1315b37fcf3Sryker } 1325b37fcf3Sryker } 1335b37fcf3Sryker if (shifts) 1345b37fcf3Sryker { 1355b37fcf3Sryker if (!BN_lshift(a,a,shifts)) goto err; 1365b37fcf3Sryker } 1375b37fcf3Sryker return(a); 1385b37fcf3Sryker err: 1395b37fcf3Sryker return(NULL); 1405b37fcf3Sryker } 1415b37fcf3Sryker 1425b37fcf3Sryker /* solves ax == 1 (mod n) */ 143*913ec974Sbeck BIGNUM *BN_mod_inverse(BIGNUM *in, BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) 1445b37fcf3Sryker { 1455b37fcf3Sryker BIGNUM *A,*B,*X,*Y,*M,*D,*R; 146*913ec974Sbeck BIGNUM *T,*ret=NULL; 1475b37fcf3Sryker int sign; 1485b37fcf3Sryker 149*913ec974Sbeck bn_check_top(a); 150*913ec974Sbeck bn_check_top(n); 151*913ec974Sbeck 152*913ec974Sbeck A= &(ctx->bn[ctx->tos]); 153*913ec974Sbeck B= &(ctx->bn[ctx->tos+1]); 154*913ec974Sbeck X= &(ctx->bn[ctx->tos+2]); 155*913ec974Sbeck D= &(ctx->bn[ctx->tos+3]); 156*913ec974Sbeck M= &(ctx->bn[ctx->tos+4]); 157*913ec974Sbeck Y= &(ctx->bn[ctx->tos+5]); 1585b37fcf3Sryker ctx->tos+=6; 159*913ec974Sbeck if (in == NULL) 1605b37fcf3Sryker R=BN_new(); 161*913ec974Sbeck else 162*913ec974Sbeck R=in; 1635b37fcf3Sryker if (R == NULL) goto err; 1645b37fcf3Sryker 1655b37fcf3Sryker BN_zero(X); 1665b37fcf3Sryker BN_one(Y); 1675b37fcf3Sryker if (BN_copy(A,a) == NULL) goto err; 1685b37fcf3Sryker if (BN_copy(B,n) == NULL) goto err; 1695b37fcf3Sryker sign=1; 1705b37fcf3Sryker 1715b37fcf3Sryker while (!BN_is_zero(B)) 1725b37fcf3Sryker { 1735b37fcf3Sryker if (!BN_div(D,M,A,B,ctx)) goto err; 1745b37fcf3Sryker T=A; 1755b37fcf3Sryker A=B; 1765b37fcf3Sryker B=M; 1775b37fcf3Sryker /* T has a struct, M does not */ 1785b37fcf3Sryker 179*913ec974Sbeck if (!BN_mul(T,D,X,ctx)) goto err; 1805b37fcf3Sryker if (!BN_add(T,T,Y)) goto err; 1815b37fcf3Sryker M=Y; 1825b37fcf3Sryker Y=X; 1835b37fcf3Sryker X=T; 1845b37fcf3Sryker sign= -sign; 1855b37fcf3Sryker } 1865b37fcf3Sryker if (sign < 0) 1875b37fcf3Sryker { 1885b37fcf3Sryker if (!BN_sub(Y,n,Y)) goto err; 1895b37fcf3Sryker } 1905b37fcf3Sryker 1915b37fcf3Sryker if (BN_is_one(A)) 1925b37fcf3Sryker { if (!BN_mod(R,Y,n,ctx)) goto err; } 1935b37fcf3Sryker else 1945b37fcf3Sryker { 1955b37fcf3Sryker BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); 1965b37fcf3Sryker goto err; 1975b37fcf3Sryker } 1985b37fcf3Sryker ret=R; 1995b37fcf3Sryker err: 200*913ec974Sbeck if ((ret == NULL) && (in == NULL)) BN_free(R); 2015b37fcf3Sryker ctx->tos-=6; 2025b37fcf3Sryker return(ret); 2035b37fcf3Sryker } 2045b37fcf3Sryker 205