int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) { const int is_multiprime = sk_RSA_additional_prime_num(rsa->additional_primes) > 0; CBB child; if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&child, is_multiprime ? kVersionMulti : kVersionTwoPrime) || !marshal_integer(&child, rsa->n) || !marshal_integer(&child, rsa->e) || !marshal_integer(&child, rsa->d) || !marshal_integer(&child, rsa->p) || !marshal_integer(&child, rsa->q) || !marshal_integer(&child, rsa->dmp1) || !marshal_integer(&child, rsa->dmq1) || !marshal_integer(&child, rsa->iqmp)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); return 0; } CBB other_prime_infos; if (is_multiprime) { if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); return 0; } size_t i; for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); CBB other_prime_info; if (!CBB_add_asn1(&other_prime_infos, &other_prime_info, CBS_ASN1_SEQUENCE) || !marshal_integer(&other_prime_info, ap->prime) || !marshal_integer(&other_prime_info, ap->exp) || !marshal_integer(&other_prime_info, ap->coeff) || !CBB_flush(&other_prime_infos)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); return 0; } } } if (!CBB_flush(cbb)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); return 0; } return 1; }
void RSA_free(RSA *r) { int i; if (r == NULL) return; i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA); #ifdef REF_PRINT REF_PRINT("RSA",r); #endif if (i > 0) return; #ifdef REF_CHECK if (i < 0) { fprintf(stderr,"RSA_free, bad reference count\n"); abort(); } #endif if (r->meth->finish) r->meth->finish(r); #ifndef OPENSSL_NO_ENGINE if (r->engine) ENGINE_finish(r->engine); #endif CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data); if (r->n != NULL) BN_clear_free(r->n); if (r->e != NULL) BN_clear_free(r->e); if (r->d != NULL) BN_clear_free(r->d); if (r->p != NULL) BN_clear_free(r->p); if (r->q != NULL) BN_clear_free(r->q); if (r->dmp1 != NULL) BN_clear_free(r->dmp1); if (r->dmq1 != NULL) BN_clear_free(r->dmq1); if (r->iqmp != NULL) BN_clear_free(r->iqmp); if (r->blinding != NULL) BN_BLINDING_free(r->blinding); if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding); if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data); if (r->additional_primes != NULL) { int j; for (j = 0; j < sk_RSA_additional_prime_num(r->additional_primes); j++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(r->additional_primes, j); BN_clear_free(ap->prime); BN_clear_free(ap->exp); BN_clear_free(ap->coeff); BN_clear_free(ap->r); } sk_RSA_additional_prime_pop_free(r->additional_primes, int_rsa_free_additional_prime); } OPENSSL_free(r); }
static int finish(RSA *rsa) { BN_MONT_CTX_free(rsa->_method_mod_n); BN_MONT_CTX_free(rsa->_method_mod_p); BN_MONT_CTX_free(rsa->_method_mod_q); if (rsa->additional_primes != NULL) { size_t i; for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); BN_MONT_CTX_free(ap->method_mod); } } return 1; }
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { assert(ctx != NULL); assert(rsa->n != NULL); assert(rsa->e != NULL); assert(rsa->d != NULL); assert(rsa->p != NULL); assert(rsa->q != NULL); assert(rsa->dmp1 != NULL); assert(rsa->dmq1 != NULL); assert(rsa->iqmp != NULL); BIGNUM *r1, *m1, *vrfy; BIGNUM local_dmp1, local_dmq1, local_c, local_r1; BIGNUM *dmp1, *dmq1, *c, *pr1; int ret = 0; size_t i, num_additional_primes = 0; if (rsa->additional_primes != NULL) { num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes); } BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); if (r1 == NULL || m1 == NULL || vrfy == NULL) { goto err; } { BIGNUM local_p, local_q; BIGNUM *p = NULL, *q = NULL; /* Make sure BN_mod in Montgomery initialization uses BN_FLG_CONSTTIME. */ BN_init(&local_p); p = &local_p; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); BN_init(&local_q); q = &local_q; BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) || !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) { goto err; } } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { goto err; } /* compute I mod q */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->q, ctx)) { goto err; } /* compute r1^dmq1 mod q */ dmq1 = &local_dmq1; BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) { goto err; } /* compute I mod p */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->p, ctx)) { goto err; } /* compute r1^dmp1 mod p */ dmp1 = &local_dmp1; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) { goto err; } if (!BN_sub(r0, r0, m1)) { goto err; } /* This will help stop the size of r0 increasing, which does * affect the multiply if it optimised for a power of 2 size */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->iqmp, ctx)) { goto err; } /* Turn BN_FLG_CONSTTIME flag on before division operation */ pr1 = &local_r1; BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); if (!BN_mod(r0, pr1, rsa->p, ctx)) { goto err; } /* If p < q it is occasionally possible for the correction of * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following * second correction should *always* correct this rare occurrence. * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->q, ctx)) { goto err; } if (!BN_add(r0, r1, m1)) { goto err; } for (i = 0; i < num_additional_primes; i++) { /* multi-prime RSA. */ BIGNUM local_exp, local_prime; BIGNUM *exp = &local_exp, *prime = &local_prime; RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME); BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME); /* c will already point to a BIGNUM with the correct flags. */ if (!BN_mod(r1, c, prime, ctx)) { goto err; } if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) || !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) { goto err; } BN_set_flags(m1, BN_FLG_CONSTTIME); if (!BN_sub(m1, m1, r0) || !BN_mul(m1, m1, ap->coeff, ctx) || !BN_mod(m1, m1, prime, ctx) || (BN_is_negative(m1) && !BN_add(m1, m1, prime)) || !BN_mul(m1, m1, ap->r, ctx) || !BN_add(r0, r0, m1)) { goto err; } } ret = 1; err: BN_CTX_end(ctx); return ret; }
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { BIGNUM *r1, *m1, *vrfy; BIGNUM local_dmp1, local_dmq1, local_c, local_r1; BIGNUM *dmp1, *dmq1, *c, *pr1; int ret = 0; size_t i, num_additional_primes = 0; if (rsa->additional_primes != NULL) { num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes); } BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); { BIGNUM local_p, local_q; BIGNUM *p = NULL, *q = NULL; /* Make sure BN_mod_inverse in Montgomery intialization uses the * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */ BN_init(&local_p); p = &local_p; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); BN_init(&local_q); q = &local_q; BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { if (BN_MONT_CTX_set_locked(&rsa->_method_mod_p, &rsa->lock, p, ctx) == NULL) { goto err; } if (BN_MONT_CTX_set_locked(&rsa->_method_mod_q, &rsa->lock, q, ctx) == NULL) { goto err; } } } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) { if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) == NULL) { goto err; } } /* compute I mod q */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->q, ctx)) { goto err; } /* compute r1^dmq1 mod q */ dmq1 = &local_dmq1; BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q)) { goto err; } /* compute I mod p */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->p, ctx)) { goto err; } /* compute r1^dmp1 mod p */ dmp1 = &local_dmp1; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p)) { goto err; } if (!BN_sub(r0, r0, m1)) { goto err; } /* This will help stop the size of r0 increasing, which does * affect the multiply if it optimised for a power of 2 size */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->iqmp, ctx)) { goto err; } /* Turn BN_FLG_CONSTTIME flag on before division operation */ pr1 = &local_r1; BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); if (!BN_mod(r0, pr1, rsa->p, ctx)) { goto err; } /* If p < q it is occasionally possible for the correction of * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following * second correction should *always* correct this rare occurrence. * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->q, ctx)) { goto err; } if (!BN_add(r0, r1, m1)) { goto err; } for (i = 0; i < num_additional_primes; i++) { /* multi-prime RSA. */ BIGNUM local_exp, local_prime; BIGNUM *exp = &local_exp, *prime = &local_prime; RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME); BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME); /* c will already point to a BIGNUM with the correct flags. */ if (!BN_mod(r1, c, prime, ctx)) { goto err; } if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) && !BN_MONT_CTX_set_locked(&ap->method_mod, &rsa->lock, prime, ctx)) { goto err; } if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->method_mod)) { goto err; } BN_set_flags(m1, BN_FLG_CONSTTIME); if (!BN_sub(m1, m1, r0) || !BN_mul(m1, m1, ap->coeff, ctx) || !BN_mod(m1, m1, prime, ctx) || (BN_is_negative(m1) && !BN_add(m1, m1, prime)) || !BN_mul(m1, m1, ap->r, ctx) || !BN_add(r0, r0, m1)) { goto err; } } if (rsa->e && rsa->n) { if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) { goto err; } /* If 'I' was greater than (or equal to) rsa->n, the operation * will be equivalent to using 'I mod n'. However, the result of * the verify will *always* be less than 'n' so we don't check * for absolute equality, just congruency. */ if (!BN_sub(vrfy, vrfy, I)) { goto err; } if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) { goto err; } if (BN_is_negative(vrfy)) { if (!BN_add(vrfy, vrfy, rsa->n)) { goto err; } } if (!BN_is_zero(vrfy)) { /* 'I' and 'vrfy' aren't congruent mod n. Don't leak * miscalculated CRT output, just do a raw (slower) * mod_exp and return that instead. */ BIGNUM local_d; BIGNUM *d = NULL; d = &local_d; BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->_method_mod_n)) { goto err; } } } ret = 1; err: BN_CTX_end(ctx); return ret; }
static int do_rsa_print(BIO *out, const RSA *rsa, int off, int include_private) { char *str; const char *s; uint8_t *m = NULL; int ret = 0, mod_len = 0; size_t buf_len = 0; update_buflen(rsa->n, &buf_len); update_buflen(rsa->e, &buf_len); if (include_private) { update_buflen(rsa->d, &buf_len); update_buflen(rsa->p, &buf_len); update_buflen(rsa->q, &buf_len); update_buflen(rsa->dmp1, &buf_len); update_buflen(rsa->dmq1, &buf_len); update_buflen(rsa->iqmp, &buf_len); if (rsa->additional_primes != NULL) { size_t i; for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { const RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); update_buflen(ap->prime, &buf_len); update_buflen(ap->exp, &buf_len); update_buflen(ap->coeff, &buf_len); } } } m = (uint8_t *)OPENSSL_malloc(buf_len + 10); if (m == NULL) { OPENSSL_PUT_ERROR(EVP, do_rsa_print, ERR_R_MALLOC_FAILURE); goto err; } if (rsa->n != NULL) { mod_len = BN_num_bits(rsa->n); } if (!BIO_indent(out, off, 128)) { goto err; } if (include_private && rsa->d) { if (BIO_printf(out, "Private-Key: (%d bit)\nversion: %ld\n", mod_len, rsa->version) <= 0) { goto err; } str = "modulus:"; s = "publicExponent:"; } else { if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) { goto err; } str = "Modulus:"; s = "Exponent:"; } if (!ASN1_bn_print(out, str, rsa->n, m, off) || !ASN1_bn_print(out, s, rsa->e, m, off)) { goto err; } if (include_private) { if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) || !ASN1_bn_print(out, "prime1:", rsa->p, m, off) || !ASN1_bn_print(out, "prime2:", rsa->q, m, off) || !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) || !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) || !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) { goto err; } if (rsa->additional_primes != NULL && sk_RSA_additional_prime_num(rsa->additional_primes) > 0) { size_t i; if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) { goto err; } for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { const RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); if (BIO_printf(out, "otherPrimeInfo (prime %u):\n", (unsigned)(i + 3)) <= 0 || !ASN1_bn_print(out, "prime:", ap->prime, m, off) || !ASN1_bn_print(out, "exponent:", ap->exp, m, off) || !ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) { goto err; } } } } ret = 1; err: OPENSSL_free(m); return ret; }
static int rsa_builtin_multi_prime_keygen(RSA *rsa, int bits, int num_primes, BIGNUM *e_value, BN_GENCB *cb) { BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp; BIGNUM local_r0,local_d,local_p; BIGNUM *pr0,*d,*p; int prime_bits, ok= -1,n=0,i,j; BN_CTX *ctx=NULL; #ifdef OPENSSL_CRYPTOCOP static int cryptocop_count; #endif STACK_OF(RSA_additional_prime) *additional_primes = NULL; if (num_primes < 2) { ok = 0; /* we set our own err */ RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES); goto err; } ctx=BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); r3 = BN_CTX_get(ctx); if (r3 == NULL) goto err; if (num_primes > 2) { if ((additional_primes = sk_RSA_additional_prime_new_null()) == NULL) goto err; } #ifdef OPENSSL_CRYPTOCOP if(bits < CRYPTOCOP_MIN_RSA_BITS && cryptocop_count < CRYPTOCOP_COUNT_MAX) { syslog(LOG_ERR, "RSA key generation with %d bits " CRYPTOCOP_INFO, bits); cryptocop_count++; } #endif for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime)); if (ap == NULL) goto err; memset(ap, 0, sizeof(RSA_additional_prime)); if ((ap->prime = BN_new()) == NULL) goto err; if ((ap->exp = BN_new()) == NULL) goto err; if ((ap->coeff = BN_new()) == NULL) goto err; if ((ap->r = BN_new()) == NULL) goto err; if (!sk_RSA_additional_prime_push(additional_primes, ap)) goto err; } /* We need the RSA components non-NULL */ if(!rsa->n && ((rsa->n=BN_new()) == NULL)) goto err; if(!rsa->d && ((rsa->d=BN_new()) == NULL)) goto err; if(!rsa->e && ((rsa->e=BN_new()) == NULL)) goto err; if(!rsa->p && ((rsa->p=BN_new()) == NULL)) goto err; if(!rsa->q && ((rsa->q=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; BN_copy(rsa->e, e_value); /* generate p and q. */ prime_bits = (bits+(num_primes-1))/num_primes; for (;;) { if(!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb)) goto err; if (!BN_sub(r2,rsa->p,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1)) break; if(!BN_GENCB_call(cb, 2, n++)) goto err; } if(!BN_GENCB_call(cb, 3, 0)) goto err; prime_bits = ((bits-prime_bits) + (num_primes-2))/(num_primes-1); for (;;) { /* When generating ridiculously small keys, we can get stuck * continually regenerating the same prime values. Check for * this and bail if it happens 3 times. */ unsigned int degenerate = 0; do { if(!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) goto err; } while((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3)); if(degenerate == 3) { ok = 0; /* we set our own err */ RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,RSA_R_KEY_SIZE_TOO_SMALL); goto err; } if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1)) break; if(!BN_GENCB_call(cb, 2, n++)) goto err; } if(!BN_GENCB_call(cb, 3, 1)) goto err; if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err; for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); prime_bits = ((bits - BN_num_bits(rsa->n))+(num_primes-(i+1)))/(num_primes-i); for (;;) { if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) goto err; if (BN_cmp(rsa->p, ap->prime) == 0) continue; if (BN_cmp(rsa->q, ap->prime) == 0) continue; for (j = 0; j < i - 2; j++) { if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime, ap->prime) == 0) break; } if (j != i - 2) continue; if (!BN_sub(r2, ap->prime, BN_value_one())) goto err; if (!BN_gcd(r1, r2, rsa->e, ctx)) goto err; if (!BN_is_one(r1)) continue; if (i != num_primes - 1) break; /* For the last prime we'll check that it makes * n large enough. In the two prime case this isn't a * problem because we generate primes with the top two * bits set and so the product is always of the * expected size. In the multi prime case, this doesn't * follow. */ if (!BN_mul(r1, rsa->n, ap->prime, ctx)) goto err; if (BN_num_bits(r1) == bits) break; if(!BN_GENCB_call(cb, 2, n++)) goto err; } /* ap->r is is the product of all the primes prior to the * current one (including p and q). */ if (!BN_copy(ap->r, rsa->n)) goto err; if (i == num_primes - 1) { /* In the case of the last prime, we calculated n in r1 * in the loop above. */ if (!BN_copy(rsa->n, r1)) goto err; } else { if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) goto err; } if(!BN_GENCB_call(cb, 3, 1)) goto err; } if (BN_cmp(rsa->p,rsa->q) < 0) { tmp=rsa->p; rsa->p=rsa->q; rsa->q=tmp; } /* 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) */ for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); if (!BN_sub(r3, ap->prime, BN_value_one())) goto err; if (!BN_mul(r0, r0, r3, ctx)) goto err; } if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { pr0 = &local_r0; BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); } else pr0 = r0; if (!BN_mod_inverse(rsa->d,rsa->e,pr0,ctx)) goto err; /* d */ /* set up d for correct BN_FLG_CONSTTIME flag */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { d = &local_d; BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); } else d = rsa->d; /* calculate d mod (p-1) */ if (!BN_mod(rsa->dmp1,d,r1,ctx)) goto err; /* calculate d mod (q-1) */ if (!BN_mod(rsa->dmq1,d,r2,ctx)) goto err; /* calculate inverse of q mod p */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { p = &local_p; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); } else p = rsa->p; if (!BN_mod_inverse(rsa->iqmp,rsa->q,p,ctx)) goto err; for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); if (!BN_sub(ap->exp, ap->prime, BN_value_one())) goto err; if (!BN_mod(ap->exp, rsa->d, ap->exp, ctx)) goto err; if (!BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) goto err; } ok=1; rsa->additional_primes = additional_primes; additional_primes = NULL; err: if (ok == -1) { RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,ERR_LIB_BN); ok=0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (additional_primes != NULL) { for (i = 0; i < sk_RSA_additional_prime_num(additional_primes); i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i); if (ap->prime != NULL) BN_clear_free(ap->prime); if (ap->exp != NULL) BN_clear_free(ap->exp); if (ap->coeff != NULL) BN_clear_free(ap->coeff); if (ap->r != NULL) BN_clear_free(ap->r); } sk_RSA_additional_prime_pop_free(additional_primes, int_rsa_free_additional_prime); } return ok; }
int RSA_check_key(const RSA *key) { BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp; 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); 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); } size_t i; for (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_inverse(&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(&iqmp, key->iqmp) != 0) { 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); BN_CTX_free(ctx); return ok; }