static BIGNUM * euclid(BIGNUM *a, BIGNUM *b) { BIGNUM *t; int shifts = 0; bn_check_top(a); bn_check_top(b); /* 0 <= b <= a */ while (!BN_is_zero(b)) { /* 0 < b <= a */ if (BN_is_odd(a)) { if (BN_is_odd(b)) { if (!BN_sub(a, a, b)) goto err; if (!BN_rshift1(a, a)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } else /* a odd - b even */ { if (!BN_rshift1(b, b)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } } else /* a is even */ { if (BN_is_odd(b)) { if (!BN_rshift1(a, a)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } else /* a even - b even */ { if (!BN_rshift1(a, a)) goto err; if (!BN_rshift1(b, b)) goto err; shifts++; } } /* 0 <= b <= a */ } if (shifts) { if (!BN_lshift(a, a, shifts)) goto err; } bn_check_top(a); return (a); err: return (NULL); }
static int pgp_logincont(void *obj, struct passwd **uam_pwd, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { unsigned char iv[] = "RJscorat"; BIGNUM *bn1, *bn2, *bn3; u_int16_t sessid; char *p; *rbuflen = 0; /* check for session id */ memcpy(&sessid, ibuf, sizeof(sessid)); if (sessid != pgphash(obj)) return AFPERR_PARAM; ibuf += sizeof(sessid); /* use rbuf as scratch space */ CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey, iv, CAST_DECRYPT); /* check to make sure that the random number is the same. we * get sent back an incremented random number. */ if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL))) return AFPERR_PARAM; if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) { BN_free(bn1); return AFPERR_PARAM; } /* zero out the random number */ memset(rbuf, 0, sizeof(randbuf)); memset(randbuf, 0, sizeof(randbuf)); rbuf += KEYSIZE; if (!(bn3 = BN_new())) { BN_free(bn2); BN_free(bn1); return AFPERR_PARAM; } BN_sub(bn3, bn1, bn2); BN_free(bn2); BN_free(bn1); /* okay. is it one more? */ if (!BN_is_one(bn3)) { BN_free(bn3); return AFPERR_PARAM; } BN_free(bn3); #ifdef AFS if ( kcheckuser(*uam_pwd, rbuf) == 0) { *uam_pwd = pgppwd; return AFP_OK; } #endif /* AFS */ rbuf[PASSWDLEN] = '\0'; p = crypt( rbuf, pgppwd->pw_passwd ); memset(rbuf, 0, PASSWDLEN); if ( strcmp( p, pgppwd->pw_passwd ) == 0 ) { *uam_pwd = pgppwd; return AFP_OK; } return AFPERR_NOTAUTH; }
static void pollard_rho(BIGNUM *val) { BIGNUM *x, *y, *tmp, *num; BN_ULONG a; unsigned int steps_taken, steps_limit; x = BN_new(); y = BN_new(); tmp = BN_new(); num = BN_new(); a = 1; restart: steps_taken = 0; steps_limit = 2; BN_set_word(x, 1); BN_copy(y, x); for (;;) { BN_sqr(tmp, x, ctx); BN_add_word(tmp, a); BN_mod(x, tmp, val, ctx); BN_sub(tmp, x, y); if (BN_is_zero(tmp)) { #ifdef DEBUG printf(" (loop)"); #endif a++; goto restart; } BN_gcd(tmp, tmp, val, ctx); if (!BN_is_one(tmp)) { if (BN_is_prime(tmp, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, tmp); } else { #ifdef DEBUG printf(" (recurse for "); BN_print_dec_fp(stdout, tmp); putchar(')'); #endif pollard_rho(BN_dup(tmp)); #ifdef DEBUG printf(" (back)"); #endif } fflush(stdout); BN_div(num, NULL, val, tmp, ctx); if (BN_is_one(num)) return; if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, num); fflush(stdout); return; } BN_copy(val, num); goto restart; } steps_taken++; if (steps_taken == steps_limit) { BN_copy(y, x); /* teleport the turtle */ steps_taken = 0; steps_limit *= 2; if (steps_limit == 0) { #ifdef DEBUG printf(" (overflow)"); #endif a++; goto restart; } } } }
BIGNUM * BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; BIGNUM *ret = NULL; int sign; if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) { return BN_mod_inverse_no_branch(in, a, n, ctx); } bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); if ((A = BN_CTX_get(ctx)) == NULL) goto err; if ((B = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((D = BN_CTX_get(ctx)) == NULL) goto err; if ((M = BN_CTX_get(ctx)) == NULL) goto err; if ((Y = BN_CTX_get(ctx)) == NULL) goto err; if ((T = BN_CTX_get(ctx)) == NULL) goto err; if (in == NULL) R = BN_new(); else R = in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B, a) == NULL) goto err; if (BN_copy(A, n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* * 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) goto err; } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) goto err; } if (shift > 0) { if (!BN_rshift(B, B, shift)) goto err; } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) goto err; } /* now Y is even */ if (!BN_rshift1(Y, Y)) goto err; } if (shift > 0) { if (!BN_rshift(A, A, shift)) goto err; } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) goto err; /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) goto err; } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) goto err; /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) goto err; } } } else { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) goto err; if (!BN_sub(M, A, B)) goto err; } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T, B)) goto err; if (BN_ucmp(A, T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) goto err; if (!BN_sub(M, A, B)) goto err; } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M, A, T)) goto err; if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ if (BN_ucmp(A, D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D, 2)) goto err; /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D, 3)) goto err; /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M, M, B)) goto err; } } } else { if (!BN_div(D, M, A, B, ctx)) goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp = A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A = B; B = M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp, X, Y)) goto err; } else { if (BN_is_word(D, 2)) { if (!BN_lshift1(tmp, X)) goto err; } else if (BN_is_word(D, 4)) { if (!BN_lshift(tmp, X, 2)) goto err; } else if (D->top == 1) { if (!BN_copy(tmp, X)) goto err; if (!BN_mul_word(tmp, D->d[0])) goto err; } else { if (!BN_mul(tmp, D,X, ctx)) goto err; } if (!BN_add(tmp, tmp, Y)) goto err; } M = Y; /* keep the BIGNUM object, the value does not matter */ Y = X; X = tmp; sign = -sign; } } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y, n, Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y, n) < 0) { if (!BN_copy(R, Y)) goto err; } else { if (!BN_nnmod(R, Y,n, ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE); goto err; } ret = R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return (ret); }
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. * It does not contain branches that may leak sensitive information. */ static BIGNUM * BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; BIGNUM local_A, local_B; BIGNUM *pA, *pB; BIGNUM *ret = NULL; int sign; bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); if ((A = BN_CTX_get(ctx)) == NULL) goto err; if ((B = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((D = BN_CTX_get(ctx)) == NULL) goto err; if ((M = BN_CTX_get(ctx)) == NULL) goto err; if ((Y = BN_CTX_get(ctx)) == NULL) goto err; if ((T = BN_CTX_get(ctx)) == NULL) goto err; if (in == NULL) R = BN_new(); else R = in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B, a) == NULL) goto err; if (BN_copy(A, n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pB = &local_B; BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pA = &local_A; BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ if (!BN_div(D, M, pA, B, ctx)) goto err; /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp = A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A = B; B = M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ if (!BN_mul(tmp, D, X, ctx)) goto err; if (!BN_add(tmp, tmp, Y)) goto err; M = Y; /* keep the BIGNUM object, the value does not matter */ Y = X; X = tmp; sign = -sign; } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y, n, Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y, n) < 0) { if (!BN_copy(R, Y)) goto err; } else { if (!BN_nnmod(R, Y, n, ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH, BN_R_NO_INVERSE); goto err; } ret = R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return (ret); }
/* random number r: 0 <= r < range */ static int bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range) { int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; int n; int count = 100; if (range->neg || BN_is_zero(range)) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); #endif /*End: comment out , 17Aug2006, Chris */ return 0; } n = BN_num_bits(range); /* n > 0 */ /* BN_is_bit_set(range, n - 1) always holds */ if (n == 1) BN_zero(r); else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { /* range = 100..._2, * so 3*range (= 11..._2) is exactly one bit longer than range */ do { if (!bn_rand(r, n + 1, -1, 0)) return 0; /* If r < 3*range, use r := r MOD range * (which is either r, r - range, or r - 2*range). * Otherwise, iterate once more. * Since 3*range = 11..._2, each iteration succeeds with * probability >= .75. */ if (BN_cmp(r ,range) >= 0) { if (!BN_sub(r, r, range)) return 0; if (BN_cmp(r, range) >= 0) if (!BN_sub(r, r, range)) return 0; } if (!--count) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); #endif /*End: comment out , 17Aug2006, Chris */ return 0; } } while (BN_cmp(r, range) >= 0); } else { do { /* range = 11..._2 or range = 101..._2 */ if (!bn_rand(r, n, -1, 0)) return 0; if (!--count) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); #endif /*End: comment out , 17Aug2006, Chris */ return 0; } } while (BN_cmp(r, range) >= 0); } bn_check_top(r); return 1; }
int test_div(BIO *bp, BN_CTX *ctx) { BIGNUM a,b,c,d,e; int i; BN_init(&a); BN_init(&b); BN_init(&c); BN_init(&d); BN_init(&e); for (i=0; i<num0+num1; i++) { if (i < num1) { BN_bntest_rand(&a,400,0,0); BN_copy(&b,&a); BN_lshift(&a,&a,i); BN_add_word(&a,i); } else BN_bntest_rand(&b,50+3*(i-num1),0,0); a.neg=rand_neg(); b.neg=rand_neg(); BN_div(&d,&c,&a,&b,ctx); if (bp != NULL) { if (!results) { BN_print(bp,&a); BIO_puts(bp," / "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&d); BIO_puts(bp,"\n"); if (!results) { BN_print(bp,&a); BIO_puts(bp," % "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&c); BIO_puts(bp,"\n"); } BN_mul(&e,&d,&b,ctx); BN_add(&d,&e,&c); BN_sub(&d,&d,&a); if(!BN_is_zero(&d)) { fprintf(stderr,"Division test failed!\n"); return 0; } } BN_free(&a); BN_free(&b); BN_free(&c); BN_free(&d); BN_free(&e); return(1); }
int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec) { BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); BIGNUM *order; BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *X = NULL, *tmp = NULL; EC_POINT *C = NULL; const EC_POINT *pub_key = NULL; int ok = 0; if (ctx == NULL) goto err; BN_CTX_start(ctx); if ((order = BN_CTX_get(ctx)) == NULL) goto err; if ((e = BN_CTX_get(ctx)) == NULL) goto err; if ((z1 = BN_CTX_get(ctx)) == NULL) goto err; if ((z2 = BN_CTX_get(ctx)) == NULL) goto err; if ((tmp = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((R = BN_CTX_get(ctx)) == NULL) goto err; if ((v = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; pub_key = GOST_KEY_get0_public_key(ec); if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); goto err; } if (BN_mod(e, md, order, ctx) == 0) goto err; if (BN_is_zero(e)) BN_one(e); if ((v = BN_mod_inverse(v, e, order, ctx)) == NULL) goto err; if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0) goto err; if (BN_sub(tmp, order, sig->r) == 0) goto err; if (BN_mod_mul(z2, tmp, v, order, ctx) == 0) goto err; if ((C = EC_POINT_new(group)) == NULL) goto err; if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_mod(R, X, order, ctx) == 0) goto err; if (BN_cmp(R, sig->r) != 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } else { ok = 1; } err: EC_POINT_free(C); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }
int initRSAKey(RSA *rsa, const char *modulus, const char *exponent, const char *p, const char *q) { if(modulus[1] == 'x') modulus += 2; // Initialize with known key components if (!(BN_hex2bn(&rsa->n, modulus) // public modulus && BN_hex2bn(&rsa->e, exponent) // public exponent && BN_dec2bn(&rsa->p, p) // secret prime factor && BN_dec2bn(&rsa->q, q) // secret prime factor )) { printf("Error creating RSA key: bignum conversion failed!\n"); } int ok = -1; // BIGNUM context for bignum operations BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); BIGNUM *r0 = BN_CTX_get(ctx); BIGNUM *r1 = BN_CTX_get(ctx); BIGNUM *r2 = BN_CTX_get(ctx); if (r2 == NULL) goto err; /* We need the (other) RSA components non-NULL */ if(!rsa->d && ((rsa->d=BN_new()) == NULL)) goto err; if(!rsa->dmp1 && ((rsa->dmp1=BN_new()) == NULL)) goto err; if(!rsa->dmq1 && ((rsa->dmq1=BN_new()) == NULL)) goto err; if(!rsa->iqmp && ((rsa->iqmp=BN_new()) == NULL)) goto err; /* calculate d */ if (!BN_sub(r1,rsa->p,BN_value_one())) goto err; /* p-1 */ if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; /* q-1 */ if (!BN_mul(r0,r1,r2,ctx)) goto err; /* (p-1)(q-1) */ if (!BN_mod_inverse(rsa->d,rsa->e,r0,ctx)) goto err; /* d */ /* calculate d mod (p-1) */ if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err; /* calculate d mod (q-1) */ if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err; /* calculate inverse of q mod p */ if (!BN_mod_inverse(rsa->iqmp,rsa->q,rsa->p,ctx)) goto err; ok = 1; err: if (ok == -1) { printf("Error creating RSA key: bignum operation failed!\n"); } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { BIGNUM *kinv=NULL,*r=NULL,*s=NULL; BIGNUM m; BIGNUM xr; BN_CTX *ctx=NULL; int i,reason=ERR_R_BN_LIB; DSA_SIG *ret=NULL; BN_init(&m); BN_init(&xr); s=BN_new(); if (s == NULL) goto err; i=BN_num_bytes(dsa->q); /* should be 20 */ if ((dlen > i) || (dlen > 50)) { reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE; goto err; } ctx=BN_CTX_new(); if (ctx == NULL) goto err; if ((dsa->kinv == NULL) || (dsa->r == NULL)) { if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err; } else { kinv=dsa->kinv; dsa->kinv=NULL; r=dsa->r; dsa->r=NULL; } if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err; /* Compute s = inv(k) (m + xr) mod q */ if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */ if (!BN_add(s, &xr, &m)) goto err; /* s = m + xr */ if (BN_cmp(s,dsa->q) > 0) BN_sub(s,s,dsa->q); if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; ret=DSA_SIG_new(); if (ret == NULL) goto err; ret->r = r; ret->s = s; err: if (!ret) { DSAerr(DSA_F_DSA_DO_SIGN,reason); BN_free(r); BN_free(s); } if (ctx != NULL) BN_CTX_free(ctx); BN_clear_free(&m); BN_clear_free(&xr); if (kinv != NULL) /* dsa->kinv is NULL now if we used it */ BN_clear_free(kinv); return(ret); }
int RSA_recover_crt_params(RSA *rsa) { BN_CTX *ctx; BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q; int ok = 0; if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); return 0; } if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) { OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN); return 0; } if (rsa->additional_primes != NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY); return 0; } /* This uses the algorithm from section 9B of the RSA paper: * http://people.csail.mit.edu/rivest/Rsapaper.pdf */ ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); totient = BN_CTX_get(ctx); rem = BN_CTX_get(ctx); multiple = BN_CTX_get(ctx); p_plus_q = BN_CTX_get(ctx); p_minus_q = BN_CTX_get(ctx); if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL || p_minus_q == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } /* ed-1 is a small multiple of φ(n). */ if (!BN_mul(totient, rsa->e, rsa->d, ctx) || !BN_sub_word(totient, 1) || /* φ(n) = * pq - p - q + 1 = * n - (p + q) + 1 * * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very * close. But, when we calculate the quotient, we'll be truncating it * because we discard the remainder. Thus (ed-1)/multiple will be >= n, * which the totient cannot be. So we add one to the estimate. * * Consider ed-1 as: * * multiple * (n - (p+q) + 1) = * multiple*n - multiple*(p+q) + multiple * * When we divide by n, the first term becomes multiple and, since * multiple and p+q is tiny compared to n, the second and third terms can * be ignored. Thus I claim that subtracting one from the estimate is * sufficient. */ !BN_div(multiple, NULL, totient, rsa->n, ctx) || !BN_add_word(multiple, 1) || !BN_div(totient, rem, totient, multiple, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } if (!BN_is_zero(rem)) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); goto err; } rsa->p = BN_new(); rsa->q = BN_new(); rsa->dmp1 = BN_new(); rsa->dmq1 = BN_new(); rsa->iqmp = BN_new(); if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } /* φ(n) = n - (p + q) + 1 => * n - totient + 1 = p + q */ if (!BN_sub(p_plus_q, rsa->n, totient) || !BN_add_word(p_plus_q, 1) || /* p - q = sqrt((p+q)^2 - 4n) */ !BN_sqr(rem, p_plus_q, ctx) || !BN_lshift(multiple, rsa->n, 2) || !BN_sub(rem, rem, multiple) || !BN_sqrt(p_minus_q, rem, ctx) || /* q is 1/2 (p+q)-(p-q) */ !BN_sub(rsa->q, p_plus_q, p_minus_q) || !BN_rshift1(rsa->q, rsa->q) || !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) || !BN_mul(multiple, rsa->p, rsa->q, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } if (BN_cmp(multiple, rsa->n) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR); goto err; } if (!BN_sub(rem, rsa->p, BN_value_one()) || !BN_mod(rsa->dmp1, rsa->d, rem, ctx) || !BN_sub(rem, rsa->q, BN_value_one()) || !BN_mod(rsa->dmq1, rsa->d, rem, ctx) || !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (!ok) { bn_free_and_null(&rsa->p); bn_free_and_null(&rsa->q); bn_free_and_null(&rsa->dmp1); bn_free_and_null(&rsa->dmq1); bn_free_and_null(&rsa->iqmp); } return ok; }
int RSA_check_key(const RSA *key) { BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp_times_q; BN_CTX *ctx; int ok = 0, has_crt_values; if (RSA_is_opaque(key)) { /* Opaque keys can't be checked. */ return 1; } if ((key->p != NULL) != (key->q != NULL)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN); return 0; } if (!key->n || !key->e) { OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); return 0; } if (!key->d || !key->p) { /* For a public key, or without p and q, there's nothing that can be * checked. */ return 1; } ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); return 0; } BN_init(&n); BN_init(&pm1); BN_init(&qm1); BN_init(&lcm); BN_init(&gcd); BN_init(&de); BN_init(&dmp1); BN_init(&dmq1); BN_init(&iqmp_times_q); if (!BN_mul(&n, key->p, key->q, ctx) || /* lcm = lcm(prime-1, for all primes) */ !BN_sub(&pm1, key->p, BN_value_one()) || !BN_sub(&qm1, key->q, BN_value_one()) || !BN_mul(&lcm, &pm1, &qm1, ctx) || !BN_gcd(&gcd, &pm1, &qm1, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } size_t num_additional_primes = 0; if (key->additional_primes != NULL) { num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes); } for (size_t i = 0; i < num_additional_primes; i++) { const RSA_additional_prime *ap = sk_RSA_additional_prime_value(key->additional_primes, i); if (!BN_mul(&n, &n, ap->prime, ctx) || !BN_sub(&pm1, ap->prime, BN_value_one()) || !BN_mul(&lcm, &lcm, &pm1, ctx) || !BN_gcd(&gcd, &gcd, &pm1, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } } if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) || !BN_gcd(&gcd, &pm1, &qm1, ctx) || /* de = d*e mod lcm(prime-1, for all primes). */ !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } if (BN_cmp(&n, key->n) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q); goto out; } if (!BN_is_one(&de)) { OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1); goto out; } has_crt_values = key->dmp1 != NULL; if (has_crt_values != (key->dmq1 != NULL) || has_crt_values != (key->iqmp != NULL)) { OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES); goto out; } if (has_crt_values && num_additional_primes == 0) { if (/* dmp1 = d mod (p-1) */ !BN_mod(&dmp1, key->d, &pm1, ctx) || /* dmq1 = d mod (q-1) */ !BN_mod(&dmq1, key->d, &qm1, ctx) || /* iqmp = q^-1 mod p */ !BN_mod_mul(&iqmp_times_q, key->iqmp, key->q, key->p, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } if (BN_cmp(&dmp1, key->dmp1) != 0 || BN_cmp(&dmq1, key->dmq1) != 0 || BN_cmp(key->iqmp, key->p) >= 0 || !BN_is_one(&iqmp_times_q)) { OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT); goto out; } } ok = 1; out: BN_free(&n); BN_free(&pm1); BN_free(&qm1); BN_free(&lcm); BN_free(&gcd); BN_free(&de); BN_free(&dmp1); BN_free(&dmq1); BN_free(&iqmp_times_q); BN_CTX_free(ctx); return ok; }