int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret=0; BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) goto err; bn_check_top(tmp); if (a == b) { if (!BN_sqr(tmp,a,ctx)) goto err; } else { if (!BN_mul(tmp,a,b,ctx)) goto err; } /* reduce from aRR to aR */ if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; bn_check_top(r); ret=1; err: BN_CTX_end(ctx); return(ret); }
// 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_field_decode(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_decode, EC_R_NOT_INITIALIZED); return 0; } return BN_from_montgomery(r, a, group->field_data1, ctx); }
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { if (group->field_data1 == NULL) { ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); return 0; } return BN_from_montgomery(r, a, group->field_data1, ctx); }
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret = 0; int num = mont->N.top; #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) if (num > 1 && a->top == num && b->top == num) { if (bn_wexpand(r, num) == NULL) return (0); if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { r->neg = a->neg ^ b->neg; r->top = num; r->flags |= BN_FLG_FIXED_TOP; return (1); } } #endif if ((a->top + b->top) > 2 * num) return 0; BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) goto err; bn_check_top(tmp); if (a == b) { if (!BN_sqr(tmp, a, ctx)) goto err; } else { if (!BN_mul(tmp, a, b, ctx)) goto err; } /* reduce from aRR to aR */ #ifdef MONT_WORD if (!bn_from_montgomery_word(r, tmp, mont)) goto err; #else if (!BN_from_montgomery(r, tmp, mont, ctx)) goto err; #endif ret = 1; err: BN_CTX_end(ctx); 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 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); }
static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { if (EC_POINT_is_at_infinity(group, point)) { OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); return 0; } BN_CTX *new_ctx = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } int ret = 0; BN_CTX_start(ctx); if (BN_cmp(&point->Z, &group->one) == 0) { /* |point| is already affine. */ if (x != NULL && !BN_from_montgomery(x, &point->X, &group->mont, ctx)) { goto err; } if (y != NULL && !BN_from_montgomery(y, &point->Y, &group->mont, ctx)) { goto err; } } else { /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ BIGNUM *Z_1 = BN_CTX_get(ctx); BIGNUM *Z_2 = BN_CTX_get(ctx); BIGNUM *Z_3 = BN_CTX_get(ctx); if (Z_1 == NULL || Z_2 == NULL || Z_3 == NULL) { goto err; } /* The straightforward way to calculate the inverse of a Montgomery-encoded * value where the result is Montgomery-encoded is: * * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|. * * This is equivalent, but more efficient, because |BN_from_montgomery| * is more efficient (at least in theory) than |BN_to_montgomery|, since it * doesn't have to do the multiplication before the reduction. */ if (!BN_from_montgomery(Z_1, &point->Z, &group->mont, ctx) || !BN_from_montgomery(Z_1, Z_1, &group->mont, ctx) || !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) { goto err; } if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, &group->mont, ctx)) { goto err; } /* Instead of using |BN_from_montgomery| to convert the |x| coordinate * and then calling |BN_from_montgomery| again to convert the |y| * coordinate below, convert the common factor |Z_2| once now, saving one * reduction. */ if (!BN_from_montgomery(Z_2, Z_2, &group->mont, ctx)) { goto err; } if (x != NULL) { if (!BN_mod_mul_montgomery(x, &point->X, Z_2, &group->mont, ctx)) { goto err; } } if (y != NULL) { if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, &group->mont, ctx) || !BN_mod_mul_montgomery(y, &point->Y, Z_3, &group->mont, ctx)) { goto err; } } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { return BN_from_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); }