int main(int argc, char ** argv) { /* Generate 2 big random numbers (512 bits) */ primitive_p = initialize("1011011"); initialize_rand(SEED); BIGNUM *p = get_long_prime_number(RSA_KEY_LENGTH); printf("p=%s\n", BN_bn2hex(p)); BIGNUM *q = get_long_prime_number(RSA_KEY_LENGTH); printf("q=%s\n", BN_bn2hex(q)); /* Compute phi = (p-1)*(q-1) and n = p*q */ BIGNUM *phi, *n; BN_CTX *tmp; tmp = BN_CTX_new(); n = BN_new(); phi = BN_new(); BN_copy(n, p); BN_mul(n, n, q, tmp); printf("n=%s\n", BN_bn2dec(n)); BN_sub_word(p, 1); printf("p-1=%s\n", BN_bn2dec(p)); BN_sub_word(q, 1); printf("q-1=%s\n", BN_bn2dec(q)); phi = BN_new(); BN_init(tmp); BN_mul(phi, p, q, tmp); printf("(p-1)(q-1)=%s\n", BN_bn2dec(phi)); /* Find the smallest integer coprime with phi */ BIGNUM * e = BN_new(); BIGNUM *gcd = BN_new(); BN_add_word(e, 3); for ( ; ; BN_add_word(e, 2)) { tmp = BN_CTX_new(); BN_gcd(gcd, e, phi, tmp); if (BN_is_one(gcd)) break; } printf("e=%s\n", BN_bn2dec(e)); /* Find d, the inverse of e in Z_phi */ BIGNUM * d = BN_new(); BIGNUM * i = BN_new(); BIGNUM * rem = BN_new(); BIGNUM * prod = BN_new(); BN_add_word(i, 1); for ( ; ; BN_add_word(i, 1)) { BN_copy(prod, phi); tmp = BN_CTX_new(); BN_mul(prod, prod, i, tmp); BN_add_word(prod, 1); BN_div(d, rem, prod, e, tmp); if (BN_is_zero(rem)) { break; } } printf("d=%s\n", BN_bn2dec(d)); return 0; }
EVP_PKEY* CreateRsaKey(const_RsaDevice d) { BN_CTX* ctx = IntegerGroup_GetCtx(RsaParams_GetGroup(d->params)); // phi(n) = (p-1)(q-1) BIGNUM *phi_n, *pm, *qm; phi_n = BN_new(); CHECK_CALL(phi_n); CHECK_CALL(pm = BN_dup(d->p)); CHECK_CALL(qm = BN_dup(d->q)); CHECK_CALL(BN_sub_word(pm, 1)); CHECK_CALL(BN_sub_word(qm, 1)); CHECK_CALL(BN_mul(phi_n, pm, qm, ctx)); EVP_PKEY *evp = EVP_PKEY_new(); RSA *rsa = RSA_new(); CHECK_CALL(evp); CHECK_CALL(rsa); CHECK_CALL(rsa->n = BN_dup(d->n)); // public modulus CHECK_CALL(rsa->e = BN_new()); // public exponent BN_set_word(rsa->e, RsaEncryptionExponent); rsa->d = BN_new(); // private exponent CHECK_CALL(rsa->d); CHECK_CALL(BN_mod_inverse(rsa->d, rsa->e, phi_n, ctx)); CHECK_CALL(rsa->p = BN_dup(d->p)); // secret prime factor CHECK_CALL(rsa->q = BN_dup(d->q)); // secret prime factor rsa->dmp1 = BN_new(); // d mod (p-1) CHECK_CALL(rsa->dmp1); CHECK_CALL(BN_mod(rsa->dmp1, rsa->d, pm, ctx)); rsa->dmq1 = BN_new(); // d mod (q-1) CHECK_CALL(rsa->dmq1); CHECK_CALL(BN_mod(rsa->dmq1, rsa->d, qm, ctx)); rsa->iqmp = BN_new(); // q^-1 mod p CHECK_CALL(rsa->iqmp); CHECK_CALL(BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)); CHECK_CALL(EVP_PKEY_set1_RSA(evp, rsa)); ASSERT(RSA_check_key(rsa)); BN_clear_free(phi_n); BN_clear_free(pm); BN_clear_free(qm); return evp; }
// Generate each party's random numbers. xa is in [0, q), xb is in [1, q). static void genrand(JPakeUser * user, const JPakeParameters * params) { BIGNUM *qm1; // xa in [0, q) user->xa = BN_new(); BN_rand_range(user->xa, params->q); // q-1 qm1 = BN_new(); BN_copy(qm1, params->q); BN_sub_word(qm1, 1); // ... and xb in [0, q-1) user->xb = BN_new(); BN_rand_range(user->xb, qm1); // [1, q) BN_add_word(user->xb, 1); // cleanup BN_free(qm1); // Show printf("x%d", user->p.base); showbn("", user->xa); printf("x%d", user->p.base + 1); showbn("", user->xb); }
int BN_add_word(BIGNUM *a, BN_ULONG w) { BN_ULONG l; int i; if (a->neg) { a->neg=0; i=BN_sub_word(a,w); if (!BN_is_zero(a)) a->neg=!(a->neg); return(i); } w&=BN_MASK2; if (bn_wexpand(a,a->top+1) == NULL) return(0); i=0; for (;;) { l=(a->d[i]+(BN_ULONG)w)&BN_MASK2; a->d[i]=l; if (w > l) w=1; else break; i++; } if (i >= a->top) a->top++; return(1); }
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { int ok = 0; BIGNUM q; *ret = 0; BN_init(&q); if (!BN_set_word(&q, 1)) { goto err; } if (BN_cmp(pub_key, &q) <= 0) { *ret |= DH_CHECK_PUBKEY_TOO_SMALL; } if (!BN_copy(&q, dh->p) || !BN_sub_word(&q, 1)) { goto err; } if (BN_cmp(pub_key, &q) >= 0) { *ret |= DH_CHECK_PUBKEY_TOO_LARGE; } ok = 1; err: BN_free(&q); return ok; }
int BN_add_word(BIGNUM *a, BN_ULONG w) { BN_ULONG l; int i; bn_check_top(a); w &= BN_MASK2; /* degenerate case: w is zero */ if (!w) return 1; /* degenerate case: a is zero */ if(BN_is_zero(a)) return BN_set_word(a, w); /* handle 'a' when negative */ if (a->neg) { a->neg=0; i=BN_sub_word(a,w); if (!BN_is_zero(a)) a->neg=!(a->neg); return(i); } for (i=0;w!=0 && i<a->top;i++) { a->d[i] = l = (a->d[i]+w)&BN_MASK2; w = (w>l)?1:0; } if (w && i==a->top) { if (bn_wexpand(a,a->top+1) == NULL) return 0; a->top++; a->d[i]=w; } bn_check_top(a); return(1); }
int Lfast(BIGNUM *res, const BIGNUM *u, const BIGNUM *ninv, const BIGNUM *two_n, const BIGNUM *n) { BN_CTX *ctx = BN_CTX_new(); BN_copy(res, u); BN_sub_word(res, 1); BN_mod_mul(res, res, ninv, two_n, ctx); BN_mod(res, res, n, ctx); }
int gost_do_verify (const unsigned char *dgst, int dgst_len, DSA_SIG * sig, DSA * dsa) { BIGNUM *md, *tmp = NULL; BIGNUM *q2 = NULL; BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *tmp2 = NULL, *tmp3 = NULL; int ok; BN_CTX *ctx = BN_CTX_new (); BN_CTX_start (ctx); if (BN_cmp (sig->s, dsa->q) >= 1 || BN_cmp (sig->r, dsa->q) >= 1) { GOSTerr (GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); return 0; } md = hashsum2bn (dgst); tmp = BN_CTX_get (ctx); v = BN_CTX_get (ctx); q2 = BN_CTX_get (ctx); z1 = BN_CTX_get (ctx); z2 = BN_CTX_get (ctx); tmp2 = BN_CTX_get (ctx); tmp3 = BN_CTX_get (ctx); u = BN_CTX_get (ctx); BN_mod (tmp, md, dsa->q, ctx); if (BN_is_zero (tmp)) { BN_one (md); } BN_copy (q2, dsa->q); BN_sub_word (q2, 2); BN_mod_exp (v, md, q2, dsa->q, ctx); BN_mod_mul (z1, sig->s, v, dsa->q, ctx); BN_sub (tmp, dsa->q, sig->r); BN_mod_mul (z2, tmp, v, dsa->p, ctx); BN_mod_exp (tmp, dsa->g, z1, dsa->p, ctx); BN_mod_exp (tmp2, dsa->pub_key, z2, dsa->p, ctx); BN_mod_mul (tmp3, tmp, tmp2, dsa->p, ctx); BN_mod (u, tmp3, dsa->q, ctx); ok = BN_cmp (u, sig->r); BN_free (md); BN_CTX_end (ctx); BN_CTX_free (ctx); if (ok != 0) { GOSTerr (GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } return (ok == 0); }
/** https://core.telegram.org/api/end-to-end says: "Both clients in a secret chat creation are to check that g, g_a and g_b are greater than one and smaller than p-1. Recommented checking that g_a and g_b are between 2^{2048-64} and p - 2^{2048-64} as well." */ qint32 CryptoUtils::checkCalculatedParams(const BIGNUM *gAOrB, const BIGNUM *g, const BIGNUM *p) { ASSERT(gAOrB); ASSERT(g); ASSERT(p); // 1) gAOrB and g greater than one and smaller than p-1 BIGNUM one; BN_init(&one); Utils::ensure(BN_one(&one)); BIGNUM *pMinusOne = BN_dup(p); Utils::ensure(BN_sub_word(pMinusOne, 1)); // check params greater than one if (BN_cmp(gAOrB, &one) <= 0) return -1; if (BN_cmp(g, &one) <= 0) return -1; // check params <= p-1 if (BN_cmp(gAOrB, pMinusOne) >= 0) return -1; if (BN_cmp(g, pMinusOne) >= 0) return -1; // 2) gAOrB between 2^{2048-64} and p - 2^{2048-64} quint64 expWord = 2048 - 64; BIGNUM exp; BN_init(&exp); Utils::ensure(BN_set_word(&exp, expWord)); BIGNUM base; BN_init(&base); Utils::ensure(BN_set_word(&base, 2)); // lowLimit = base ^ exp BIGNUM lowLimit; BN_init(&lowLimit); Utils::ensure(BN_exp(&lowLimit, &base, &exp, BN_ctx)); // highLimit = p - lowLimit BIGNUM highLimit; BN_init(&highLimit); BN_sub(&highLimit, p, &lowLimit); if (BN_cmp(gAOrB, &lowLimit) < 0) return -1; if (BN_cmp(gAOrB, &highLimit) > 0) return -1; BN_free(&one); BN_free(pMinusOne); BN_free(&exp); BN_free(&lowLimit); BN_free(&highLimit); delete g; delete gAOrB; delete p; return 0; }
/* * prime_totient(p,q,totient) * Euler totient function of n, under the assumption * that n = pq and p and q are prime * inputs: BIGNUM* p * BIGNUM* q * output: BIGNUM* totient * * return value: 0 if failure * 1 if success */ int prime_totient(BIGNUM* p, BIGNUM* q, BIGNUM* totient){ BIGNUM one; BN_init(&one); BN_one(&one); BIGNUM* temp_p = BN_dup(p); BIGNUM* temp_q = BN_dup(q); BN_sub_word(temp_p, 1); BN_sub_word(temp_q, 1); BN_CTX* ctx = BN_CTX_new(); BN_mul(totient, temp_p, temp_q, ctx); BN_free(temp_p); BN_free(temp_q); BN_CTX_free(ctx); return 1; }
static int test_check_public_key(void) { int ret = 0; BIGNUM *n = NULL, *e = NULL; RSA *key = NULL; ret = TEST_ptr(key = RSA_new()) /* check NULL pointers fail */ && TEST_false(rsa_sp800_56b_check_public(key)) /* load public key */ && TEST_ptr(e = bn_load_new(cav_e, sizeof(cav_e))) && TEST_ptr(n = bn_load_new(cav_n, sizeof(cav_n))) && TEST_true(RSA_set0_key(key, n, e, NULL)); if (!ret) { BN_free(e); BN_free(n); goto end; } /* check public key is valid */ ret = TEST_true(rsa_sp800_56b_check_public(key)) /* check fail if n is even */ && TEST_true(BN_add_word(n, 1)) && TEST_false(rsa_sp800_56b_check_public(key)) && TEST_true(BN_sub_word(n, 1)) /* check fail if n is wrong number of bits */ && TEST_true(BN_lshift1(n, n)) && TEST_false(rsa_sp800_56b_check_public(key)) && TEST_true(BN_rshift1(n, n)) /* test odd exponent fails */ && TEST_true(BN_add_word(e, 1)) && TEST_false(rsa_sp800_56b_check_public(key)) && TEST_true(BN_sub_word(e, 1)) /* modulus fails composite check */ && TEST_true(BN_add_word(n, 2)) && TEST_false(rsa_sp800_56b_check_public(key)); end: RSA_free(key); return ret; }
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { BIGNUM Ri,*R; BN_init(&Ri); R= &(mont->RR); /* grab RR as a temp */ BN_copy(&(mont->N),mod); /* Set N */ { BIGNUM tmod; BN_ULONG buf[2]; mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; if (!(BN_zero(R))) goto err; if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ buf[0]=mod->d[0]; /* tmod = N mod word size */ buf[1]=0; tmod.d=buf; tmod.top=1; tmod.dmax=2; tmod.neg=mod->neg; /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) goto err; /* R*Ri */ if (!(BN_lshift(&Ri,&Ri,BN_BITS2))) goto err; if (!BN_is_zero(&Ri)) { if (!BN_sub_word(&Ri,1)) goto err; } else /* if N mod word size == 1 */ /* Ri-- (mod word size) */ { if (!BN_set_word(&Ri,BN_MASK2)) goto err; } /* Ni = (R*Ri-1)/N, keep only least significant word: */ if (!(BN_div(&Ri,NULL,&Ri,&tmod,ctx))) goto err; mont->n0=Ri.d[0]; BN_free(&Ri); } /* setup RR for conversions */ if (!(BN_zero(&(mont->RR)))) goto err; if (!(BN_set_bit(&(mont->RR),mont->ri*2))) goto err; if (!(BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx))) goto err; return(1); err: return(0); }
/* pollard p-1, algorithm from Jim Gillogly, May 2000 */ static void pollard_pminus1(BIGNUM *val) { BIGNUM *base, *rbase, *num, *i, *x; base = BN_new(); rbase = BN_new(); num = BN_new(); i = BN_new(); x = BN_new(); BN_set_word(rbase, 1); newbase: if (!BN_add_word(rbase, 1)) errx(1, "error in BN_add_word()"); BN_set_word(i, 2); BN_copy(base, rbase); for (;;) { BN_mod_exp(base, base, i, val, ctx); if (BN_is_one(base)) goto newbase; BN_copy(x, base); BN_sub_word(x, 1); if (!BN_gcd(x, x, val, ctx)) errx(1, "error in BN_gcd()"); if (!BN_is_one(x)) { if (BN_is_prime(x, PRIME_CHECKS, NULL, NULL, NULL) == 1) pr_print(x); else pollard_pminus1(x); fflush(stdout); BN_div(num, NULL, val, x, ctx); if (BN_is_one(num)) return; if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL, NULL) == 1) { pr_print(num); fflush(stdout); return; } BN_copy(val, num); } if (!BN_add_word(i, 1)) errx(1, "error in BN_add_word()"); } }
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { *ret = 0; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } BN_CTX_start(ctx); int ok = 0; /* Check |pub_key| is greater than 1. */ BIGNUM *tmp = BN_CTX_get(ctx); if (tmp == NULL || !BN_set_word(tmp, 1)) { goto err; } if (BN_cmp(pub_key, tmp) <= 0) { *ret |= DH_CHECK_PUBKEY_TOO_SMALL; } /* Check |pub_key| is less than |dh->p| - 1. */ if (!BN_copy(tmp, dh->p) || !BN_sub_word(tmp, 1)) { goto err; } if (BN_cmp(pub_key, tmp) >= 0) { *ret |= DH_CHECK_PUBKEY_TOO_LARGE; } if (dh->q != NULL) { /* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114 * groups which are not safe primes but pick a generator on a prime-order * subgroup of size |dh->q|. */ if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) { goto err; } if (!BN_is_one(tmp)) { *ret |= DH_CHECK_PUBKEY_INVALID; } } ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; }
// http://stackoverflow.com/questions/356090/how-to-compute-the-nth-root-of-a-very-big-integer static BIGNUM *nearest_cuberoot(BIGNUM *in) { BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); BIGNUM *three = BN_CTX_get(ctx); BIGNUM *high = BN_CTX_get(ctx); BIGNUM *mid = BN_CTX_get(ctx); BIGNUM *low = BN_CTX_get(ctx); BIGNUM *tmp = BN_CTX_get(ctx); BN_set_word(three, 3); // Create the constant 3 BN_set_word(high, 1); // high = 1 do { BN_lshift1(high, high); // high = high << 1 (high * 2) BN_exp(tmp, high, three, ctx); // tmp = high^3 } while (BN_ucmp(tmp, in) <= -1); // while (tmp < in) BN_rshift1(low, high); // low = high >> 1 (high / 2) while (BN_ucmp(low, high) <= -1) // while (low < high) { BN_add(tmp, low, high); // tmp = low + high BN_rshift1(mid, tmp); // mid = tmp >> 1 (tmp / 2) BN_exp(tmp, mid, three, ctx); // tmp = mid^3 if (BN_ucmp(low, mid) <= -1 && BN_ucmp(tmp, in) <= -1) // if (low < mid && tmp < in) BN_copy(low, mid); // low = mid else if (BN_ucmp(high, mid) >= 1 && BN_ucmp(tmp, in) >= 1) // else if (high > mid && tmp > in) BN_copy(high, mid); // high = mid else { // subtract 1 from mid because 1 will be added after the loop BN_sub_word(mid, 1); // mid -= 1 break; } } BN_add_word(mid, 1); // mid += 1 BIGNUM *result = BN_dup(mid); BN_CTX_end(ctx); BN_CTX_free(ctx); return result; }
int BN_add_word(BIGNUM *a, BN_ULONG w) { BN_ULONG l; int i; bn_check_top(a); w &= BN_MASK2; /* degenerate case: w is zero */ if (!w) return 1; /* degenerate case: a is zero */ if(BN_is_zero(a)) return BN_set_word(a, w); /* handle 'a' when negative */ if (a->neg) { a->neg=0; i=BN_sub_word(a,w); if (!BN_is_zero(a)) a->neg=!(a->neg); return(i); } /* Only expand (and risk failing) if it's possibly necessary */ if (((BN_ULONG)(a->d[a->top - 1] + 1) == 0) && (bn_wexpand(a,a->top+1) == NULL)) return(0); i=0; for (;;) { if (i >= a->top) l=w; else l=(a->d[i]+w)&BN_MASK2; a->d[i]=l; if (w > l) w=1; else break; i++; } if (i >= a->top) a->top++; bn_check_top(a); return(1); }
BIGNUM * DH_get_q(const DH *dh, BN_CTX *ctx) { BIGNUM *q_new = NULL, *bn = NULL; int i; const BIGNUM *p, *q; check(dh, "Invalid arguments"); DH_get0_pqg(dh, &p, &q, NULL); if (!q) { q_new = BN_new(); bn = BN_dup(p); /* DH primes should be strong, based on a Sophie Germain prime q * p=(2*q)+1 or (p-1)/2=q */ if (!q_new || !bn || !BN_sub_word(bn, 1) || !BN_rshift1(q_new, bn)) { goto err; } } else { q_new = BN_dup(q); } /* q should always be prime */ i = BN_is_prime_ex(q_new, BN_prime_checks, ctx, NULL); if (i <= 0) { if (i == 0) log_err("Unable to get Sophie Germain prime"); goto err; } return q_new; err: if (bn) BN_clear_free(bn); if (q_new) BN_clear_free(q_new); return NULL; }
/* Generate each party's random numbers. xa is in [0, q), xb is in [1, q). */ static void genrand(JPAKE_CTX *ctx) { BIGNUM *qm1; /* xa in [0, q) */ BN_rand_range(ctx->xa, ctx->p.q); /* q-1 */ qm1 = BN_new(); BN_copy(qm1, ctx->p.q); BN_sub_word(qm1, 1); /* ... and xb in [0, q-1) */ BN_rand_range(ctx->xb, qm1); /* [1, q) */ BN_add_word(ctx->xb, 1); /* cleanup */ BN_free(qm1); }
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { BIGNUM *q = NULL; *ret = 0; q = BN_new(); if (q == NULL) return 0; BN_set_word(q, 1); if (BN_cmp(pub_key, q) <= 0) *ret |= DH_CHECK_PUBKEY_TOO_SMALL; BN_copy(q, dh->p); BN_sub_word(q, 1); if (BN_cmp(pub_key, q) >= 0) *ret |= DH_CHECK_PUBKEY_TOO_LARGE; BN_free(q); return 1; }
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { int ok=0; BIGNUM *q=NULL; *ret=0; q=BN_new(); if (q == NULL) goto err; BN_set_word(q,1); if (BN_cmp(pub_key,q) <= 0) *ret|=DH_CHECK_PUBKEY_TOO_SMALL; BN_copy(q,dh->p); BN_sub_word(q,1); if (BN_cmp(pub_key,q) >= 0) *ret|=DH_CHECK_PUBKEY_TOO_LARGE; ok = 1; err: if (q != NULL) BN_free(q); return(ok); }
// For key generation static int L(BIGNUM *res, const BIGNUM *u, const BIGNUM *n, BN_CTX *ctx) { int ret = 1; BIGNUM *u_cp = BN_dup(u); if (!BN_sub_word(u_cp, 1)) goto end; if (!BN_div(res, NULL, u_cp, n, ctx)) goto end; ret = 0; end: if (ret) { ERR_load_crypto_strings(); fprintf(stderr, "Error calculating L: %s", ERR_error_string(ERR_get_error(), NULL)); } BN_free(u_cp); return ret; }
int BN_add_word(BIGNUM *a, BN_ULONG w) { BN_ULONG l; int i; // degenerate case: w is zero if (!w) { return 1; } // degenerate case: a is zero if (BN_is_zero(a)) { return BN_set_word(a, w); } // handle 'a' when negative if (a->neg) { a->neg = 0; i = BN_sub_word(a, w); if (!BN_is_zero(a)) { a->neg = !(a->neg); } return i; } for (i = 0; w != 0 && i < a->width; i++) { a->d[i] = l = a->d[i] + w; w = (w > l) ? 1 : 0; } if (w && i == a->width) { if (!bn_wexpand(a, a->width + 1)) { return 0; } a->width++; a->d[i] = w; } return 1; }
BIGNUM * DH_get_order(const DH *dh, BN_CTX *ctx) { BIGNUM *order = NULL, *bn = NULL; const BIGNUM *p, *g; check(dh && ctx, "Invalid argument"); BN_CTX_start(ctx); DH_get0_pqg(dh, &p, NULL, &g); /* suppose the order of g is q-1 */ order = DH_get_q(dh, ctx); bn = BN_CTX_get(ctx); if (!bn || !order || !BN_sub_word(order, 1) || !BN_mod_exp(bn, g, order, p, ctx)) goto err; if (BN_cmp(bn, BN_value_one()) != 0) { /* if bn != 1, then q-1 is not the order of g, but p-1 should be */ if (!BN_sub(order, p, BN_value_one()) || !BN_mod_exp(bn, g, order, p, ctx)) goto err; check(BN_cmp(bn, BN_value_one()) == 0, "Unable to get order"); } BN_CTX_end(ctx); return order; err: if (order) BN_clear_free(order); BN_CTX_end(ctx); return NULL; }
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { int ok = 0; BIGNUM *tmp = NULL; BN_CTX *ctx = NULL; *ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL || !BN_set_word(tmp, 1)) goto err; if (BN_cmp(pub_key, tmp) <= 0) *ret |= DH_CHECK_PUBKEY_TOO_SMALL; if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) goto err; if (BN_cmp(pub_key, tmp) >= 0) *ret |= DH_CHECK_PUBKEY_TOO_LARGE; if (dh->q != NULL) { /* Check pub_key^q == 1 mod p */ if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) goto err; if (!BN_is_one(tmp)) *ret |= DH_CHECK_PUBKEY_INVALID; } ok = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return (ok); }
int BN_is_prime_fasttest(const BIGNUM *a, int checks, void (*callback)(int,int,void *), BN_CTX *ctx_passed, void *cb_arg, int do_trial_division) { int i, j, ret = -1; int k; BN_CTX *ctx = NULL; BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ BN_MONT_CTX *mont = NULL; const BIGNUM *A = NULL; if (BN_cmp(a, BN_value_one()) <= 0) return 0; if (checks == BN_prime_checks) checks = BN_prime_checks_for_size(BN_num_bits(a)); /* first look for small factors */ if (!BN_is_odd(a)) return 0; if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) if (BN_mod_word(a, primes[i]) == 0) return 0; if (callback != NULL) callback(1, -1, cb_arg); } if (ctx_passed != NULL) ctx = ctx_passed; else if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); /* A := abs(a) */ if (a->neg) { BIGNUM *t; if ((t = BN_CTX_get(ctx)) == NULL) goto err; BN_copy(t, a); t->neg = 0; A = t; } else A = a; A1 = BN_CTX_get(ctx); A1_odd = BN_CTX_get(ctx); check = BN_CTX_get(ctx); if (check == NULL) goto err; /* compute A1 := A - 1 */ if (!BN_copy(A1, A)) goto err; if (!BN_sub_word(A1, 1)) goto err; if (BN_is_zero(A1)) { ret = 0; goto err; } /* write A1 as A1_odd * 2^k */ k = 1; while (!BN_is_bit_set(A1, k)) k++; if (!BN_rshift(A1_odd, A1, k)) goto err; /* Montgomery setup for computations mod A */ mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, A, ctx)) goto err; for (i = 0; i < checks; i++) { if (!BN_pseudo_rand_range(check, A1)) goto err; if (!BN_add_word(check, 1)) goto err; /* now 1 <= check < A */ j = witness(check, A, A1, A1_odd, k, ctx, mont); if (j == -1) goto err; if (j) { ret=0; goto err; } if (callback != NULL) callback(1,i,cb_arg); } ret=1; err: if (ctx != NULL) { BN_CTX_end(ctx); if (ctx_passed == NULL) BN_CTX_free(ctx); } if (mont != NULL) BN_MONT_CTX_free(mont); return(ret); }
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { int ret = 0; BIGNUM *Ri, *R; BN_CTX_start(ctx); if ((Ri = BN_CTX_get(ctx)) == NULL) goto err; R = &(mont->RR); /* grab RR as a temp */ if (!BN_copy(&(mont->N), mod)) goto err; /* Set N */ mont->N.neg = 0; #ifdef MONT_WORD { BIGNUM tmod; BN_ULONG buf[2]; BN_init(&tmod); tmod.d = buf; tmod.dmax = 2; tmod.neg = 0; mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) /* Only certain BN_BITS2<=32 platforms actually make use of * n0[1], and we could use the #else case (with a shorter R * value) for the others. However, currently only the assembler * files do know which is which. */ BN_zero(R); if (!(BN_set_bit(R, 2 * BN_BITS2))) goto err; tmod.top = 0; if ((buf[0] = mod->d[0])) tmod.top = 1; if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) tmod.top = 2; if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL) goto err; if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) goto err; /* R*Ri */ if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri, 1)) goto err; } else /* if N mod word size == 1 */ { if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) goto err; /* Ri-- (mod double word size) */ Ri->neg = 0; Ri->d[0] = BN_MASK2; Ri->d[1] = BN_MASK2; Ri->top = 2; } if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only couple of least significant words: */ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; #else BN_zero(R); if (!(BN_set_bit(R, BN_BITS2))) goto err; /* R */ buf[0] = mod->d[0]; /* tmod = N mod word size */ buf[1] = 0; tmod.top = buf[0] != 0 ? 1 : 0; /* Ri = R^-1 mod N*/ if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL) goto err; if (!BN_lshift(Ri, Ri, BN_BITS2)) goto err; /* R*Ri */ if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri, 1)) goto err; } else /* if N mod word size == 1 */ { if (!BN_set_word(Ri, BN_MASK2)) goto err; /* Ri-- (mod word size) */ } if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only least significant word: */ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; mont->n0[1] = 0; #endif } #else /* !MONT_WORD */ { /* bignum version */ mont->ri = BN_num_bits(&mont->N); BN_zero(R); if (!BN_set_bit(R, mont->ri)) goto err; /* R = 2^ri */ /* Ri = R^-1 mod N*/ if ((BN_mod_inverse_ct(Ri, R, &mont->N, ctx)) == NULL) goto err; if (!BN_lshift(Ri, Ri, mont->ri)) goto err; /* R*Ri */ if (!BN_sub_word(Ri, 1)) goto err; /* Ni = (R*Ri-1) / N */ if (!BN_div_ct(&(mont->Ni), NULL, Ri, &mont->N, ctx)) goto err; } #endif /* setup RR for conversions */ BN_zero(&(mont->RR)); if (!BN_set_bit(&(mont->RR), mont->ri*2)) goto err; if (!BN_mod_ct(&(mont->RR), &(mont->RR), &(mont->N), ctx)) goto err; ret = 1; err: BN_CTX_end(ctx); return ret; }
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) /* Returns 'ret' such that * ret^2 == a (mod p), * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course * in Algebraic Computational Number Theory", algorithm 1.5.1). * 'p' must be prime! */ { BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); return(NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto end; if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; /* A = a mod p */ if (!BN_nnmod(A, a, p, ctx)) goto end; /* now write |p| - 1 as 2^e*q where q is odd */ e = 1; while (!BN_is_bit_set(p, e)) e++; /* we'll set q later (if needed) */ if (e == 1) { /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse * modulo (|p|-1)/2, and square roots can be computed * directly by modular exponentiation. * We have * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. */ if (!BN_rshift(q, p, 2)) goto end; q->neg = 0; if (!BN_add_word(q, 1)) goto end; if (!BN_mod_exp(ret, A, q, p, ctx)) goto end; err = 0; goto vrfy; } if (e == 2) { /* |p| == 5 (mod 8) * * In this case 2 is always a non-square since * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. * So if a really is a square, then 2*a is a non-square. * Thus for * b := (2*a)^((|p|-5)/8), * i := (2*a)*b^2 * we have * i^2 = (2*a)^((1 + (|p|-5)/4)*2) * = (2*a)^((p-1)/2) * = -1; * so if we set * x := a*b*(i-1), * then * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) * = a^2 * b^2 * (-2*i) * = a*(-i)*(2*a*b^2) * = a*(-i)*i * = a. * * (This is due to A.O.L. Atkin, * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, * November 1992.) */ /* t := 2*a */ if (!BN_mod_lshift1_quick(t, A, p)) goto end; /* b := (2*a)^((|p|-5)/8) */ if (!BN_rshift(q, p, 3)) goto end; q->neg = 0; if (!BN_mod_exp(b, t, q, p, ctx)) goto end; /* y := b^2 */ if (!BN_mod_sqr(y, b, p, ctx)) goto end; /* t := (2*a)*b^2 - 1*/ if (!BN_mod_mul(t, t, y, p, ctx)) goto end; if (!BN_sub_word(t, 1)) goto end; /* x = a*b*t */ if (!BN_mod_mul(x, A, b, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* e > 2, so we really have to use the Tonelli/Shanks algorithm. * First, find some y that is not a square. */ if (!BN_copy(q, p)) goto end; /* use 'q' as temp */ q->neg = 0; i = 2; do { /* For efficiency, try small numbers first; * if this fails, try random numbers. */ if (i < 22) { if (!BN_set_word(y, i)) goto end; } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end; if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end; } /* now 0 <= y < |p| */ if (BN_is_zero(y)) if (!BN_set_word(y, i)) goto end; } r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ if (r < -1) goto end; if (r == 0) { /* m divides p */ BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { /* Many rounds and still no non-square -- this is more likely * a bug than just bad luck. * Even if p is not prime, we should have found some y * such that r == -1. */ BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); goto end; } /* Here's our actual 'q': */ if (!BN_rshift(q, q, e)) goto end; /* Now that we have some non-square, we can find an element * of order 2^e by computing its q'th power. */ if (!BN_mod_exp(y, y, q, p, ctx)) goto end; if (BN_is_one(y)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } /* Now we know that (if p is indeed prime) there is an integer * k, 0 <= k < 2^e, such that * * a^q * y^k == 1 (mod p). * * As a^q is a square and y is not, k must be even. * q+1 is even, too, so there is an element * * X := a^((q+1)/2) * y^(k/2), * * and it satisfies * * X^2 = a^q * a * y^k * = a, * * so it is the square root that we are looking for. */ /* t := (q-1)/2 (note that q is odd) */ if (!BN_rshift1(t, q)) goto end; /* x := a^((q-1)/2) */ if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ { if (!BN_nnmod(t, A, p, ctx)) goto end; if (BN_is_zero(t)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) goto end; } else { if (!BN_mod_exp(x, A, t, p, ctx)) goto end; if (BN_is_zero(x)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } } /* b := a*x^2 (= a^q) */ if (!BN_mod_sqr(b, x, p, ctx)) goto end; if (!BN_mod_mul(b, b, A, p, ctx)) goto end; /* x := a*x (= a^((q+1)/2)) */ if (!BN_mod_mul(x, x, A, p, ctx)) goto end; while (1) { /* Now b is a^q * y^k for some even k (0 <= k < 2^E * where E refers to the original value of e, which we * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). * * We have a*b = x^2, * y^2^(e-1) = -1, * b^2^(e-1) = 1. */ if (BN_is_one(b)) { if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* find smallest i such that b^(2^i) = 1 */ i = 1; if (!BN_mod_sqr(t, b, p, ctx)) goto end; while (!BN_is_one(t)) { i++; if (i == e) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) goto end; } /* t := y^2^(e - i - 1) */ if (!BN_copy(t, y)) goto end; for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) goto end; } if (!BN_mod_mul(y, t, t, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_mod_mul(b, b, y, p, ctx)) goto end; e = i; } vrfy: if (!err) { /* verify the result -- the input might have been not a square * (test added in 0.9.8) */ if (!BN_mod_sqr(x, ret, p, ctx)) err = 1; if (!err && 0 != BN_cmp(x, A)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != NULL && ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); bn_check_top(ret); return ret; }
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb) { int ret = 0; BIGNUM *t, *p1p2, *pm1; /* Only even e supported */ if (!BN_is_odd(e)) return 0; BN_CTX_start(ctx); if (p1 == NULL) { if ((p1 = BN_CTX_get(ctx)) == NULL) goto err; } if (p2 == NULL) { if ((p2 = BN_CTX_get(ctx)) == NULL) goto err; } if ((t = BN_CTX_get(ctx)) == NULL) goto err; if ((p1p2 = BN_CTX_get(ctx)) == NULL) goto err; if ((pm1 = BN_CTX_get(ctx)) == NULL) goto err; if (!bn_x931_derive_pi(p1, Xp1, ctx, cb)) goto err; if (!bn_x931_derive_pi(p2, Xp2, ctx, cb)) goto err; if (!BN_mul(p1p2, p1, p2, ctx)) goto err; /* First set p to value of Rp */ if (!BN_mod_inverse(p, p2, p1, ctx)) goto err; if (!BN_mul(p, p, p2, ctx)) goto err; if (!BN_mod_inverse(t, p1, p2, ctx)) goto err; if (!BN_mul(t, t, p1, ctx)) goto err; if (!BN_sub(p, p, t)) goto err; if (p->neg && !BN_add(p, p, p1p2)) goto err; /* p now equals Rp */ if (!BN_mod_sub(p, p, Xp, p1p2, ctx)) goto err; if (!BN_add(p, p, Xp)) goto err; /* p now equals Yp0 */ for (;;) { int i = 1; BN_GENCB_call(cb, 0, i++); if (!BN_copy(pm1, p)) goto err; if (!BN_sub_word(pm1, 1)) goto err; if (!BN_gcd(t, pm1, e, ctx)) goto err; if (BN_is_one(t) /* X9.31 specifies 8 MR and 1 Lucas test or any prime test * offering similar or better guarantees 50 MR is considerably * better. */ && BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb)) break; if (!BN_add(p, p, p1p2)) goto err; } BN_GENCB_call(cb, 3, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
int generateRandomKeys(paillierKeys *keys, int *key_len, BN_CTX *ctx) { int ret = 1, final_key_l = 0; BIGNUM *p, *q, *tmp, *n, *n2, *g, *lamda, *mu; if (key_len != NULL && *key_len == 0) { *key_len = DEFAULT_KEY_LEN; final_key_l = *key_len; } else if (key_len != NULL) { final_key_l = *key_len; } else { final_key_l = DEFAULT_KEY_LEN; } if (final_key_l < 32) { fprintf(stderr, "Key lenght too short. Minimum lenght 32 bits"); goto end; } BN_CTX_start(ctx); // Temp BIGNUMs p = BN_CTX_get(ctx); q = BN_CTX_get(ctx); tmp = BN_CTX_get(ctx); // Part of the keys BIGNUMs n = BN_new(); n2 = BN_new(); g = BN_new(); lamda = BN_new(); mu = BN_new(); // 1. Choose two large prime numbers // This numbers have to hold gcd(pq, (p-1)(q-1)) = 1 unsigned char buffer; do { if (!RAND_bytes(&buffer, sizeof(buffer))) goto end; srandom((int)buffer); if (!BN_generate_prime_ex(p, final_key_l / 2, 0, NULL, NULL, NULL)) goto end; if (!BN_generate_prime_ex(q, final_key_l / 2, 0, NULL, NULL, NULL)) goto end; // 2. Compute n = pq if (!BN_mul(n, p, q, ctx)) goto end; // Test if primes are ok if (!BN_sub_word(p, 1)) goto end; if (!BN_sub_word(q, 1)) goto end; if (!BN_mul(tmp, p, q, ctx)) goto end; } while (BN_cmp(p, q) == 0 || BN_gcd(tmp, tmp, n, ctx) != 1); // and lamda = lcm(p-1,q-1) if (!BN_lcm(lamda, p, q, ctx)) goto end; if (!BN_mul(n2, n, n, ctx)) goto end; do { // 3. Select a random integer g moz n2 do { if (!BN_rand_range(g, n2)) goto end; } while (BN_is_zero(g)); // 4. Ensure n divides the order of g if (!BN_mod_exp(tmp, g, lamda, n2, ctx)) goto end; if (L(tmp, tmp, n, ctx) != 0) goto end; BN_mod_inverse(mu, tmp, n, ctx); } while (mu == NULL); keys->pub.n = n; keys->pub.n2 = n2; keys->pub.g = g; keys->priv.n = BN_dup(n); keys->priv.n2 = BN_dup(n2); keys->priv.lamda = lamda; keys->priv.mu = mu; keys->n = BN_dup(n); keys->n2 = BN_dup(n2); ret = 0; end: if (ret) { ERR_load_crypto_strings(); fprintf(stderr, "Error generating keys: %s", ERR_error_string(ERR_get_error(), NULL)); } BN_CTX_end(ctx); return ret; }
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { int ret = 0; BIGNUM *Ri,*R; BN_CTX_start(ctx); if((Ri = BN_CTX_get(ctx)) == NULL) goto err; R= &(mont->RR); /* grab RR as a temp */ if (!BN_copy(&(mont->N),mod)) goto err; /* Set N */ mont->N.neg = 0; #ifdef MONT_WORD { BIGNUM tmod; BN_ULONG buf[2]; mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; BN_zero(R); if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ buf[0]=mod->d[0]; /* tmod = N mod word size */ buf[1]=0; tmod.d=buf; tmod.top = buf[0] != 0 ? 1 : 0; tmod.dmax=2; tmod.neg=0; /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) goto err; if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */ if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri,1)) goto err; } else /* if N mod word size == 1 */ { if (!BN_set_word(Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */ } if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only least significant word: */ mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0; } #else /* !MONT_WORD */ { /* bignum version */ mont->ri=BN_num_bits(&mont->N); BN_zero(R); if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */ /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL) goto err; if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */ if (!BN_sub_word(Ri,1)) goto err; /* Ni = (R*Ri-1) / N */ if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err; } #endif /* setup RR for conversions */ BN_zero(&(mont->RR)); if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err; if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err; ret = 1; err: BN_CTX_end(ctx); return ret; }