int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) { int i, nm, nd; int ret = 0; BIGNUM *D; bn_check_top(m); bn_check_top(d); if (BN_is_zero(d)) { BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); return (0); } if (BN_ucmp(m, d) < 0) { if (rem != NULL) { if (BN_copy(rem, m) == NULL) return (0); } if (dv != NULL) BN_zero(dv); return (1); } BN_CTX_start(ctx); D = BN_CTX_get(ctx); if (dv == NULL) dv = BN_CTX_get(ctx); if (rem == NULL) rem = BN_CTX_get(ctx); if (D == NULL || dv == NULL || rem == NULL) goto end; nd = BN_num_bits(d); nm = BN_num_bits(m); if (BN_copy(D, d) == NULL) goto end; if (BN_copy(rem, m) == NULL) goto end; /* * The next 2 are needed so we can do a dv->d[0]|=1 later since * BN_lshift1 will only work once there is a value :-) */ BN_zero(dv); if (bn_wexpand(dv, 1) == NULL) goto end; dv->top = 1; if (!BN_lshift(D, D, nm - nd)) goto end; for (i = nm - nd; i >= 0; i--) { if (!BN_lshift1(dv, dv)) goto end; if (BN_ucmp(rem, D) >= 0) { dv->d[0] |= 1; if (!BN_usub(rem, rem, D)) goto end; } /* CAN IMPROVE (and have now :=) */ if (!BN_rshift1(D, D)) goto end; } rem->neg = BN_is_zero(rem) ? 0 : m->neg; dv->neg = m->neg ^ d->neg; ret = 1; end: BN_CTX_end(ctx); return (ret); }
BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM *ret=NULL; int sign; if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) { return BN_mod_inverse_no_branch(in, a, n, ctx); } bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ #if 0 if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* * 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) goto err; } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) goto err; } if (shift > 0) { if (!BN_rshift(B, B, shift)) goto err; } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) goto err; } /* now Y is even */ if (!BN_rshift1(Y, Y)) goto err; } if (shift > 0) { if (!BN_rshift(A, A, shift)) goto err; } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) goto err; /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) goto err; } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) goto err; /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) goto err; } } } else #endif { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T,B)) goto err; if (BN_ucmp(A,T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M,A,T)) goto err; if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ if (BN_ucmp(A,D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D,2)) goto err; /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D,3)) goto err; /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M,M,B)) goto err; } } } else { if (!BN_div(D,M,A,B,ctx)) goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp,X,Y)) goto err; } else { if (BN_is_word(D,2)) { if (!BN_lshift1(tmp,X)) goto err; } else if (BN_is_word(D,4)) { if (!BN_lshift(tmp,X,2)) goto err; } else if (D->top == 1) { if (!BN_copy(tmp,X)) goto err; if (!BN_mul_word(tmp,D->d[0])) goto err; } else { if (!BN_mul(tmp,D,X,ctx)) goto err; } if (!BN_add(tmp,tmp,Y)) goto err; } M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return(ret); }
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, BN_CTX *ctx) { int i, j, ret = 0; BIGNUM *a, *b, *d, *r; BN_CTX_start(ctx); a = BN_CTX_get(ctx); b = BN_CTX_get(ctx); if (dv != NULL) d = dv; else d = BN_CTX_get(ctx); if (rem != NULL) r = rem; else r = BN_CTX_get(ctx); if (a == NULL || b == NULL || d == NULL || r == NULL) goto err; if (BN_ucmp(m, &(recp->N)) < 0) { BN_zero(d); if (!BN_copy(r, m)) { BN_CTX_end(ctx); return 0; } BN_CTX_end(ctx); return (1); } /* * We want the remainder Given input of ABCDEF / ab we need multiply * ABCDEF by 3 digests of the reciprocal of ab */ /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */ i = BN_num_bits(m); j = recp->num_bits << 1; if (j > i) i = j; /* Nr := round(2^i / N) */ if (i != recp->shift) recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx); /* BN_reciprocal could have returned -1 for an error */ if (recp->shift == -1) goto err; /*- * d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))| * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| * = |m/N| */ if (!BN_rshift(a, m, recp->num_bits)) goto err; if (!BN_mul(b, a, &(recp->Nr), ctx)) goto err; if (!BN_rshift(d, b, i - recp->num_bits)) goto err; d->neg = 0; if (!BN_mul(b, &(recp->N), d, ctx)) goto err; if (!BN_usub(r, m, b)) goto err; r->neg = 0; #if 1 j = 0; while (BN_ucmp(r, &(recp->N)) >= 0) { if (j++ > 2) { BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL); goto err; } if (!BN_usub(r, r, &(recp->N))) goto err; if (!BN_add_word(d, 1)) goto err; } #endif r->neg = BN_is_zero(r) ? 0 : m->neg; d->neg = m->neg ^ recp->N.neg; ret = 1; err: BN_CTX_end(ctx); bn_check_top(dv); bn_check_top(rem); return (ret); }
int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr) { if (fDebugRingSig) { // LogPrintf("%s size %d\n", __func__, nRingSize); // happens often }; int rv = 0; BN_CTX_start(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnH = BN_CTX_get(bnCtx); BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnR = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptKi = NULL; EC_POINT *ptL = NULL; EC_POINT *ptR = NULL; EC_POINT *ptSi = NULL; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION); ssCommitHash << txnHash; // zero sum if (!bnSum || !(BN_zero(bnSum))) { LogPrintf("%s: BN_zero failed.\n", __func__); rv = 1; goto End; }; if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptKi = EC_POINT_new(ecGrp)) || !(ptL = EC_POINT_new(ecGrp)) || !(ptSi = EC_POINT_new(ecGrp)) || !(ptR = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT)) || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx))) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; for (int i = 0; i < nRingSize; ++i) { // Li = ci * Pi + ri * G // Ri = ci * I + ri * Hp(Pi) if ( !bnC || !(bnC = BN_bin2bn(&pSigc[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnC)) || !bnR || !(bnR = BN_bin2bn(&pSigr[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnR))) { LogPrintf("%s: extract bnC and bnR failed.\n", __func__); rv = 1; goto End; }; // get Pk i as point if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT)) || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx))) { LogPrintf("%s: extract ptPk failed.\n", __func__); rv = 1; goto End; }; // ptT1 = ci * Pi if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = ri * G if (!EC_POINT_mul(ecGrp, ptT2, bnR, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptL = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // ptT3 = Hp(Pi) if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // DEBUGGING: ------- check if we can find the signer... // ptSi = Pi * bnT if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx) || false) && (rv = errorN(1, "%s: EC_POINT_mul failed.1", __func__))) goto End; if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) ) LogPrintf("signer is index %d\n", i); // DEBUGGING: - End - check if we can find the signer... // ptT1 = k1 * I if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnR, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptR = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // sum = (sum + ci) % N if (!BN_mod_add(bnSum, bnSum, bnC, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_add failed.\n", __func__); rv = 1; goto End; }; // -- add ptL and ptR to hash if ( !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCommitHash.write((const char*)&tempData[0], 66); }; commitHash = ssCommitHash.GetHash(); if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH))) { LogPrintf("%s: commitHash -> bnH failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod failed.\n", __func__); rv = 1; goto End; }; // bnT = (bnH - bnSum) % N if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; // test bnT == 0 (bnSum == bnH) if (!BN_is_zero(bnT)) { LogPrintf("%s: signature does not verify.\n", __func__); rv = 2; }; End: EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptPk); EC_POINT_free(ptKi); EC_POINT_free(ptL); EC_POINT_free(ptR); EC_POINT_free(ptSi); BN_CTX_end(bnCtx); return rv; };
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { int i, ret = 0; BIGNUM *Ri, *R; if (BN_is_zero(mod)) return 0; 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 */ if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) BN_set_flags(&(mont->N), BN_FLG_CONSTTIME); 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; if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) BN_set_flags(&tmod, BN_FLG_CONSTTIME); 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_is_one(&tmod)) BN_zero(Ri); else if ((BN_mod_inverse(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(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_is_one(&tmod)) BN_zero(Ri); else 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[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(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; for (i = mont->RR.top, ret = mont->N.top; i < ret; i++) mont->RR.d[i] = 0; mont->RR.top = ret; mont->RR.flags |= BN_FLG_FIXED_TOP; ret = 1; err: BN_CTX_end(ctx); return ret; }
/* random number r: 0 <= r < range */ static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range) { int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; int n; int count = 100; if (range->neg || BN_is_zero(range)) { BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); return 0; } n = BN_num_bits(range); /* n > 0 */ /* BN_is_bit_set(range, n - 1) always holds */ if (n == 1) BN_zero(r); #ifdef OPENSSL_FIPS /* FIPS 186-3 is picky about how random numbers for keys etc are * generated. So we just use the second case which is equivalent to * "Generation by Testing Candidates" mentioned in B.1.2 et al. */ else if (!FIPS_mode() && !BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) #else else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) #endif { /* range = 100..._2, * so 3*range (= 11..._2) is exactly one bit longer than range */ do { if (!bn_rand(r, n + 1, -1, 0)) return 0; /* If r < 3*range, use r := r MOD range * (which is either r, r - range, or r - 2*range). * Otherwise, iterate once more. * Since 3*range = 11..._2, each iteration succeeds with * probability >= .75. */ if (BN_cmp(r ,range) >= 0) { if (!BN_sub(r, r, range)) return 0; if (BN_cmp(r, range) >= 0) if (!BN_sub(r, r, range)) return 0; } if (!--count) { BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); return 0; } } while (BN_cmp(r, range) >= 0); } else { do { /* range = 11..._2 or range = 101..._2 */ if (!bn_rand(r, n, -1, 0)) return 0; if (!--count) { BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); return 0; } } while (BN_cmp(r, range) >= 0); } bn_check_top(r); return 1; }
int MKEMParams_init(MKEMParams *params) { const mk_curve_params *p = &mk_curves[MK_CURVE_163_0]; BIGNUM *maxu = 0; size_t bitsize, bytesize, bitcap, k; memset(params, 0, sizeof(MKEMParams)); FAILZ(params->ctx = BN_CTX_new()); FAILZ(params->m = BN_bin2bn(p->m, p->L_m, 0)); FAILZ(params->b = BN_bin2bn(p->b, p->L_b, 0)); FAILZ(params->a0 = BN_new()); FAILZ(BN_zero((BIGNUM *)params->a0)); FAILZ(params->a1 = BN_value_one()); FAILZ(params->p0 = BN_bin2bn(p->p0, p->L_p0, 0)); FAILZ(params->p1 = BN_bin2bn(p->p1, p->L_p1, 0)); FAILZ(params->n0 = BN_bin2bn(p->n0, p->L_n0, 0)); FAILZ(params->n1 = BN_bin2bn(p->n1, p->L_n1, 0)); FAILZ(params->c0 = EC_GROUP_new_curve_GF2m(params->m, params->a0, params->b, params->ctx)); FAILZ(params->c1 = EC_GROUP_new_curve_GF2m(params->m, params->a1, params->b, params->ctx)); FAILZ(params->g0 = EC_POINT_new(params->c0)); FAILZ(EC_POINT_oct2point(params->c0, (EC_POINT *)params->g0, p->g0, p->L_g0, params->ctx)); FAILZ(params->g1 = EC_POINT_new(params->c1)); FAILZ(EC_POINT_oct2point(params->c1, (EC_POINT *)params->g1, p->g1, p->L_g1, params->ctx)); /* Calculate the upper limit for the random integer U input to MKEM_generate_message_u. The paper calls for us to choose between curve 0 and curve 1 with probability proportional to the number of points on that curve, and then choose a random integer in the range 0 < u < n{curve}. The easiest way to do this accurately is to choose a random integer in the range [1, n0 + n1 - 2]. If it is less than n0, MKEM_generate_message_u will use it unmodified with curve 0. If it is greater than or equal to n0, MKEM_generate_message_u will subtract n0-1, leaving a number in the range [1, n1-1], and use that with curve 1. */ FAILZ(maxu = BN_dup(params->n0)); FAILZ(BN_add(maxu, maxu, params->n1)); FAILZ(BN_sub(maxu, maxu, BN_value_one())); FAILZ(BN_sub(maxu, maxu, BN_value_one())); params->maxu = maxu; maxu = 0; /* Calculate the maximum size of a message and the padding mask applied to the high byte of each message. See MKEM_generate_message_u for further exposition. */ bitsize = EC_GROUP_get_degree(params->c0); if ((size_t)EC_GROUP_get_degree(params->c1) != bitsize) goto fail; bytesize = (bitsize + 7) / 8; bitcap = bytesize * 8; k = bitcap - bitsize; if (k == 0) goto fail; params->msgsize = bytesize; params->pad_bits = k - 1; params->pad_mask = ~((1 << (8 - params->pad_bits)) - 1); params->curve_bit = 1 << (8 - k); return 0; fail: if (maxu) BN_free(maxu); MKEMParams_teardown(params); return -1; }
static int FIPS_dsa_builtin_paramgen(DSA *ret, int bits, unsigned char *seed_in, int seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) { int ok=0; unsigned char seed[SHA_DIGEST_LENGTH]; unsigned char md[SHA_DIGEST_LENGTH]; unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH]; BIGNUM *r0,*W,*X,*c,*test; BIGNUM *g=NULL,*q=NULL,*p=NULL; BN_MONT_CTX *mont=NULL; int k,n=0,i,b,m=0; int counter=0; int r=0; BN_CTX *ctx=NULL; unsigned int h=2; if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_DSA_BUILTIN_PARAMGEN, FIPS_R_FIPS_SELFTEST_FAILED); goto err; } if (FIPS_mode() && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL); goto err; } if (bits < 512) bits=512; bits=(bits+63)/64*64; /* NB: seed_len == 0 is special case: copy generated seed to * seed_in if it is not NULL. */ if (seed_len && (seed_len < 20)) seed_in = NULL; /* seed buffer too small -- ignore */ if (seed_len > 20) seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED, * but our internal buffers are restricted to 160 bits*/ if ((seed_in != NULL) && (seed_len == 20)) { memcpy(seed,seed_in,seed_len); /* set seed_in to NULL to avoid it being copied back */ seed_in = NULL; } if ((ctx=BN_CTX_new()) == NULL) goto err; if ((mont=BN_MONT_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); g = BN_CTX_get(ctx); W = BN_CTX_get(ctx); q = BN_CTX_get(ctx); X = BN_CTX_get(ctx); c = BN_CTX_get(ctx); p = BN_CTX_get(ctx); test = BN_CTX_get(ctx); if (!BN_lshift(test,BN_value_one(),bits-1)) goto err; for (;;) { for (;;) /* find q */ { int seed_is_random; /* step 1 */ if(!BN_GENCB_call(cb, 0, m++)) goto err; if (!seed_len) { RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH); seed_is_random = 1; } else { seed_is_random = 0; seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/ } memcpy(buf,seed,SHA_DIGEST_LENGTH); memcpy(buf2,seed,SHA_DIGEST_LENGTH); /* precompute "SEED + 1" for step 7: */ for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) { buf[i]++; if (buf[i] != 0) break; } /* step 2 */ EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL); EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL); for (i=0; i<SHA_DIGEST_LENGTH; i++) md[i]^=buf2[i]; /* step 3 */ md[0]|=0x80; md[SHA_DIGEST_LENGTH-1]|=0x01; if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,q)) goto err; /* step 4 */ r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, seed_is_random, cb); if (r > 0) break; if (r != 0) goto err; /* do a callback call */ /* step 5 */ } if(!BN_GENCB_call(cb, 2, 0)) goto err; if(!BN_GENCB_call(cb, 3, 0)) goto err; /* step 6 */ counter=0; /* "offset = 2" */ n=(bits-1)/160; b=(bits-1)-n*160; for (;;) { if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) goto err; /* step 7 */ BN_zero(W); /* now 'buf' contains "SEED + offset - 1" */ for (k=0; k<=n; k++) { /* obtain "SEED + offset + k" by incrementing: */ for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) { buf[i]++; if (buf[i] != 0) break; } EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL); /* step 8 */ if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0)) goto err; if (!BN_lshift(r0,r0,160*k)) goto err; if (!BN_add(W,W,r0)) goto err; } /* more of step 8 */ if (!BN_mask_bits(W,bits-1)) goto err; if (!BN_copy(X,W)) goto err; if (!BN_add(X,X,test)) goto err; /* step 9 */ if (!BN_lshift1(r0,q)) goto err; if (!BN_mod(c,X,r0,ctx)) goto err; if (!BN_sub(r0,c,BN_value_one())) goto err; if (!BN_sub(p,X,r0)) goto err; /* step 10 */ if (BN_cmp(p,test) >= 0) { /* step 11 */ r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); if (r > 0) goto end; /* found it */ if (r != 0) goto err; } /* step 13 */ counter++; /* "offset = offset + n + 1" */ /* step 14 */ if (counter >= 4096) break; } } end: if(!BN_GENCB_call(cb, 2, 1)) goto err; /* We now need to generate g */ /* Set r0=(p-1)/q */ if (!BN_sub(test,p,BN_value_one())) goto err; if (!BN_div(r0,NULL,test,q,ctx)) goto err; if (!BN_set_word(test,h)) goto err; if (!BN_MONT_CTX_set(mont,p,ctx)) goto err; for (;;) { /* g=test^r0%p */ if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err; if (!BN_is_one(g)) break; if (!BN_add(test,test,BN_value_one())) goto err; h++; } if(!BN_GENCB_call(cb, 3, 1)) goto err; ok=1; err: if (ok) { if(ret->p) BN_free(ret->p); if(ret->q) BN_free(ret->q); if(ret->g) BN_free(ret->g); ret->p=BN_dup(p); ret->q=BN_dup(q); ret->g=BN_dup(g); if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { ok=0; goto err; } if (seed_in != NULL) memcpy(seed_in,seed,20); if (counter_ret != NULL) *counter_ret=counter; if (h_ret != NULL) *h_ret=h; } if(ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (mont != NULL) BN_MONT_CTX_free(mont); return ok; }
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; }
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero() { 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; }
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_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; int top, al, bl; BIGNUM *rr; #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) int i; #endif #ifdef BN_RECURSION BIGNUM *t = NULL; int j = 0, k; #endif bn_check_top(a); bn_check_top(b); bn_check_top(r); al = a->top; bl = b->top; if ((al == 0) || (bl == 0)) { BN_zero(r); return (1); } top = al + bl; BN_CTX_start(ctx); if ((r == a) || (r == b)) { if ((rr = BN_CTX_get(ctx)) == NULL) goto err; } else rr = r; rr->neg = a->neg ^ b->neg; #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) i = al - bl; #endif #ifdef BN_MUL_COMBA if (i == 0) { # if 0 if (al == 4) { if (bn_wexpand(rr, 8) == NULL) goto err; rr->top = 8; bn_mul_comba4(rr->d, a->d, b->d); goto end; } # endif if (al == 8) { if (bn_wexpand(rr, 16) == NULL) goto err; rr->top = 16; bn_mul_comba8(rr->d, a->d, b->d); goto end; } } #endif /* BN_MUL_COMBA */ #ifdef BN_RECURSION if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { if (i >= -1 && i <= 1) { /* * Find out the power of two lower or equal to the longest of the * two numbers */ if (i >= 0) { j = BN_num_bits_word((BN_ULONG)al); } if (i == -1) { j = BN_num_bits_word((BN_ULONG)bl); } j = 1 << (j - 1); assert(j <= al || j <= bl); k = j + j; t = BN_CTX_get(ctx); if (t == NULL) goto err; if (al > j || bl > j) { if (bn_wexpand(t, k * 4) == NULL) goto err; if (bn_wexpand(rr, k * 4) == NULL) goto err; bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } else { /* al <= j || bl <= j */ if (bn_wexpand(t, k * 2) == NULL) goto err; if (bn_wexpand(rr, k * 2) == NULL) goto err; bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } rr->top = top; goto end; } # if 0 if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) { BIGNUM *tmp_bn = (BIGNUM *)b; if (bn_wexpand(tmp_bn, al) == NULL) goto err; tmp_bn->d[bl] = 0; bl++; i--; } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) { BIGNUM *tmp_bn = (BIGNUM *)a; if (bn_wexpand(tmp_bn, bl) == NULL) goto err; tmp_bn->d[al] = 0; al++; i++; } if (i == 0) { /* symmetric and > 4 */ /* 16 or larger */ j = BN_num_bits_word((BN_ULONG)al); j = 1 << (j - 1); k = j + j; t = BN_CTX_get(ctx); if (al == j) { /* exact multiple */ if (bn_wexpand(t, k * 2) == NULL) goto err; if (bn_wexpand(rr, k * 2) == NULL) goto err; bn_mul_recursive(rr->d, a->d, b->d, al, t->d); } else { if (bn_wexpand(t, k * 4) == NULL) goto err; if (bn_wexpand(rr, k * 4) == NULL) goto err; bn_mul_part_recursive(rr->d, a->d, b->d, al - j, j, t->d); } rr->top = top; goto end; } # endif } #endif /* BN_RECURSION */ if (bn_wexpand(rr, top) == NULL) goto err; rr->top = top; bn_mul_normal(rr->d, a->d, al, b->d, bl); #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) end: #endif bn_correct_top(rr); if (r != rr) BN_copy(r, rr); ret = 1; err: bn_check_top(r); 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; BIGNUM tmod; BN_ULONG buf[2]; if (BN_is_zero(mod)) { OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); return 0; } BN_CTX_start(ctx); Ri = BN_CTX_get(ctx); if (Ri == 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; 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(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(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(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[0] = (Ri->top > 0) ? Ri->d[0] : 0; mont->n0[1] = 0; #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; }
// bn_mul_impl implements |BN_mul| and |bn_mul_consttime|. Note this function // breaks |BIGNUM| invariants and may return a negative zero. This is handled by // the callers. static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int al = a->width; int bl = b->width; if (al == 0 || bl == 0) { BN_zero(r); return 1; } int ret = 0; BIGNUM *rr; BN_CTX_start(ctx); if (r == a || r == b) { rr = BN_CTX_get(ctx); if (rr == NULL) { goto err; } } else { rr = r; } rr->neg = a->neg ^ b->neg; int i = al - bl; if (i == 0) { if (al == 8) { if (!bn_wexpand(rr, 16)) { goto err; } rr->width = 16; bn_mul_comba8(rr->d, a->d, b->d); goto end; } } int top = al + bl; static const int kMulNormalSize = 16; if (al >= kMulNormalSize && bl >= kMulNormalSize) { if (-1 <= i && i <= 1) { // Find the larger power of two less than or equal to the larger length. int j; if (i >= 0) { j = BN_num_bits_word((BN_ULONG)al); } else { j = BN_num_bits_word((BN_ULONG)bl); } j = 1 << (j - 1); assert(j <= al || j <= bl); BIGNUM *t = BN_CTX_get(ctx); if (t == NULL) { goto err; } if (al > j || bl > j) { // We know |al| and |bl| are at most one from each other, so if al > j, // bl >= j, and vice versa. Thus we can use |bn_mul_part_recursive|. assert(al >= j && bl >= j); if (!bn_wexpand(t, j * 8) || !bn_wexpand(rr, j * 4)) { goto err; } bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } else { // al <= j && bl <= j. Additionally, we know j <= al or j <= bl, so one // of al - j or bl - j is zero. The other, by the bound on |i| above, is // zero or -1. Thus, we can use |bn_mul_recursive|. if (!bn_wexpand(t, j * 4) || !bn_wexpand(rr, j * 2)) { goto err; } bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } rr->width = top; goto end; } } if (!bn_wexpand(rr, top)) { goto err; } rr->width = top; bn_mul_normal(rr->d, a->d, al, b->d, bl); end: if (r != rr && !BN_copy(r, rr)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }
/** * Reconstruct secret using the provided shares * * @param shares Shares used to reconstruct secret (should contain t entries) * @param t Threshold used to reconstruct the secret * @param prime Prime for finite field arithmetic * @param s Pointer for storage of calculated secred */ static int reconstructSecret(secret_share_t *shares, unsigned char t, const BIGNUM prime, BIGNUM *s) { unsigned char i; unsigned char j; // Array representing the polynomial a(x) = s + a_1 * x + ... + a_n-1 * x^n-1 mod p BIGNUM **bValue = malloc(t * sizeof(BIGNUM *)); BIGNUM **pbValue; BIGNUM numerator; BIGNUM denominator; BIGNUM temp; secret_share_t *sp_i; secret_share_t *sp_j; BN_CTX *ctx; // Initialize pbValue = bValue; for (i = 0; i < t; i++) { *pbValue = BN_new(); BN_init(*pbValue); pbValue++; } BN_init(&numerator); BN_init(&denominator); BN_init(&temp); // Create context for temporary variables of engine ctx = BN_CTX_new(); BN_CTX_init(ctx); pbValue = bValue; sp_i = shares; for (i = 0; i < t; i++) { BN_one(&numerator); BN_one(&denominator); sp_j = shares; for (j = 0; j < t; j++) { if (i == j) { sp_j++; continue; } BN_mul(&numerator, &numerator, &(sp_j->x), ctx); BN_sub(&temp, &(sp_j->x), &(sp_i->x)); BN_mul(&denominator, &denominator, &temp, ctx); sp_j++; } /* * Use the modular inverse value of the denominator for the * multiplication */ if (BN_mod_inverse(&denominator, &denominator, &prime, ctx) == NULL ) { free(bValue); return -1; } BN_mod_mul(*pbValue, &numerator, &denominator, &prime, ctx); pbValue++; sp_i++; } /* * Calculate the secret by multiplying all y-values with their * corresponding intermediate values */ pbValue = bValue; sp_i = shares; BN_zero(s); for (i = 0; i < t; i++) { BN_mul(&temp, &(sp_i->y), *pbValue, ctx); BN_add(s, s, &temp); pbValue++; sp_i++; } // Perform modulo operation and copy result BN_nnmod(&temp, s, &prime, ctx); BN_copy(s, &temp); BN_clear_free(&numerator); BN_clear_free(&denominator); BN_clear_free(&temp); BN_CTX_free(ctx); // Deallocate the resource of the polynomial pbValue = bValue; for (i = 0; i < t; i++) { BN_clear_free(*pbValue); pbValue++; } free(bValue); return 0; }
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); const BIGNUM *p; BN_CTX *new_ctx = NULL; BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; int ret = 0; if (a == b) return EC_POINT_dbl(group, r, a, ctx); if (EC_POINT_is_at_infinity(group, a)) return EC_POINT_copy(r, b); if (EC_POINT_is_at_infinity(group, b)) return EC_POINT_copy(r, a); field_mul = group->meth->field_mul; field_sqr = group->meth->field_sqr; p = &group->field; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); n0 = BN_CTX_get(ctx); n1 = BN_CTX_get(ctx); n2 = BN_CTX_get(ctx); n3 = BN_CTX_get(ctx); n4 = BN_CTX_get(ctx); n5 = BN_CTX_get(ctx); n6 = BN_CTX_get(ctx); if (n6 == NULL) goto end; /* Note that in this function we must not read components of 'a' or 'b' * once we have written the corresponding components of 'r'. * ('r' might be one of 'a' or 'b'.) */ /* n1, n2 */ if (b->Z_is_one) { if (!BN_copy(n1, &a->X)) goto end; if (!BN_copy(n2, &a->Y)) goto end; /* n1 = X_a */ /* n2 = Y_a */ } else { if (!field_sqr(group, n0, &b->Z, ctx)) goto end; if (!field_mul(group, n1, &a->X, n0, ctx)) goto end; /* n1 = X_a * Z_b^2 */ if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end; if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end; /* n2 = Y_a * Z_b^3 */ } /* n3, n4 */ if (a->Z_is_one) { if (!BN_copy(n3, &b->X)) goto end; if (!BN_copy(n4, &b->Y)) goto end; /* n3 = X_b */ /* n4 = Y_b */ } else { if (!field_sqr(group, n0, &a->Z, ctx)) goto end; if (!field_mul(group, n3, &b->X, n0, ctx)) goto end; /* n3 = X_b * Z_a^2 */ if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end; if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end; /* n4 = Y_b * Z_a^3 */ } /* n5, n6 */ if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end; if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end; /* n5 = n1 - n3 */ /* n6 = n2 - n4 */ if (BN_is_zero(n5)) { if (BN_is_zero(n6)) { /* a is the same point as b */ BN_CTX_end(ctx); ret = EC_POINT_dbl(group, r, a, ctx); ctx = NULL; goto end; } else { /* a is the inverse of b */ BN_zero(&r->Z); r->Z_is_one = 0; ret = 1; goto end; } } /* 'n7', 'n8' */ if (!BN_mod_add_quick(n1, n1, n3, p)) goto end; if (!BN_mod_add_quick(n2, n2, n4, p)) goto end; /* 'n7' = n1 + n3 */ /* 'n8' = n2 + n4 */ /* Z_r */ if (a->Z_is_one && b->Z_is_one) { if (!BN_copy(&r->Z, n5)) goto end; } else { if (a->Z_is_one) { if (!BN_copy(n0, &b->Z)) goto end; } else if (b->Z_is_one) { if (!BN_copy(n0, &a->Z)) goto end; } else { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; } if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end; } r->Z_is_one = 0; /* Z_r = Z_a * Z_b * n5 */ /* X_r */ if (!field_sqr(group, n0, n6, ctx)) goto end; if (!field_sqr(group, n4, n5, ctx)) goto end; if (!field_mul(group, n3, n1, n4, ctx)) goto end; if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end; /* X_r = n6^2 - n5^2 * 'n7' */ /* 'n9' */ if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end; if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end; /* n9 = n5^2 * 'n7' - 2 * X_r */ /* Y_r */ if (!field_mul(group, n0, n0, n6, ctx)) goto end; if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */ if (!field_mul(group, n1, n2, n5, ctx)) goto end; if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end; if (BN_is_odd(n0)) if (!BN_add(n0, n0, p)) goto end; /* now 0 <= n0 < 2*p, and n0 is even */ if (!BN_rshift1(&r->Y, n0)) goto end; /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ ret = 1; end: if (ctx) /* otherwise we already called BN_CTX_end */ BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) { unsigned char *buf=NULL; int ret=0,bit,bytes,mask; time_t tim; if (bits == 0) { BN_zero(rnd); return 1; } bytes=(bits+7)/8; bit=(bits-1)%8; mask=0xff<<(bit+1); buf=(unsigned char *)OPENSSL_malloc(bytes); if (buf == NULL) { BNerr(BN_F_BNRAND,ERR_R_MALLOC_FAILURE); goto err; } /* make a random number and set the top and bottom bits */ time(&tim); RAND_add(&tim,sizeof(tim),0.0); if (pseudorand) { if (RAND_pseudo_bytes(buf, bytes) == -1) goto err; } else { if (RAND_bytes(buf, bytes) <= 0) goto err; } #if 1 if (pseudorand == 2) { /* generate patterns that are more likely to trigger BN library bugs */ int i; unsigned char c; for (i = 0; i < bytes; i++) { RAND_pseudo_bytes(&c, 1); if (c >= 128 && i > 0) buf[i] = buf[i-1]; else if (c < 42) buf[i] = 0; else if (c < 84) buf[i] = 255; } } #endif if (top != -1) { if (top) { if (bit == 0) { buf[0]=1; buf[1]|=0x80; } else { buf[0]|=(3<<(bit-1)); } } else { buf[0]|=(1<<bit); } } buf[0] &= ~mask; if (bottom) /* set bottom bit if requested */ buf[bytes-1]|=1; if (!BN_bin2bn(buf,bytes,rnd)) goto err; ret=1; err: if (buf != NULL) { OPENSSL_cleanse(buf,bytes); OPENSSL_free(buf); } bn_check_top(rnd); return(ret); }
int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) { int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); const BIGNUM *p; BN_CTX *new_ctx = NULL; BIGNUM *n0, *n1, *n2, *n3; int ret = 0; if (EC_POINT_is_at_infinity(group, a)) { BN_zero(&r->Z); r->Z_is_one = 0; return 1; } field_mul = group->meth->field_mul; field_sqr = group->meth->field_sqr; p = &group->field; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); n0 = BN_CTX_get(ctx); n1 = BN_CTX_get(ctx); n2 = BN_CTX_get(ctx); n3 = BN_CTX_get(ctx); if (n3 == NULL) goto err; /* Note that in this function we must not read components of 'a' * once we have written the corresponding components of 'r'. * ('r' might the same as 'a'.) */ /* n1 */ if (a->Z_is_one) { if (!field_sqr(group, n0, &a->X, ctx)) goto err; if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err; /* n1 = 3 * X_a^2 + a_curve */ } else if (group->a_is_minus3) { if (!field_sqr(group, n1, &a->Z, ctx)) goto err; if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err; if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err; if (!field_mul(group, n1, n0, n2, ctx)) goto err; if (!BN_mod_lshift1_quick(n0, n1, p)) goto err; if (!BN_mod_add_quick(n1, n0, n1, p)) goto err; /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) * = 3 * X_a^2 - 3 * Z_a^4 */ } else { if (!field_sqr(group, n0, &a->X, ctx)) goto err; if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; if (!field_sqr(group, n1, &a->Z, ctx)) goto err; if (!field_sqr(group, n1, n1, ctx)) goto err; if (!field_mul(group, n1, n1, &group->a, ctx)) goto err; if (!BN_mod_add_quick(n1, n1, n0, p)) goto err; /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ } /* Z_r */ if (a->Z_is_one) { if (!BN_copy(n0, &a->Y)) goto err; } else { if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err; } if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err; r->Z_is_one = 0; /* Z_r = 2 * Y_a * Z_a */ /* n2 */ if (!field_sqr(group, n3, &a->Y, ctx)) goto err; if (!field_mul(group, n2, &a->X, n3, ctx)) goto err; if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err; /* n2 = 4 * X_a * Y_a^2 */ /* X_r */ if (!BN_mod_lshift1_quick(n0, n2, p)) goto err; if (!field_sqr(group, &r->X, n1, ctx)) goto err; if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err; /* X_r = n1^2 - 2 * n2 */ /* n3 */ if (!field_sqr(group, n0, n3, ctx)) goto err; if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err; /* n3 = 8 * Y_a^4 */ /* Y_r */ if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err; if (!field_mul(group, n0, n1, n0, ctx)) goto err; if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err; /* Y_r = n1 * (n2 - X_r) - n3 */ ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
/*- * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) * using Montgomery point multiplication algorithm Mxy() in appendix of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * Returns: * 0 on error * 1 if return value should be the point at infinity * 2 otherwise */ static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) { BIGNUM *t3, *t4, *t5; int ret = 0; if (BN_is_zero(z1)) { BN_zero(x2); BN_zero(z2); return 1; } if (BN_is_zero(z2)) { if (!BN_copy(x2, x)) return 0; if (!BN_GF2m_add(z2, x, y)) return 0; return 2; } /* Since Mxy is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); t3 = BN_CTX_get(ctx); t4 = BN_CTX_get(ctx); t5 = BN_CTX_get(ctx); if (t5 == NULL) goto err; if (!BN_one(t5)) goto err; if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err; if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err; if (!BN_GF2m_add(z1, z1, x1)) goto err; if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err; if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err; if (!BN_GF2m_add(z2, z2, x2)) goto err; if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err; if (!group->meth->field_sqr(group, t4, x, ctx)) goto err; if (!BN_GF2m_add(t4, t4, y)) goto err; if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err; if (!BN_GF2m_add(t4, t4, z2)) goto err; if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err; if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err; if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err; if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err; if (!BN_GF2m_add(z2, x2, x)) goto err; if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err; if (!BN_GF2m_add(z2, z2, y)) goto err; ret = 2; err: BN_CTX_end(ctx); return ret; }
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) { point->Z_is_one = 0; BN_zero(&point->Z); return 1; }
int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr) { if (fDebugRingSig) LogPrintf("%s: Ring size %d.\n", __func__, nRingSize); int rv = 0; int nBytes; BN_CTX_start(bnCtx); BIGNUM *bnKS = BN_CTX_get(bnCtx); BIGNUM *bnK1 = BN_CTX_get(bnCtx); BIGNUM *bnK2 = BN_CTX_get(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnH = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptKi = NULL; EC_POINT *ptL = NULL; EC_POINT *ptR = NULL; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; ec_secret scData1, scData2; CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION); ssCommitHash << txnHash; // zero signature memset(pSigc, 0, EC_SECRET_SIZE * nRingSize); memset(pSigr, 0, EC_SECRET_SIZE * nRingSize); // ks = random 256 bit int mod P if (GenerateRandomSecret(scData1) && (rv = errorN(1, "%s: GenerateRandomSecret failed.", __func__))) goto End; if (!bnKS || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnKS))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // zero sum if (!bnSum || !(BN_zero(bnSum))) { LogPrintf("%s: BN_zero failed.\n", __func__); rv = 1; goto End; }; if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptKi = EC_POINT_new(ecGrp)) || !(ptL = EC_POINT_new(ecGrp)) || !(ptR = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT)) || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx))) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; for (int i = 0; i < nRingSize; ++i) { if (i == nSecretOffset) { // k = random 256 bit int mod P // L = k * G // R = k * HashToEC(PKi) if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT1) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; } else { // k1 = random 256 bit int mod P // k2 = random 256 bit int mod P // Li = k1 * Pi + k2 * G // Ri = k1 * I + k2 * Hp(Pi) // ci = k1 // ri = k2 if (GenerateRandomSecret(scData1) != 0 || !bnK1 || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnK1)) || GenerateRandomSecret(scData2) != 0 || !bnK2 || !(BN_bin2bn(&scData2.e[0], EC_SECRET_SIZE, bnK2))) { LogPrintf("%s: k1 and k2 failed.\n", __func__); rv = 1; goto End; }; // get Pk i as point if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT)) || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx))) { LogPrintf("%s: extract ptPk failed.\n", __func__); rv = 1; goto End; }; // ptT1 = k1 * Pi if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * G if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptL = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // ptT3 = Hp(Pi) if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // ptT1 = k1 * I if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptR = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; memcpy(&pSigc[i * EC_SECRET_SIZE], &scData1.e[0], EC_SECRET_SIZE); memcpy(&pSigr[i * EC_SECRET_SIZE], &scData2.e[0], EC_SECRET_SIZE); // sum = (sum + sigc) % N , sigc == bnK1 if (!BN_mod_add(bnSum, bnSum, bnK1, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_add failed.\n", __func__); rv = 1; goto End; }; }; // -- add ptL and ptR to hash if ( !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCommitHash.write((const char*)&tempData[0], 66); }; commitHash = ssCommitHash.GetHash(); if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH))) { LogPrintf("%s: commitHash -> bnH failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) // this is necessary { LogPrintf("%s: BN_mod failed.\n", __func__); rv = 1; goto End; }; // sigc[nSecretOffset] = (bnH - bnSum) % N if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if ((nBytes = BN_num_bytes(bnT)) > (int)EC_SECRET_SIZE || BN_bn2bin(bnT, &pSigc[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnT -> pSigc failed.\n", __func__); rv = 1; goto End; }; // sigr[nSecretOffset] = (bnKS - sigc[nSecretOffset] * bnSecret) % N // reuse bnH for bnSecret if (!bnH || !(BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnH))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // bnT = sigc[nSecretOffset] * bnSecret , TODO: mod N ? if (!BN_mul(bnT, bnT, bnH, bnCtx)) { LogPrintf("%s: BN_mul failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod_sub(bnT, bnKS, bnT, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if ((nBytes = BN_num_bytes(bnT)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnT, &pSigr[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnT -> pSigr failed.\n", __func__); rv = 1; goto End; }; End: EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptPk); EC_POINT_free(ptKi); EC_POINT_free(ptL); EC_POINT_free(ptR); BN_CTX_end(bnCtx); return rv; };
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp, BN_CTX *ctx) { int i,j,ret=0; BIGNUM *a,*b,*d,*r; BN_CTX_start(ctx); a=BN_CTX_get(ctx); b=BN_CTX_get(ctx); if (dv != NULL) d=dv; else d=BN_CTX_get(ctx); if (rem != NULL) r=rem; else r=BN_CTX_get(ctx); if (a == NULL || b == NULL || d == NULL || r == NULL) goto err; if (BN_ucmp(m,&(recp->N)) < 0) { BN_zero(d); BN_copy(r,m); BN_CTX_end(ctx); return(1); } /* We want the remainder * Given input of ABCDEF / ab * we need multiply ABCDEF by 3 digests of the reciprocal of ab * */ i=BN_num_bits(m); j=recp->num_bits<<1; if (j>i) i=j; j>>=1; if (i != recp->shift) recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N), i,ctx); if (!BN_rshift(a,m,j)) goto err; if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err; if (!BN_rshift(d,b,i-j)) goto err; d->neg=0; if (!BN_mul(b,&(recp->N),d,ctx)) goto err; if (!BN_usub(r,m,b)) goto err; r->neg=0; #if 1 j=0; while (BN_ucmp(r,&(recp->N)) >= 0) { if (j++ > 2) { BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL); goto err; } if (!BN_usub(r,r,&(recp->N))) goto err; if (!BN_add_word(d,1)) goto err; } #endif r->neg=BN_is_zero(r)?0:m->neg; d->neg=m->neg^recp->N.neg; ret=1; err: BN_CTX_end(ctx); return(ret); }
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields // recid selects which key is recovered // if check is nonzero, additional checks are performed int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) { if (!eckey) return 0; int ret = 0; BN_CTX *ctx = NULL; BIGNUM *x = NULL; BIGNUM *e = NULL; BIGNUM *order = NULL; BIGNUM *sor = NULL; BIGNUM *eor = NULL; BIGNUM *field = NULL; EC_POINT *R = NULL; EC_POINT *O = NULL; EC_POINT *Q = NULL; BIGNUM *rr = NULL; BIGNUM *zero = NULL; int n = 0; int i = recid / 2; const EC_GROUP *group = EC_KEY_get0_group(eckey); if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } x = BN_CTX_get(ctx); if (!BN_copy(x, order)) { ret=-1; goto err; } if (!BN_mul_word(x, i)) { ret=-1; goto err; } if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } field = BN_CTX_get(ctx); if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } if (BN_cmp(x, field) >= 0) { ret=0; goto err; } if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } if (check) { if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } } if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } n = EC_GROUP_get_degree(group); e = BN_CTX_get(ctx); if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); zero = BN_CTX_get(ctx); if (!BN_zero(zero)) { ret=-1; goto err; } if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } rr = BN_CTX_get(ctx); if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } sor = BN_CTX_get(ctx); if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } eor = BN_CTX_get(ctx); if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; } ret = 1; err: if (ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (R != NULL) EC_POINT_free(R); if (O != NULL) EC_POINT_free(O); if (Q != NULL) EC_POINT_free(Q); return ret; }
/* random number r: 0 <= r < range */ static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range) { int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; int n; int count = 100; if (range->neg || BN_is_zero(range)) { BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); return 0; } n = BN_num_bits(range); /* n > 0 */ /* BN_is_bit_set(range, n - 1) always holds */ if (n == 1) BN_zero(r); else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { /* range = 100..._2, * so 3*range (= 11..._2) is exactly one bit longer than range */ do { if (!bn_rand(r, n + 1, -1, 0)) return 0; /* If r < 3*range, use r := r MOD range * (which is either r, r - range, or r - 2*range). * Otherwise, iterate once more. * Since 3*range = 11..._2, each iteration succeeds with * probability >= .75. */ if (BN_cmp(r, range) >= 0) { if (!BN_sub(r, r, range)) return 0; if (BN_cmp(r, range) >= 0) if (!BN_sub(r, r, range)) return 0; } if (!--count) { BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); return 0; } } while (BN_cmp(r, range) >= 0); } else { do { /* range = 11..._2 or range = 101..._2 */ if (!bn_rand(r, n, -1, 0)) return 0; if (!--count) { BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); return 0; } } while (BN_cmp(r, range) >= 0); } bn_check_top(r); return 1; }
int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) { int ok = 0; unsigned char seed[SHA256_DIGEST_LENGTH]; unsigned char md[SHA256_DIGEST_LENGTH]; unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; BIGNUM *r0, *W, *X, *c, *test; BIGNUM *g = NULL, *q = NULL, *p = NULL; BN_MONT_CTX *mont = NULL; int i, k, n = 0, m = 0, qsize = qbits >> 3; int counter = 0; int r = 0; BN_CTX *ctx = NULL; unsigned int h = 2; if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH && qsize != SHA256_DIGEST_LENGTH) /* invalid q size */ return 0; if (evpmd == NULL) /* use SHA1 as default */ evpmd = EVP_sha1(); if (bits < 512) bits = 512; bits = (bits + 63) / 64 * 64; /* * NB: seed_len == 0 is special case: copy generated seed to seed_in if * it is not NULL. */ if (seed_len && (seed_len < (size_t)qsize)) seed_in = NULL; /* seed buffer too small -- ignore */ if (seed_len > (size_t)qsize) seed_len = qsize; /* App. 2.2 of FIPS PUB 186 allows larger * SEED, but our internal buffers are * restricted to 160 bits */ if (seed_in != NULL) memcpy(seed, seed_in, seed_len); if ((ctx = BN_CTX_new()) == NULL) goto err; if ((mont = BN_MONT_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); g = BN_CTX_get(ctx); W = BN_CTX_get(ctx); q = BN_CTX_get(ctx); X = BN_CTX_get(ctx); c = BN_CTX_get(ctx); p = BN_CTX_get(ctx); test = BN_CTX_get(ctx); if (!BN_lshift(test, BN_value_one(), bits - 1)) goto err; for (;;) { for (;;) { /* find q */ int seed_is_random; /* step 1 */ if (!BN_GENCB_call(cb, 0, m++)) goto err; if (!seed_len) { RAND_pseudo_bytes(seed, qsize); seed_is_random = 1; } else { seed_is_random = 0; seed_len = 0; /* use random seed if 'seed_in' turns out to * be bad */ } memcpy(buf, seed, qsize); memcpy(buf2, seed, qsize); /* precompute "SEED + 1" for step 7: */ for (i = qsize - 1; i >= 0; i--) { buf[i]++; if (buf[i] != 0) break; } /* step 2 */ EVP_Digest(seed, qsize, md, NULL, evpmd, NULL); EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL); for (i = 0; i < qsize; i++) md[i] ^= buf2[i]; /* step 3 */ md[0] |= 0x80; md[qsize - 1] |= 0x01; if (!BN_bin2bn(md, qsize, q)) goto err; /* step 4 */ r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, seed_is_random, cb); if (r > 0) break; if (r != 0) goto err; /* do a callback call */ /* step 5 */ } if (!BN_GENCB_call(cb, 2, 0)) goto err; if (!BN_GENCB_call(cb, 3, 0)) goto err; /* step 6 */ counter = 0; /* "offset = 2" */ n = (bits - 1) / 160; for (;;) { if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) goto err; /* step 7 */ BN_zero(W); /* now 'buf' contains "SEED + offset - 1" */ for (k = 0; k <= n; k++) { /* * obtain "SEED + offset + k" by incrementing: */ for (i = qsize - 1; i >= 0; i--) { buf[i]++; if (buf[i] != 0) break; } EVP_Digest(buf, qsize, md, NULL, evpmd, NULL); /* step 8 */ if (!BN_bin2bn(md, qsize, r0)) goto err; if (!BN_lshift(r0, r0, (qsize << 3) * k)) goto err; if (!BN_add(W, W, r0)) goto err; } /* more of step 8 */ if (!BN_mask_bits(W, bits - 1)) goto err; if (!BN_copy(X, W)) goto err; if (!BN_add(X, X, test)) goto err; /* step 9 */ if (!BN_lshift1(r0, q)) goto err; if (!BN_mod(c, X, r0, ctx)) goto err; if (!BN_sub(r0, c, BN_value_one())) goto err; if (!BN_sub(p, X, r0)) goto err; /* step 10 */ if (BN_cmp(p, test) >= 0) { /* step 11 */ r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); if (r > 0) goto end; /* found it */ if (r != 0) goto err; } /* step 13 */ counter++; /* "offset = offset + n + 1" */ /* step 14 */ if (counter >= 4096) break; } } end: if (!BN_GENCB_call(cb, 2, 1)) goto err; /* We now need to generate g */ /* Set r0=(p-1)/q */ if (!BN_sub(test, p, BN_value_one())) goto err; if (!BN_div(r0, NULL, test, q, ctx)) goto err; if (!BN_set_word(test, h)) goto err; if (!BN_MONT_CTX_set(mont, p, ctx)) goto err; for (;;) { /* g=test^r0%p */ if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) goto err; if (!BN_is_one(g)) break; if (!BN_add(test, test, BN_value_one())) goto err; h++; } if (!BN_GENCB_call(cb, 3, 1)) goto err; ok = 1; err: if (ok) { if (ret->p) BN_free(ret->p); if (ret->q) BN_free(ret->q); if (ret->g) BN_free(ret->g); ret->p = BN_dup(p); ret->q = BN_dup(q); ret->g = BN_dup(g); if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { ok = 0; goto err; } if (counter_ret != NULL) *counter_ret = counter; if (h_ret != NULL) *h_ret = h; } if (ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (mont != NULL) BN_MONT_CTX_free(mont); return ok; }
/*- * BN_div computes dv := num / divisor, rounding towards * zero, and sets up rm such that dv*divisor + rm = num holds. * Thus: * dv->neg == num->neg ^ divisor->neg (unless the result is zero) * rm->neg == num->neg (unless the remainder is zero) * If 'dv' or 'rm' is NULL, the respective value is not returned. */ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift, i, loop; BIGNUM *tmp, wnum, *snum, *sdiv, *res; BN_ULONG *resp, *wnump; BN_ULONG d0, d1; int num_n, div_n; int no_branch = 0; /* * Invalid zero-padding would have particularly bad consequences so don't * just rely on bn_check_top() here (bn_check_top() works only for * BN_DEBUG builds) */ if ((num->top > 0 && num->d[num->top - 1] == 0) || (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) { BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED); return 0; } bn_check_top(num); bn_check_top(divisor); if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) { no_branch = 1; } bn_check_top(dv); bn_check_top(rm); /*- bn_check_top(num); *//* * 'num' has been checked already */ /*- bn_check_top(divisor); *//* * 'divisor' has been checked already */ if (BN_is_zero(divisor)) { BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); return (0); } if (!no_branch && BN_ucmp(num, divisor) < 0) { if (rm != NULL) { if (BN_copy(rm, num) == NULL) return (0); } if (dv != NULL) BN_zero(dv); return (1); } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); snum = BN_CTX_get(ctx); sdiv = BN_CTX_get(ctx); if (dv == NULL) res = BN_CTX_get(ctx); else res = dv; if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL) goto err; /* First we normalise the numbers */ norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); if (!(BN_lshift(sdiv, divisor, norm_shift))) goto err; sdiv->neg = 0; norm_shift += BN_BITS2; if (!(BN_lshift(snum, num, norm_shift))) goto err; snum->neg = 0; if (no_branch) { /* * Since we don't know whether snum is larger than sdiv, we pad snum * with enough zeroes without changing its value. */ if (snum->top <= sdiv->top + 1) { if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err; for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0; snum->top = sdiv->top + 2; } else { if (bn_wexpand(snum, snum->top + 1) == NULL) goto err; snum->d[snum->top] = 0; snum->top++; } } div_n = sdiv->top; num_n = snum->top; loop = num_n - div_n; /* * Lets setup a 'window' into snum This is the part that corresponds to * the current 'area' being divided */ wnum.neg = 0; wnum.d = &(snum->d[loop]); wnum.top = div_n; /* * only needed when BN_ucmp messes up the values between top and max */ wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ /* Get the top 2 words of sdiv */ /* div_n=sdiv->top; */ d0 = sdiv->d[div_n - 1]; d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; /* pointer to the 'top' of snum */ wnump = &(snum->d[num_n - 1]); /* Setup to 'res' */ res->neg = (num->neg ^ divisor->neg); if (!bn_wexpand(res, (loop + 1))) goto err; res->top = loop - no_branch; resp = &(res->d[loop - 1]); /* space for temp */ if (!bn_wexpand(tmp, (div_n + 1))) goto err; if (!no_branch) { if (BN_ucmp(&wnum, sdiv) >= 0) { /* * If BN_DEBUG_RAND is defined BN_ucmp changes (via bn_pollute) * the const bignum arguments => clean the values between top and * max again */ bn_clear_top2max(&wnum); bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n); *resp = 1; } else res->top--; } /* * if res->top == 0 then clear the neg value otherwise decrease the resp * pointer */ if (res->top == 0) res->neg = 0; else resp--; for (i = 0; i < loop - 1; i++, wnump--, resp--) { BN_ULONG q, l0; /* * the first part of the loop uses the top two words of snum and sdiv * to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv */ # if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG); q = bn_div_3_words(wnump, d1, d0); # else BN_ULONG n0, n1, rem = 0; n0 = wnump[0]; n1 = wnump[-1]; if (n0 == d0) q = BN_MASK2; else { /* n0 < d0 */ # ifdef BN_LLONG BN_ULLONG t2; # if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0); # else q = bn_div_words(n0, n1, d0); # endif # ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem = (n1 - q * d0) & BN_MASK2; # endif t2 = (BN_ULLONG) d1 *q; for (;;) { if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2])) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ t2 -= d1; } # else /* !BN_LLONG */ BN_ULONG t2l, t2h; q = bn_div_words(n0, n1, d0); # ifndef REMAINDER_IS_ALREADY_CALCULATED rem = (n1 - q * d0) & BN_MASK2; # endif # if defined(BN_UMULT_LOHI) BN_UMULT_LOHI(t2l, t2h, d1, q); # elif defined(BN_UMULT_HIGH) t2l = d1 * q; t2h = BN_UMULT_HIGH(d1, q); # else { BN_ULONG ql, qh; t2l = LBITS(d1); t2h = HBITS(d1); ql = LBITS(q); qh = HBITS(q); mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ } # endif for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } # endif /* !BN_LLONG */ } # endif /* !BN_DIV3W */ l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); tmp->d[div_n] = l0; wnum.d--; /* * ingore top values of the bignums just sub the two BN_ULONG arrays * with bn_sub_words */ if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { /* * Note: As we have considered only the leading two BN_ULONGs in * the calculation of q, sdiv * q might be greater than wnum (but * then (q-1) * sdiv is less or equal than wnum) */ q--; if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) /* * we can't have an overflow here (assuming that q != 0, but * if q == 0 then tmp is zero anyway) */ (*wnump)++; } /* store part of the result */ *resp = q; } bn_correct_top(snum); if (rm != NULL) { /* * Keep a copy of the neg flag in num because if rm==num BN_rshift() * will overwrite it. */ int neg = num->neg; BN_rshift(rm, snum, norm_shift); if (!BN_is_zero(rm)) rm->neg = neg; bn_check_top(rm); } if (no_branch) bn_correct_top(res); BN_CTX_end(ctx); return (1); err: bn_check_top(rm); BN_CTX_end(ctx); return (0); }
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. * It does not contain branches that may leak sensitive information. */ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM local_A, local_B; BIGNUM *pA, *pB; BIGNUM *ret=NULL; int sign; bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pB = &local_B; BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pA = &local_A; BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ if (!BN_div(D,M,pA,B,ctx)) goto err; /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ if (!BN_mul(tmp,D,X,ctx)) goto err; if (!BN_add(tmp,tmp,Y)) goto err; M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return(ret); }
int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; int top, al, bl; BIGNUM *rr; int i; BIGNUM *t = NULL; int j = 0, k; al = a->top; bl = b->top; if ((al == 0) || (bl == 0)) { BN_zero(r); return 1; } top = al + bl; BN_CTX_start(ctx); if ((r == a) || (r == b)) { if ((rr = BN_CTX_get(ctx)) == NULL) { goto err; } } else { rr = r; } rr->neg = a->neg ^ b->neg; i = al - bl; if (i == 0) { if (al == 8) { if (!bn_wexpand(rr, 16)) { goto err; } rr->top = 16; bn_mul_comba8(rr->d, a->d, b->d); goto end; } } static const int kMulNormalSize = 16; if (al >= kMulNormalSize && bl >= kMulNormalSize) { if (i >= -1 && i <= 1) { /* Find out the power of two lower or equal to the longest of the two numbers */ if (i >= 0) { j = BN_num_bits_word((BN_ULONG)al); } if (i == -1) { j = BN_num_bits_word((BN_ULONG)bl); } j = 1 << (j - 1); assert(j <= al || j <= bl); k = j + j; t = BN_CTX_get(ctx); if (t == NULL) { goto err; } if (al > j || bl > j) { if (!bn_wexpand(t, k * 4)) { goto err; } if (!bn_wexpand(rr, k * 4)) { goto err; } bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } else { /* al <= j || bl <= j */ if (!bn_wexpand(t, k * 2)) { goto err; } if (!bn_wexpand(rr, k * 2)) { goto err; } bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } rr->top = top; goto end; } } if (!bn_wexpand(rr, top)) { goto err; } rr->top = top; bn_mul_normal(rr->d, a->d, al, b->d, bl); end: bn_correct_top(rr); if (r != rr && !BN_copy(r, rr)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }