int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) { BN_CTX *ctx = NULL; BIGNUM *shared_key; int ret = -1; int check_result; if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); shared_key = BN_CTX_get(ctx); if (shared_key == NULL) { goto err; } if (dh->priv_key == NULL) { OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE); goto err; } if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, dh->p, ctx)) { goto err; } if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) { OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); goto err; } if (!BN_mod_exp_mont_consttime(shared_key, peers_key, dh->priv_key, dh->p, ctx, dh->method_mont_p)) { OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); goto err; } ret = BN_bn2bin(shared_key, out); err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ret; }
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; }
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) { BIGNUM *f, *result; BN_CTX *ctx = NULL; unsigned blinding_index = 0; BN_BLINDING *blinding = NULL; int ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); f = BN_CTX_get(ctx); result = BN_CTX_get(ctx); if (f == NULL || result == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } if (BN_bin2bn(in, len, f) == NULL) { goto err; } if (BN_ucmp(f, rsa->n) >= 0) { /* Usually the padding functions would catch this. */ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } /* We cannot do blinding or verification without |e|, and continuing without * those countermeasures is dangerous. However, the Java/Android RSA API * requires support for keys where only |d| and |n| (and not |e|) are known. * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */ int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL; if (!disable_security) { /* Keys without public exponents must have blinding explicitly disabled to * be used. */ if (rsa->e == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT); goto err; } blinding = rsa_blinding_get(rsa, &blinding_index, ctx); if (blinding == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) { goto err; } } if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL && rsa->dmq1 != NULL && rsa->iqmp != NULL) { if (!mod_exp(result, f, rsa, ctx)) { goto err; } } else { BIGNUM local_d; BIGNUM *d = NULL; BN_init(&local_d); d = &local_d; BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(result, f, d, rsa->n, ctx, rsa->mont_n)) { goto err; } } /* Verify the result to protect against fault attacks as described in the * 1997 paper "On the Importance of Checking Cryptographic Protocols for * Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some * implementations do this only when the CRT is used, but we do it in all * cases. Section 6 of the aforementioned paper describes an attack that * works when the CRT isn't used. That attack is much less likely to succeed * than the CRT attack, but there have likely been improvements since 1997. * * This check is cheap assuming |e| is small; it almost always is. */ if (!disable_security) { BIGNUM *vrfy = BN_CTX_get(ctx); if (vrfy == NULL || !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) || !BN_equal_consttime(vrfy, f)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) { goto err; } } if (!BN_bn2bin_padded(out, len, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } ret = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (blinding != NULL) { rsa_blinding_release(rsa, blinding, blinding_index); } return ret; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (k == NULL || r == NULL || order == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* * We do not want timing information to leak the length of k, so we * compute G*k using an equivalent scalar of fixed bit-length. */ if (!BN_add(k, k, order)) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (!BN_add(k, k, order)) goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (EC_GROUP_get_mont_data(group) != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx != ctx_in) BN_CTX_free(ctx); BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return (ret); }
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; int ret = 0; BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); if (r1 == NULL || m1 == NULL) { goto err; } if (!freeze_private_key(rsa, ctx)) { goto err; } // Implementing RSA with CRT in constant-time is sensitive to which prime is // larger. Canonicalize fields so that |p| is the larger prime. const BIGNUM *dmp1 = rsa->dmp1_fixed, *dmq1 = rsa->dmq1_fixed; const BN_MONT_CTX *mont_p = rsa->mont_p, *mont_q = rsa->mont_q; if (BN_cmp(rsa->p, rsa->q) < 0) { mont_p = rsa->mont_q; mont_q = rsa->mont_p; dmp1 = rsa->dmq1_fixed; dmq1 = rsa->dmp1_fixed; } // Use the minimal-width versions of |n|, |p|, and |q|. Either works, but if // someone gives us non-minimal values, these will be slightly more efficient // on the non-Montgomery operations. const BIGNUM *n = &rsa->mont_n->N; const BIGNUM *p = &mont_p->N; const BIGNUM *q = &mont_q->N; // This is a pre-condition for |mod_montgomery|. It was already checked by the // caller. assert(BN_ucmp(I, n) < 0); if (// |m1| is the result modulo |q|. !mod_montgomery(r1, I, q, mont_q, p, ctx) || !BN_mod_exp_mont_consttime(m1, r1, dmq1, q, ctx, mont_q) || // |r0| is the result modulo |p|. !mod_montgomery(r1, I, p, mont_p, q, ctx) || !BN_mod_exp_mont_consttime(r0, r1, dmp1, p, ctx, mont_p) || // Compute r0 = r0 - m1 mod p. |p| is the larger prime, so |m1| is already // fully reduced mod |p|. !bn_mod_sub_consttime(r0, r0, m1, p, ctx) || // r0 = r0 * iqmp mod p. We use Montgomery multiplication to compute this // in constant time. |inv_small_mod_large_mont| is in Montgomery form and // r0 is not, so the result is taken out of Montgomery form. !BN_mod_mul_montgomery(r0, r0, rsa->inv_small_mod_large_mont, mont_p, ctx) || // r0 = r0 * q + m1 gives the final result. Reducing modulo q gives m1, so // it is correct mod p. Reducing modulo p gives (r0-m1)*iqmp*q + m1 = r0, // so it is correct mod q. Finally, the result is bounded by [m1, n + m1), // and the result is at least |m1|, so this must be the unique answer in // [0, n). !bn_mul_consttime(r0, r0, q, ctx) || !bn_uadd_consttime(r0, r0, m1) || // The result should be bounded by |n|, but fixed-width operations may // bound the width slightly higher, so fix it. !bn_resize_words(r0, n->width)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) { if (rsa->n == NULL || rsa->d == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); return 0; } BIGNUM *f, *result; BN_CTX *ctx = NULL; unsigned blinding_index = 0; BN_BLINDING *blinding = NULL; int ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); f = BN_CTX_get(ctx); result = BN_CTX_get(ctx); if (f == NULL || result == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } if (BN_bin2bn(in, len, f) == NULL) { goto err; } if (BN_ucmp(f, rsa->n) >= 0) { // Usually the padding functions would catch this. OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); goto err; } if (!freeze_private_key(rsa, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } const int do_blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0; if (rsa->e == NULL && do_blinding) { // We cannot do blinding or verification without |e|, and continuing without // those countermeasures is dangerous. However, the Java/Android RSA API // requires support for keys where only |d| and |n| (and not |e|) are known. // The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT); goto err; } if (do_blinding) { blinding = rsa_blinding_get(rsa, &blinding_index, ctx); if (blinding == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) { goto err; } } if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL && rsa->dmq1 != NULL && rsa->iqmp != NULL) { if (!mod_exp(result, f, rsa, ctx)) { goto err; } } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d_fixed, rsa->n, ctx, rsa->mont_n)) { goto err; } // Verify the result to protect against fault attacks as described in the // 1997 paper "On the Importance of Checking Cryptographic Protocols for // Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some // implementations do this only when the CRT is used, but we do it in all // cases. Section 6 of the aforementioned paper describes an attack that // works when the CRT isn't used. That attack is much less likely to succeed // than the CRT attack, but there have likely been improvements since 1997. // // This check is cheap assuming |e| is small; it almost always is. if (rsa->e != NULL) { BIGNUM *vrfy = BN_CTX_get(ctx); if (vrfy == NULL || !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) || !BN_equal_consttime(vrfy, f)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } } if (do_blinding && !BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) { goto err; } // The computation should have left |result| as a maximally-wide number, so // that it and serializing does not leak information about the magnitude of // the result. // // See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. assert(result->width == rsa->mont_n->N.width); if (!BN_bn2bin_padded(out, len, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } ret = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (blinding != NULL) { rsa_blinding_release(rsa, blinding, blinding_index); } return ret; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; int order_bits; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } /* Preallocate space */ order_bits = BN_num_bits(order); if (!BN_set_bit(k, order_bits) || !BN_set_bit(r, order_bits) || !BN_set_bit(X, order_bits)) goto err; do { /* get random k */ do if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } while (BN_is_zero(k)) ; /* * We do not want timing information to leak the length of k, so we * compute G*k using an equivalent scalar of fixed bit-length. * * We unconditionally perform both of these additions to prevent a * small timing information leakage. We then choose the sum that is * one bit longer than the order. This guarantees the code * path used in the constant time implementations elsewhere. * * TODO: revisit the BN_copy aiming for a memory access agnostic * conditional copy. */ if (!BN_add(r, k, order) || !BN_add(X, r, order) || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X)) goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (EC_GROUP_get_mont_data(group) != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); if (*kinvp != NULL) BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order != NULL) BN_free(order); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return (ret); }
int main(int argc, char *argv[]) { BN_CTX *ctx; BIO *out = NULL; int i, ret; unsigned char c; BIGNUM *r_mont, *r_mont_const, *r_recp, *r_simple, *a, *b, *m; RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we * don't even check its return * value (which we should) */ ERR_load_BN_strings(); ctx = BN_CTX_new(); if (ctx == NULL) EXIT(1); r_mont = BN_new(); r_mont_const = BN_new(); r_recp = BN_new(); r_simple = BN_new(); a = BN_new(); b = BN_new(); m = BN_new(); if ((r_mont == NULL) || (r_recp == NULL) || (a == NULL) || (b == NULL)) goto err; out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); for (i = 0; i < 200; i++) { RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(a, NUM_BITS + c, 0, 0); RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(b, NUM_BITS + c, 0, 0); RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(m, NUM_BITS + c, 0, 1); BN_mod(a, a, m, ctx); BN_mod(b, b, m, ctx); ret = BN_mod_exp_mont(r_mont, a, b, m, ctx, NULL); if (ret <= 0) { printf("BN_mod_exp_mont() problems\n"); ERR_print_errors(out); EXIT(1); } ret = BN_mod_exp_recp(r_recp, a, b, m, ctx); if (ret <= 0) { printf("BN_mod_exp_recp() problems\n"); ERR_print_errors(out); EXIT(1); } ret = BN_mod_exp_simple(r_simple, a, b, m, ctx); if (ret <= 0) { printf("BN_mod_exp_simple() problems\n"); ERR_print_errors(out); EXIT(1); } ret = BN_mod_exp_mont_consttime(r_mont_const, a, b, m, ctx, NULL); if (ret <= 0) { printf("BN_mod_exp_mont_consttime() problems\n"); ERR_print_errors(out); EXIT(1); } if (BN_cmp(r_simple, r_mont) == 0 && BN_cmp(r_simple, r_recp) == 0 && BN_cmp(r_simple, r_mont_const) == 0) { printf("."); fflush(stdout); } else { if (BN_cmp(r_simple, r_mont) != 0) printf("\nsimple and mont results differ\n"); if (BN_cmp(r_simple, r_mont_const) != 0) printf("\nsimple and mont const time results differ\n"); if (BN_cmp(r_simple, r_recp) != 0) printf("\nsimple and recp results differ\n"); printf("a (%3d) = ", BN_num_bits(a)); BN_print(out, a); printf("\nb (%3d) = ", BN_num_bits(b)); BN_print(out, b); printf("\nm (%3d) = ", BN_num_bits(m)); BN_print(out, m); printf("\nsimple ="); BN_print(out, r_simple); printf("\nrecp ="); BN_print(out, r_recp); printf("\nmont ="); BN_print(out, r_mont); printf("\nmont_ct ="); BN_print(out, r_mont_const); printf("\n"); EXIT(1); } } BN_free(r_mont); BN_free(r_mont_const); BN_free(r_recp); BN_free(r_simple); BN_free(a); BN_free(b); BN_free(m); BN_CTX_free(ctx); ERR_remove_thread_state(NULL); CRYPTO_mem_leaks(out); BIO_free(out); printf("\n"); if (test_exp_mod_zero() != 0) goto err; printf("done\n"); EXIT(0); err: ERR_load_crypto_strings(); ERR_print_errors(out); #ifdef OPENSSL_SYS_NETWARE printf("ERROR\n"); #endif EXIT(1); return (1); }
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero() { BIGNUM *a = NULL, *p = NULL, *m = NULL; BIGNUM *r = NULL; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; m = BN_new(); if (!m) goto err; BN_one(m); a = BN_new(); if (!a) goto err; BN_one(a); p = BN_new(); if (!p) goto err; BN_zero(p); r = BN_new(); if (!r) goto err; if (!BN_rand(a, 1024, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) goto err; if (!BN_mod_exp(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp", r, a)) failed = 1; if (!BN_mod_exp_recp(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_recp", r, a)) failed = 1; if (!BN_mod_exp_simple(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_simple", r, a)) failed = 1; if (!BN_mod_exp_mont(r, a, p, m, ctx, NULL)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_mont", r, a)) failed = 1; if (!BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL)) { goto err; } if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a)) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL)) goto err; if (!BN_is_zero(r)) { fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); fprintf(stderr, "r = "); BN_print_fp(stderr, r); fprintf(stderr, "\n"); return 0; } ret = failed; err: BN_free(r); BN_free(a); BN_free(p); BN_free(m); BN_CTX_free(ctx); return ret; }
int DH_generate_key(DH *dh) { int ok = 0; int generate_new_key = 0; BN_CTX *ctx = NULL; BIGNUM *pub_key = NULL, *priv_key = NULL; if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } if (dh->priv_key == NULL) { priv_key = BN_new(); if (priv_key == NULL) { goto err; } generate_new_key = 1; } else { priv_key = dh->priv_key; } if (dh->pub_key == NULL) { pub_key = BN_new(); if (pub_key == NULL) { goto err; } } else { pub_key = dh->pub_key; } if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, dh->p, ctx)) { goto err; } if (generate_new_key) { if (dh->q) { if (!BN_rand_range_ex(priv_key, 2, dh->q)) { goto err; } } else { // secret exponent length unsigned priv_bits = dh->priv_length; if (priv_bits == 0) { const unsigned p_bits = BN_num_bits(dh->p); if (p_bits == 0) { goto err; } priv_bits = p_bits - 1; } if (!BN_rand(priv_key, priv_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) { goto err; } } } if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx, dh->method_mont_p)) { goto err; } dh->pub_key = pub_key; dh->priv_key = priv_key; ok = 1; err: if (ok != 1) { OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); } if (dh->pub_key == NULL) { BN_free(pub_key); } if (dh->priv_key == NULL) { BN_free(priv_key); } BN_CTX_free(ctx); return ok; }
/* * test_mod_exp_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_mod_exp_zero(void) { BIGNUM *a = NULL, *p = NULL, *m = NULL; BIGNUM *r = NULL; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; if (!TEST_ptr(m = BN_new()) || !TEST_ptr(a = BN_new()) || !TEST_ptr(p = BN_new()) || !TEST_ptr(r = BN_new())) goto err; BN_one(m); BN_one(a); BN_zero(p); if (!TEST_true(BN_rand(a, 1024, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))) goto err; if (!TEST_true(BN_mod_exp(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_recp(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_recp", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_simple(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_simple", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_mont(r, a, p, m, ctx, NULL))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a))) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!TEST_true(BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL))) goto err; if (!TEST_BN_eq_zero(r)) { TEST_error("BN_mod_exp_mont_word failed: " "1 ** 0 mod 1 = r (should be 0)"); BN_print_var(r); goto err; } ret = !failed; err: BN_free(r); BN_free(a); BN_free(p); BN_free(m); BN_CTX_free(ctx); return ret; }
static int test_mod_exp(int round) { BN_CTX *ctx; unsigned char c; int ret = 0; BIGNUM *r_mont = NULL; BIGNUM *r_mont_const = NULL; BIGNUM *r_recp = NULL; BIGNUM *r_simple = NULL; BIGNUM *a = NULL; BIGNUM *b = NULL; BIGNUM *m = NULL; if (!TEST_ptr(ctx = BN_CTX_new())) goto err; if (!TEST_ptr(r_mont = BN_new()) || !TEST_ptr(r_mont_const = BN_new()) || !TEST_ptr(r_recp = BN_new()) || !TEST_ptr(r_simple = BN_new()) || !TEST_ptr(a = BN_new()) || !TEST_ptr(b = BN_new()) || !TEST_ptr(m = BN_new())) goto err; RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(a, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY); RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(b, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY); RAND_bytes(&c, 1); c = (c % BN_BITS) - BN_BITS2; BN_rand(m, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD); if (!TEST_true(BN_mod(a, a, m, ctx)) || !TEST_true(BN_mod(b, b, m, ctx)) || !TEST_true(BN_mod_exp_mont(r_mont, a, b, m, ctx, NULL)) || !TEST_true(BN_mod_exp_recp(r_recp, a, b, m, ctx)) || !TEST_true(BN_mod_exp_simple(r_simple, a, b, m, ctx)) || !TEST_true(BN_mod_exp_mont_consttime(r_mont_const, a, b, m, ctx, NULL))) goto err; if (!TEST_BN_eq(r_simple, r_mont) || !TEST_BN_eq(r_simple, r_recp) || !TEST_BN_eq(r_simple, r_mont_const)) { if (BN_cmp(r_simple, r_mont) != 0) TEST_info("simple and mont results differ"); if (BN_cmp(r_simple, r_mont_const) != 0) TEST_info("simple and mont const time results differ"); if (BN_cmp(r_simple, r_recp) != 0) TEST_info("simple and recp results differ"); BN_print_var(a); BN_print_var(b); BN_print_var(m); BN_print_var(r_simple); BN_print_var(r_recp); BN_print_var(r_mont); BN_print_var(r_mont_const); goto err; } ret = 1; err: BN_free(r_mont); BN_free(r_mont_const); BN_free(r_recp); BN_free(r_simple); BN_free(a); BN_free(b); BN_free(m); BN_CTX_free(ctx); return ret; }
int exp_main(int argc, char *argv[]) #endif { BN_CTX *ctx; BIO *out=NULL; int i,ret; unsigned char c; BIGNUM *r_mont,*r_mont_const,*r_recp,*r_simple,*a,*b,*m; // FILE* temp; RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't * even check its return value * (which we should) */ if(errno==ENOMEM) { return 1; } ERR_load_BN_strings(); if(errno==ENOMEM) { return 1; } ctx=BN_CTX_new(); if (ctx == NULL) { if(errno==ENOMEM) { return 1; } return 1; } r_mont=BN_new(); if(r_mont==NULL&&errno==ENOMEM) { return 1; } r_mont_const=BN_new(); if(r_mont_const==NULL&&errno==ENOMEM) { return 1; } r_recp=BN_new(); if(r_recp==NULL&&errno==ENOMEM) { return 1; } r_simple=BN_new(); if(r_simple==NULL&&errno==ENOMEM) { return 1; } a=BN_new(); if(a==NULL&&errno==ENOMEM) { return 1; } b=BN_new(); if(b==NULL&&errno==ENOMEM) { return 1; } m=BN_new(); if(m==NULL&&errno==ENOMEM) { return 1; } if ( (r_mont == NULL) || (r_recp == NULL) || (a == NULL) || (b == NULL)) goto err; out=BIO_new(BIO_s_file()); if(out==NULL&&errno==ENOMEM) { return 1; } if (out == NULL) return 1; BIO_set_fp(out,stdout,BIO_NOCLOSE); if(errno==ENOMEM) { return 1; } // temp = fopen("sanjeev.txt", "w"); for (i=0; i<200; i++) { // fputc(i,temp); RAND_bytes(&c,1); if(errno==ENOMEM) { return 1; } c=(c%BN_BITS)-BN_BITS2; BN_rand(a,NUM_BITS+c,0,0); if(errno==ENOMEM) { return 1; } RAND_bytes(&c,1); if(errno==ENOMEM) { return 1; } c=(c%BN_BITS)-BN_BITS2; BN_rand(b,NUM_BITS+c,0,0); if(errno==ENOMEM) { return 1; } RAND_bytes(&c,1); if(errno==ENOMEM) { return 1; } c=(c%BN_BITS)-BN_BITS2; BN_rand(m,NUM_BITS+c,0,1); if(errno==ENOMEM) { return 1; } BN_mod(a,a,m,ctx); if(errno==ENOMEM) { return 1; } BN_mod(b,b,m,ctx); if(errno==ENOMEM) { return 1; } ret=BN_mod_exp_mont(r_mont,a,b,m,ctx,NULL); if (ret <= 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"BN_mod_exp_mont() problems\n"); ERR_print_errors(out); if(errno==ENOMEM) { return 1; } return 1; } ret=BN_mod_exp_recp(r_recp,a,b,m,ctx); if (ret <= 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"BN_mod_exp_recp() problems\n"); ERR_print_errors(out); if(errno==ENOMEM) { return 1; } return 1; } ret=BN_mod_exp_simple(r_simple,a,b,m,ctx); if (ret <= 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"BN_mod_exp_simple() problems\n"); ERR_print_errors(out); if(errno==ENOMEM) { return 1; } return 1; } ret=BN_mod_exp_mont_consttime(r_mont_const,a,b,m,ctx,NULL); if (ret <= 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"BN_mod_exp_mont_consttime() problems\n"); ERR_print_errors(out); if(errno==ENOMEM) { return 1; } return 1; } if (BN_cmp(r_simple, r_mont) == 0 && BN_cmp(r_simple,r_recp) == 0 && BN_cmp(r_simple,r_mont_const) == 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"."); fflush(stdout); } else { if (BN_cmp(r_simple,r_mont) != 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nsimple and mont results differ\n"); } if (BN_cmp(r_simple,r_mont) != 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nsimple and mont const time results differ\n"); } if (BN_cmp(r_simple,r_recp) != 0) { if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nsimple and recp results differ\n"); } fprintf(stdout,"a (%3d) = ",BN_num_bits(a)); BN_print(out,a); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nb (%3d) = ",BN_num_bits(b)); BN_print(out,b); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nm (%3d) = ",BN_num_bits(m)); BN_print(out,m); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nsimple ="); BN_print(out,r_simple); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nrecp ="); BN_print(out,r_recp); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nmont ="); BN_print(out,r_mont); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\nmont_ct ="); BN_print(out,r_mont_const); if(errno==ENOMEM) { return 1; } fprintf(stdout,"\n"); return 1; } } BN_free(r_mont); BN_free(r_mont_const); BN_free(r_recp); BN_free(r_simple); BN_free(a); BN_free(b); BN_free(m); BN_CTX_free(ctx); ERR_remove_state(0); if(errno==ENOMEM) { return 1; } CRYPTO_mem_leaks(out); if(errno==ENOMEM) { return 1; } BIO_free(out); if(errno==ENOMEM) { return 1; } CRYPTO_cleanup_all_ex_data(); if(errno==ENOMEM) { return 1; } fprintf(stdout," done\n"); fprintf(stdout," Test case passed\n"); return 0; err: ERR_load_crypto_strings(); if(errno==ENOMEM) { return 1; } ERR_print_errors(out); if(errno==ENOMEM) { return 1; } #ifdef OPENSSL_SYS_NETWARE fprintf(stdout,"ERROR\n"); #endif return(1); }
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM - 2]; int ret = 0, i, ex_primes = 0, smooth = 0; RSA_PRIME_INFO *pinfo; BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); if (vrfy == NULL) goto err; if (rsa->version == RSA_ASN1_VERSION_MULTI && ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0 || ex_primes > RSA_MAX_PRIME_NUM - 2)) goto err; if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { BIGNUM *factor = BN_new(); if (factor == NULL) goto err; /* * Make sure BN_mod_inverse in Montgomery initialization uses the * BN_FLG_CONSTTIME flag */ if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME), BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock, factor, ctx)) || !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME), BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock, factor, ctx))) { BN_free(factor); goto err; } for (i = 0; i < ex_primes; i++) { pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME); if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) { BN_free(factor); goto err; } } /* * We MUST free |factor| before any further use of the prime factors */ BN_free(factor); smooth = (ex_primes == 0) && (rsa->meth->bn_mod_exp == BN_mod_exp_mont) && (BN_num_bits(rsa->q) == BN_num_bits(rsa->p)); } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx)) goto err; if (smooth) { /* * Conversion from Montgomery domain, a.k.a. Montgomery reduction, * accepts values in [0-m*2^w) range. w is m's bit width rounded up * to limb width. So that at the very least if |I| is fully reduced, * i.e. less than p*q, we can count on from-to round to perform * below modulo operations on |I|. Unlike BN_mod it's constant time. */ if (/* m1 = I moq q */ !bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx) || !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx) /* m1 = m1^dmq1 mod q */ || !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx, rsa->_method_mod_q) /* r1 = I mod p */ || !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx) || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) /* r1 = r1^dmp1 mod p */ || !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx, rsa->_method_mod_p) /* r1 = (r1 - m1) mod p */ /* * bn_mod_sub_fixed_top is not regular modular subtraction, * it can tolerate subtrahend to be larger than modulus, but * not bit-wise wider. This makes up for uncommon q>p case, * when |m1| can be larger than |rsa->p|. */ || !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p) /* r1 = r1 * iqmp mod p */ || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) || !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p, ctx) /* r0 = r1 * q + m1 */ || !bn_mul_fixed_top(r0, r1, rsa->q, ctx) || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n)) goto err; goto tail; } /* compute I mod q */ { BIGNUM *c = BN_new(); if (c == NULL) goto err; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->q, ctx)) { BN_free(c); goto err; } { BIGNUM *dmq1 = BN_new(); if (dmq1 == NULL) { BN_free(c); goto err; } BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); /* compute r1^dmq1 mod q */ if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q)) { BN_free(c); BN_free(dmq1); goto err; } /* We MUST free dmq1 before any further use of rsa->dmq1 */ BN_free(dmq1); } /* compute I mod p */ if (!BN_mod(r1, c, rsa->p, ctx)) { BN_free(c); goto err; } /* We MUST free c before any further use of I */ BN_free(c); } { BIGNUM *dmp1 = BN_new(); if (dmp1 == NULL) goto err; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); /* compute r1^dmp1 mod p */ if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p)) { BN_free(dmp1); goto err; } /* We MUST free dmp1 before any further use of rsa->dmp1 */ BN_free(dmp1); } /* * calculate m_i in multi-prime case * * TODO: * 1. squash the following two loops and calculate |m_i| there. * 2. remove cc and reuse |c|. * 3. remove |dmq1| and |dmp1| in previous block and use |di|. * * If these things are done, the code will be more readable. */ if (ex_primes > 0) { BIGNUM *di = BN_new(), *cc = BN_new(); if (cc == NULL || di == NULL) { BN_free(cc); BN_free(di); goto err; } for (i = 0; i < ex_primes; i++) { /* prepare m_i */ if ((m[i] = BN_CTX_get(ctx)) == NULL) { BN_free(cc); BN_free(di); goto err; } pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); /* prepare c and d_i */ BN_with_flags(cc, I, BN_FLG_CONSTTIME); BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME); if (!BN_mod(r1, cc, pinfo->r, ctx)) { BN_free(cc); BN_free(di); goto err; } /* compute r1 ^ d_i mod r_i */ if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) { BN_free(cc); BN_free(di); goto err; } } BN_free(cc); BN_free(di); } 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; { BIGNUM *pr1 = BN_new(); if (pr1 == NULL) goto err; BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); if (!BN_mod(r0, pr1, rsa->p, ctx)) { BN_free(pr1); goto err; } /* We MUST free pr1 before any further use of r1 */ BN_free(pr1); } /* * 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; /* add m_i to m in multi-prime case */ if (ex_primes > 0) { BIGNUM *pr2 = BN_new(); if (pr2 == NULL) goto err; for (i = 0; i < ex_primes; i++) { pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); if (!BN_sub(r1, m[i], r0)) { BN_free(pr2); goto err; } if (!BN_mul(r2, r1, pinfo->t, ctx)) { BN_free(pr2); goto err; } BN_with_flags(pr2, r2, BN_FLG_CONSTTIME); if (!BN_mod(r1, pr2, pinfo->r, ctx)) { BN_free(pr2); goto err; } if (BN_is_negative(r1)) if (!BN_add(r1, r1, pinfo->r)) { BN_free(pr2); goto err; } if (!BN_mul(r1, r1, pinfo->pp, ctx)) { BN_free(pr2); goto err; } if (!BN_add(r0, r0, r1)) { BN_free(pr2); goto err; } } BN_free(pr2); } tail: if (rsa->e && rsa->n) { if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) { if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) goto err; } else { bn_correct_top(r0); 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_is_zero(vrfy)) { bn_correct_top(r0); ret = 1; goto err; /* not actually error */ } 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 *d = BN_new(); if (d == NULL) goto err; 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)) { BN_free(d); goto err; } /* We MUST free d before any further use of rsa->d */ BN_free(d); } } /* * It's unfortunate that we have to bn_correct_top(r0). What hopefully * saves the day is that correction is highly unlike, and private key * operations are customarily performed on blinded message. Which means * that attacker won't observe correlation with chosen plaintext. * Secondly, remaining code would still handle it in same computational * time and even conceal memory access pattern around corrected top. */ bn_correct_top(r0); ret = 1; err: BN_CTX_end(ctx); return ret; }
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero(void) { BIGNUM a, p, m; BIGNUM r; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; BN_init(&m); BN_one(&m); BN_init(&a); BN_one(&a); BN_init(&p); BN_zero(&p); BN_init(&r); if (!BN_rand(&a, 1024, 0, 0)) goto err; if (!BN_mod_exp(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp", &r, &a)) failed = 1; if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a)) failed = 1; if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a)) failed = 1; if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a)) failed = 1; if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) { goto err; } if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a)) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL)) goto err; if (!BN_is_zero(&r)) { fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); fprintf(stderr, "r = "); BN_print_fp(stderr, &r); fprintf(stderr, "\n"); return 0; } ret = failed; err: BN_free(&r); BN_free(&a); BN_free(&p); BN_free(&m); BN_CTX_free(ctx); return ret; }