// mod_montgomery sets |r| to |I| mod |p|. |I| must already be fully reduced // modulo |p| times |q|. It returns one on success and zero on error. static int mod_montgomery(BIGNUM *r, const BIGNUM *I, const BIGNUM *p, const BN_MONT_CTX *mont_p, const BIGNUM *q, BN_CTX *ctx) { // Reducing in constant-time with Montgomery reduction requires I <= p * R. We // have I < p * q, so this follows if q < R. In particular, this always holds // if p and q are the same size, which is true for any RSA keys we or anyone // sane generates. For other keys, we fall back to |BN_mod|. if (!bn_less_than_montgomery_R(q, mont_p)) { return BN_mod(r, I, p, ctx); } if (// Reduce mod p with Montgomery reduction. This computes I * R^-1 mod p. !BN_from_montgomery(r, I, mont_p, ctx) || // Multiply by R^2 and do another Montgomery reduction to compute // I * R^-1 * R^2 * R^-1 = I mod p. !BN_to_montgomery(r, r, mont_p, ctx)) { return 0; } // By precomputing R^3 mod p (normally |BN_MONT_CTX| only uses R^2 mod p) and // adjusting the API for |BN_mod_exp_mont_consttime|, we could instead compute // I * R mod p here and save a reduction per prime. But this would require // changing the RSAZ code and may not be worth it. Note that the RSAZ code // uses a different radix, so it uses R' = 2^1044. There we'd actually want // R^2 * R', and would futher benefit from a precomputed R'^2. It currently // converts |mont_p->RR| to R'^2. return 1; }
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BN_MONT_CTX *mont = NULL; BIGNUM *one = NULL; int ret = 0; if (group->field_data1 != NULL) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; } if (group->field_data2 != NULL) { BN_free(group->field_data2); group->field_data2 = NULL; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, p, ctx)) { ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); goto err; } one = BN_new(); if (one == NULL) goto err; if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err; group->field_data1 = mont; mont = NULL; group->field_data2 = one; one = NULL; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; BN_free(group->field_data2); group->field_data2 = NULL; } err: if (new_ctx != NULL) BN_CTX_free(new_ctx); if (mont != NULL) BN_MONT_CTX_free(mont); if (one != NULL) BN_free(one); return ret; }
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { if (group->field_data1 == NULL) { OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_encode, EC_R_NOT_INITIALIZED); return 0; } return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); }
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { if (group->field_data1 == NULL) { ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); return 0; } return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); }
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BN_MONT_CTX *mont = NULL; BIGNUM *one = NULL; int ret = 0; BN_MONT_CTX_free(group->mont); group->mont = NULL; BN_free(group->one); group->one = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } mont = BN_MONT_CTX_new(); if (mont == NULL) { goto err; } if (!BN_MONT_CTX_set(mont, p, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } one = BN_new(); if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) { goto err; } group->mont = mont; mont = NULL; group->one = one; one = NULL; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { BN_MONT_CTX_free(group->mont); group->mont = NULL; BN_free(group->one); group->one = NULL; } err: BN_CTX_free(new_ctx); BN_MONT_CTX_free(mont); BN_free(one); return ret; }
static int bn_blinding_create_param(BN_BLINDING *b, const RSA *rsa, BN_CTX *ctx) { int retry_counter = 32; do { if (!BN_rand_range(b->A, rsa->n)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } /* `BN_from_montgomery` + `BN_mod_inverse_no_branch` is equivalent to, but * more efficient than, `BN_mod_inverse_no_branch` + `BN_to_montgomery`. */ if (!BN_from_montgomery(b->Ai, b->A, rsa->mont_n, ctx)) { return 0; } assert(BN_get_flags(b->A, BN_FLG_CONSTTIME)); int no_inverse; if (BN_mod_inverse_no_branch(b->Ai, &no_inverse, b->Ai, rsa->n, ctx) == NULL) { /* this should almost never happen for good RSA keys */ if (no_inverse) { if (retry_counter-- == 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); return 0; } ERR_clear_error(); } else { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } } else { break; } } while (1); if (!BN_mod_exp_mont(b->A, b->A, rsa->e, rsa->n, ctx, rsa->mont_n)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } if (!BN_to_montgomery(b->A, b->A, rsa->mont_n, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int BN_reduce_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mod_mont, BN_CTX *ctx) { BIGNUM tmp; BN_init(&tmp); if (!BN_copy(&tmp, a)) { OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); return 0; } int ret = 0; if (!BN_from_montgomery_word(r, &tmp, mod_mont) || !BN_to_montgomery(r, r, mod_mont, ctx)) { goto err; } ret = 1; err: BN_free(&tmp); return ret; }
// freeze_private_key finishes initializing |rsa|'s private key components. // After this function has returned, |rsa| may not be changed. This is needed // because |RSA| is a public struct and, additionally, OpenSSL 1.1.0 opaquified // it wrong (see https://github.com/openssl/openssl/issues/5158). static int freeze_private_key(RSA *rsa, BN_CTX *ctx) { CRYPTO_MUTEX_lock_read(&rsa->lock); int frozen = rsa->private_key_frozen; CRYPTO_MUTEX_unlock_read(&rsa->lock); if (frozen) { return 1; } int ret = 0; CRYPTO_MUTEX_lock_write(&rsa->lock); if (rsa->private_key_frozen) { ret = 1; goto err; } // Pre-compute various intermediate values, as well as copies of private // exponents with correct widths. Note that other threads may concurrently // read from |rsa->n|, |rsa->e|, etc., so any fixes must be in separate // copies. We use |mont_n->N|, |mont_p->N|, and |mont_q->N| as copies of |n|, // |p|, and |q| with the correct minimal widths. if (rsa->mont_n == NULL) { rsa->mont_n = BN_MONT_CTX_new_for_modulus(rsa->n, ctx); if (rsa->mont_n == NULL) { goto err; } } const BIGNUM *n_fixed = &rsa->mont_n->N; // The only public upper-bound of |rsa->d| is the bit length of |rsa->n|. The // ASN.1 serialization of RSA private keys unfortunately leaks the byte length // of |rsa->d|, but normalize it so we only leak it once, rather than per // operation. if (rsa->d != NULL && !ensure_fixed_copy(&rsa->d_fixed, rsa->d, n_fixed->width)) { goto err; } if (rsa->p != NULL && rsa->q != NULL) { if (rsa->mont_p == NULL) { rsa->mont_p = BN_MONT_CTX_new_for_modulus(rsa->p, ctx); if (rsa->mont_p == NULL) { goto err; } } const BIGNUM *p_fixed = &rsa->mont_p->N; if (rsa->mont_q == NULL) { rsa->mont_q = BN_MONT_CTX_new_for_modulus(rsa->q, ctx); if (rsa->mont_q == NULL) { goto err; } } const BIGNUM *q_fixed = &rsa->mont_q->N; if (rsa->dmp1 != NULL && rsa->dmq1 != NULL) { // Key generation relies on this function to compute |iqmp|. if (rsa->iqmp == NULL) { BIGNUM *iqmp = BN_new(); if (iqmp == NULL || !bn_mod_inverse_secret_prime(iqmp, rsa->q, rsa->p, ctx, rsa->mont_p)) { BN_free(iqmp); goto err; } rsa->iqmp = iqmp; } // CRT components are only publicly bounded by their corresponding // moduli's bit lengths. |rsa->iqmp| is unused outside of this one-time // setup, so we do not compute a fixed-width version of it. if (!ensure_fixed_copy(&rsa->dmp1_fixed, rsa->dmp1, p_fixed->width) || !ensure_fixed_copy(&rsa->dmq1_fixed, rsa->dmq1, q_fixed->width)) { goto err; } // Compute |inv_small_mod_large_mont|. Note that it is always modulo the // larger prime, independent of what is stored in |rsa->iqmp|. if (rsa->inv_small_mod_large_mont == NULL) { BIGNUM *inv_small_mod_large_mont = BN_new(); int ok; if (BN_cmp(rsa->p, rsa->q) < 0) { ok = inv_small_mod_large_mont != NULL && bn_mod_inverse_secret_prime(inv_small_mod_large_mont, rsa->p, rsa->q, ctx, rsa->mont_q) && BN_to_montgomery(inv_small_mod_large_mont, inv_small_mod_large_mont, rsa->mont_q, ctx); } else { ok = inv_small_mod_large_mont != NULL && BN_to_montgomery(inv_small_mod_large_mont, rsa->iqmp, rsa->mont_p, ctx); } if (!ok) { BN_free(inv_small_mod_large_mont); goto err; } rsa->inv_small_mod_large_mont = inv_small_mod_large_mont; } } } rsa->private_key_frozen = 1; ret = 1; err: CRYPTO_MUTEX_unlock_write(&rsa->lock); return ret; }
int test_mont(BIO *bp, BN_CTX *ctx) { BIGNUM a,b,c,d,A,B; BIGNUM n; int i; BN_MONT_CTX *mont; BN_init(&a); BN_init(&b); BN_init(&c); BN_init(&d); BN_init(&A); BN_init(&B); BN_init(&n); mont=BN_MONT_CTX_new(); BN_bntest_rand(&a,100,0,0); /**/ BN_bntest_rand(&b,100,0,0); /**/ for (i=0; i<num2; i++) { int bits = (200*(i+1))/num2; if (bits == 0) continue; BN_bntest_rand(&n,bits,0,1); BN_MONT_CTX_set(mont,&n,ctx); BN_nnmod(&a,&a,&n,ctx); BN_nnmod(&b,&b,&n,ctx); BN_to_montgomery(&A,&a,mont,ctx); BN_to_montgomery(&B,&b,mont,ctx); BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/ BN_from_montgomery(&A,&c,mont,ctx);/**/ if (bp != NULL) { if (!results) { #ifdef undef fprintf(stderr,"%d * %d %% %d\n", BN_num_bits(&a), BN_num_bits(&b), BN_num_bits(mont->N)); #endif BN_print(bp,&a); BIO_puts(bp," * "); BN_print(bp,&b); BIO_puts(bp," % "); BN_print(bp,&(mont->N)); BIO_puts(bp," - "); } BN_print(bp,&A); BIO_puts(bp,"\n"); } BN_mod_mul(&d,&a,&b,&n,ctx); BN_sub(&d,&d,&A); if(!BN_is_zero(&d)) { fprintf(stderr,"Montgomery multiplication test failed!\n"); return 0; } } BN_MONT_CTX_free(mont); BN_free(&a); BN_free(&b); BN_free(&c); BN_free(&d); BN_free(&A); BN_free(&B); BN_free(&n); return(1); }
// freeze_private_key finishes initializing |rsa|'s private key components. // After this function has returned, |rsa| may not be changed. This is needed // because |RSA| is a public struct and, additionally, OpenSSL 1.1.0 opaquified // it wrong (see https://github.com/openssl/openssl/issues/5158). static int freeze_private_key(RSA *rsa, BN_CTX *ctx) { CRYPTO_MUTEX_lock_read(&rsa->lock); int flags = rsa->flags; CRYPTO_MUTEX_unlock_read(&rsa->lock); if (flags & RSA_FLAG_PRIVATE_KEY_FROZEN) { return 1; } int ret = 0; CRYPTO_MUTEX_lock_write(&rsa->lock); if (rsa->flags & RSA_FLAG_PRIVATE_KEY_FROZEN) { ret = 1; goto err; } // |rsa->n| is public. Normalize the width. bn_set_minimal_width(rsa->n); if (rsa->mont_n == NULL) { rsa->mont_n = BN_MONT_CTX_new_for_modulus(rsa->n, ctx); if (rsa->mont_n == NULL) { goto err; } } // The only public upper-bound of |rsa->d| is the bit length of |rsa->n|. The // ASN.1 serialization of RSA private keys unfortunately leaks the byte length // of |rsa->d|, but normalize it so we only leak it once, rather than per // operation. if (rsa->d != NULL && !bn_resize_words(rsa->d, rsa->n->width)) { goto err; } if (rsa->p != NULL && rsa->q != NULL) { // |p| and |q| have public bit lengths. bn_set_minimal_width(rsa->p); bn_set_minimal_width(rsa->q); if (rsa->mont_p == NULL) { rsa->mont_p = BN_MONT_CTX_new_for_modulus(rsa->p, ctx); if (rsa->mont_p == NULL) { goto err; } } if (rsa->mont_q == NULL) { rsa->mont_q = BN_MONT_CTX_new_for_modulus(rsa->q, ctx); if (rsa->mont_q == NULL) { goto err; } } if (rsa->dmp1 != NULL && rsa->dmq1 != NULL) { // Key generation relies on this function to compute |iqmp|. if (rsa->iqmp == NULL) { BIGNUM *iqmp = BN_new(); if (iqmp == NULL || !bn_mod_inverse_secret_prime(iqmp, rsa->q, rsa->p, ctx, rsa->mont_p)) { BN_free(iqmp); goto err; } rsa->iqmp = iqmp; } // CRT components are only publicly bounded by their corresponding // moduli's bit lengths. if (!bn_resize_words(rsa->dmp1, rsa->p->width) || !bn_resize_words(rsa->dmq1, rsa->q->width) || !bn_resize_words(rsa->iqmp, rsa->p->width)) { goto err; } // Compute |inv_small_mod_large_mont|. Note that it is always modulo the // larger prime, independent of what is stored in |rsa->iqmp|. if (rsa->inv_small_mod_large_mont == NULL) { BIGNUM *inv_small_mod_large_mont = BN_new(); int ok; if (BN_cmp(rsa->p, rsa->q) < 0) { ok = inv_small_mod_large_mont != NULL && bn_mod_inverse_secret_prime(inv_small_mod_large_mont, rsa->p, rsa->q, ctx, rsa->mont_q) && BN_to_montgomery(inv_small_mod_large_mont, inv_small_mod_large_mont, rsa->mont_q, ctx); } else { ok = inv_small_mod_large_mont != NULL && BN_to_montgomery(inv_small_mod_large_mont, rsa->iqmp, rsa->mont_p, ctx); } if (!ok) { BN_free(inv_small_mod_large_mont); goto err; } rsa->inv_small_mod_large_mont = inv_small_mod_large_mont; } } } rsa->flags |= RSA_FLAG_PRIVATE_KEY_FROZEN; ret = 1; err: CRYPTO_MUTEX_unlock_write(&rsa->lock); return ret; }
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { return BN_to_montgomery(r, a, &group->mont, ctx); }
int BN_mod_exp2_mont(BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) { int i,j,k,bits,bits1,bits2,ret=0,wstart,wend,window,xvalue,yvalue; int start=1,ts=0,x,y; BIGNUM *d,*aa1,*aa2,*r; BIGNUM val[EXP2_TABLE_SIZE][EXP2_TABLE_SIZE]; BN_MONT_CTX *mont=NULL; bn_check_top(a1); bn_check_top(p1); bn_check_top(a2); bn_check_top(p2); bn_check_top(m); if (!(m->d[0] & 1)) { BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); return(0); } bits1=BN_num_bits(p1); bits2=BN_num_bits(p2); if ((bits1 == 0) && (bits2 == 0)) { BN_one(rr); return(1); } BN_CTX_start(ctx); d = BN_CTX_get(ctx); r = BN_CTX_get(ctx); if (d == NULL || r == NULL) goto err; bits=(bits1 > bits2)?bits1:bits2; /* If this is not done, things will break in the montgomery * part */ if (in_mont != NULL) mont=in_mont; else { if ((mont=BN_MONT_CTX_new()) == NULL) goto err; if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; } BN_init(&(val[0][0])); BN_init(&(val[1][1])); BN_init(&(val[0][1])); BN_init(&(val[1][0])); ts=1; if (BN_ucmp(a1,m) >= 0) { BN_mod(&(val[1][0]),a1,m,ctx); aa1= &(val[1][0]); } else aa1=a1; if (BN_ucmp(a2,m) >= 0) { BN_mod(&(val[0][1]),a2,m,ctx); aa2= &(val[0][1]); } else aa2=a2; if (!BN_to_montgomery(&(val[1][0]),aa1,mont,ctx)) goto err; if (!BN_to_montgomery(&(val[0][1]),aa2,mont,ctx)) goto err; if (!BN_mod_mul_montgomery(&(val[1][1]), &(val[1][0]),&(val[0][1]),mont,ctx)) goto err; #if 0 if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */ window=1; else if (bits > 250) window=5; /* max size of window */ else if (bits >= 120) window=4; else window=3; #else window=EXP2_TABLE_BITS; #endif k=1<<window; for (x=0; x<k; x++) { if (x >= 2) { BN_init(&(val[x][0])); BN_init(&(val[x][1])); if (!BN_mod_mul_montgomery(&(val[x][0]), &(val[1][0]),&(val[x-1][0]),mont,ctx)) goto err; if (!BN_mod_mul_montgomery(&(val[x][1]), &(val[1][0]),&(val[x-1][1]),mont,ctx)) goto err; } for (y=2; y<k; y++) { BN_init(&(val[x][y])); if (!BN_mod_mul_montgomery(&(val[x][y]), &(val[x][y-1]),&(val[0][1]),mont,ctx)) goto err; } } ts=k; start=1; /* This is used to avoid multiplication etc * when there is only the value '1' in the * buffer. */ xvalue=0; /* The 'x value' of the window */ yvalue=0; /* The 'y value' of the window */ wstart=bits-1; /* The top bit of the window */ wend=0; /* The bottom bit of the window */ if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err; for (;;) { xvalue=BN_is_bit_set(p1,wstart); yvalue=BN_is_bit_set(p2,wstart); if (!(xvalue || yvalue)) { if (!start) { if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) goto err; } wstart--; if (wstart < 0) break; continue; } /* We now have wstart on a 'set' bit, we now need to work out * how bit a window to do. To do this we need to scan * forward until the last set bit before the end of the * window */ j=wstart; /* xvalue=BN_is_bit_set(p1,wstart); already set */ /* yvalue=BN_is_bit_set(p1,wstart); already set */ wend=0; for (i=1; i<window; i++) { if (wstart-i < 0) break; xvalue+=xvalue; xvalue|=BN_is_bit_set(p1,wstart-i); yvalue+=yvalue; yvalue|=BN_is_bit_set(p2,wstart-i); } /* i is the size of the current window */ /* add the 'bytes above' */ if (!start) for (j=0; j<i; j++) { if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) goto err; } /* wvalue will be an odd number < 2^window */ if (xvalue || yvalue) { if (!BN_mod_mul_montgomery(r,r,&(val[xvalue][yvalue]), mont,ctx)) goto err; } /* move the 'window' down further */ wstart-=i; start=0; if (wstart < 0) break; } BN_from_montgomery(rr,r,mont,ctx); ret=1; err: if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); BN_CTX_end(ctx); for (i=0; i<ts; i++) { for (j=0; j<ts; j++) { BN_clear_free(&(val[i][j])); } } return(ret); }