SM2CiphertextValue *SM2_do_encrypt(const EVP_MD *md, const unsigned char *in, size_t inlen, EC_KEY *ec_key) { SM2CiphertextValue *ret = NULL; SM2CiphertextValue *cv = NULL; const EC_GROUP *group; const EC_POINT *pub_key; KDF_FUNC kdf; EC_POINT *ephem_point = NULL; EC_POINT *share_point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BIGNUM *k = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; int nbytes; size_t len; size_t i; unsigned int hashlen; /* check arguments */ if (!md || !in || !ec_key) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (inlen < SM2_MIN_PLAINTEXT_LENGTH || inlen > SM2_MAX_PLAINTEXT_LENGTH) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PLAINTEXT_LENGTH); return 0; } if (!(kdf = KDF_get_x9_63(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_DIGEST_ALGOR); return 0; } if (!(group = EC_KEY_get0_group(ec_key)) || !(pub_key = EC_KEY_get0_public_key(ec_key))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_EC_KEY); return 0; } /* malloc */ if (!(cv = SM2CiphertextValue_new()) || !(ephem_point = EC_POINT_new(group)) || !(share_point = EC_POINT_new(group)) || !(n = BN_new()) || !(h = BN_new()) || !(k = BN_new()) || !(bn_ctx = BN_CTX_new()) || !(md_ctx = EVP_MD_CTX_new())) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); goto end; } if (!ASN1_OCTET_STRING_set(cv->ciphertext, NULL, (int)inlen) || !ASN1_OCTET_STRING_set(cv->hash, NULL, EVP_MD_size(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_ASN1_LIB); goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(group, n, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } nbytes = (EC_GROUP_get_degree(group) + 7) / 8; /* check [h]P_B != O */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } if (EC_POINT_is_at_infinity(group, share_point)) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PUBLIC_KEY); goto end; } do { size_t size; /* rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* compute ephem_point [k]G = (x1, y1) */ if (!EC_POINT_mul(group, ephem_point, k, NULL, NULL, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute ECDH share_point [k]P_B = (x2, y2) */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, k, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute t = KDF(x2 || y2, klen) */ if (!(len = EC_POINT_point2oct(group, share_point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } size = cv->ciphertext->length; kdf(buf + 1, len - 1, cv->ciphertext->data, &size); if (size != inlen) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_KDF_FAILURE); goto end; } /* ASN1_OCTET_STRING_is_zero in asn1.h and a_octet.c */ } while (ASN1_OCTET_STRING_is_zero(cv->ciphertext)); /* set x/yCoordinates as (x1, y1) */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } /* ciphertext = t xor in */ for (i = 0; i < inlen; i++) { cv->ciphertext->data[i] ^= in[i]; } /* generate hash = Hash(x2 || M || y2) */ hashlen = cv->hash->length; if (!EVP_DigestInit_ex(md_ctx, md, NULL) || !EVP_DigestUpdate(md_ctx, buf + 1, nbytes) || !EVP_DigestUpdate(md_ctx, in, inlen) || !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes) || !EVP_DigestFinal_ex(md_ctx, cv->hash->data, &hashlen)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EVP_LIB); goto end; } ret = cv; cv = NULL; end: SM2CiphertextValue_free(cv); EC_POINT_free(share_point); EC_POINT_free(ephem_point); BN_free(n); BN_free(h); BN_clear_free(k); BN_CTX_free(bn_ctx); EVP_MD_CTX_free(md_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; }
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; }
ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0; BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; const BIGNUM *priv_key; if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); return NULL; } group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return NULL; } ret = ECDSA_SIG_new(); if (!ret) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } const BIGNUM *order = EC_GROUP_get0_order(group); if (!digest_to_bn(m, digest, digest_len, order)) { goto err; } for (;;) { if (in_kinv == NULL || in_r == NULL) { if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* if kinv and r have been supplied by the caller * don't to generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else { /* s != 0 => we have a valid signature */ break; } } ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } BN_CTX_free(ctx); BN_clear_free(m); BN_clear_free(tmp); BN_clear_free(kinv); 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_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; local_B.flags = 0; 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; local_A.flags = 0; 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 ECDSA_do_verify(const uint8_t *digest, size_t digest_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = 0; BN_CTX *ctx; BIGNUM *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if ((group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS); return 0; } ctx = BN_CTX_new(); if (!ctx) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } const BIGNUM *order = EC_GROUP_get0_order(group); if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!digest_to_bn(m, digest, digest_len, order)) { goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } point = EC_POINT_new(group); if (point == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(u1, X, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(point); return ret; }
/* random number r: 0 <= r < range */ static int bn_rand_range(int pseudo, BIGNUM *r, 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)) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); #endif /*End: comment out , 17Aug2006, Chris */ 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) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); #endif /*End: comment out , 17Aug2006, Chris */ 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) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); #endif /*End: comment out , 17Aug2006, Chris */ return 0; } } while (BN_cmp(r, range) >= 0); } bn_check_top(r); return 1; }
/*- * 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); res = (dv == NULL) ? BN_CTX_get(ctx) : dv; tmp = BN_CTX_get(ctx); snum = BN_CTX_get(ctx); sdiv = BN_CTX_get(ctx); if (sdiv == 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; wnum.flags = BN_FLG_STATIC_DATA; /* * 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' */ if (!bn_wexpand(res, (loop + 1))) goto err; res->neg = (num->neg ^ divisor->neg); 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--; } /* Increase the resp pointer so that we never create an invalid pointer. */ resp++; /* * 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--) { 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--; *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; }
int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec) { BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); BIGNUM *order; BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *X = NULL, *tmp = NULL; EC_POINT *C = NULL; const EC_POINT *pub_key = NULL; int ok = 0; if (ctx == NULL) goto err; BN_CTX_start(ctx); if ((order = BN_CTX_get(ctx)) == NULL) goto err; if ((e = BN_CTX_get(ctx)) == NULL) goto err; if ((z1 = BN_CTX_get(ctx)) == NULL) goto err; if ((z2 = BN_CTX_get(ctx)) == NULL) goto err; if ((tmp = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((R = BN_CTX_get(ctx)) == NULL) goto err; if ((v = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; pub_key = GOST_KEY_get0_public_key(ec); if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); goto err; } if (BN_mod(e, md, order, ctx) == 0) goto err; if (BN_is_zero(e)) BN_one(e); if ((v = BN_mod_inverse(v, e, order, ctx)) == NULL) goto err; if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0) goto err; if (BN_sub(tmp, order, sig->r) == 0) goto err; if (BN_mod_mul(z2, tmp, v, order, ctx) == 0) goto err; if ((C = EC_POINT_new(group)) == NULL) goto err; if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_mod(R, X, order, ctx) == 0) goto err; if (BN_cmp(R, sig->r) != 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } else { ok = 1; } err: EC_POINT_free(C); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }
int EC_KEY_check_key(const EC_KEY * eckey) { int ok = 0; BN_CTX *ctx = NULL; const BIGNUM *order = NULL; EC_POINT *point = NULL; if (!eckey || !eckey->group || !eckey->pub_key) { ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); goto err; } if ((ctx = BN_CTX_new()) == NULL) goto err; if ((point = EC_POINT_new(eckey->group)) == NULL) goto err; /* testing whether the pub_key is on the elliptic curve */ if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); goto err; } /* testing whether pub_key * order is the point at infinity */ order = &eckey->group->order; if (BN_is_zero(order)) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); goto err; } if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (!EC_POINT_is_at_infinity(eckey->group, point)) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } /* * in case the priv_key is present : check if generator * priv_key == * pub_key */ if (eckey->priv_key) { if (BN_cmp(eckey->priv_key, order) >= 0) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); goto err; } } ok = 1; err: BN_CTX_free(ctx); EC_POINT_free(point); return (ok); }
ECDSA_SIG * gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey) { ECDSA_SIG *newsig = NULL; BIGNUM *order = NULL; const EC_GROUP *group; const BIGNUM *priv_key; BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = NULL, *e = NULL; EC_POINT *C = NULL; BN_CTX *ctx = BN_CTX_new(); int ok = 0; if (ctx == NULL) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } BN_CTX_start(ctx); newsig = ECDSA_SIG_new(); if (newsig == NULL) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } s = newsig->s; r = newsig->r; group = GOST_KEY_get0_group(eckey); if ((order = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; priv_key = GOST_KEY_get0_private_key(eckey); if ((e = BN_CTX_get(ctx)) == NULL) goto err; if (BN_mod(e, md, order, ctx) == 0) goto err; if (BN_is_zero(e)) BN_one(e); if ((k = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((C = EC_POINT_new(group)) == NULL) goto err; do { do { if (!BN_rand_range(k, order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); goto err; } /* * We do not want timing information to leak the length * of k, so we compute G*k using an equivalent scalar * of fixed bit-length. */ if (BN_add(k, k, order) == 0) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (BN_add(k, k, order) == 0) goto err; if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (BN_nnmod(r, X, order, ctx) == 0) goto err; } while (BN_is_zero(r)); /* s = (r*priv_key+k*e) mod order */ if (tmp == NULL) { if ((tmp = BN_CTX_get(ctx)) == NULL) goto err; } if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0) goto err; if (tmp2 == NULL) { if ((tmp2 = BN_CTX_get(ctx)) == NULL) goto err; } if (BN_mod_mul(tmp2, k, e, order, ctx) == 0) goto err; if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0) goto err; } while (BN_is_zero(s)); ok = 1; err: EC_POINT_free(C); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (ok == 0) { ECDSA_SIG_free(newsig); newsig = NULL; } return newsig; }
int StealthSharedToSecretSpend(ec_secret& sharedS, ec_secret& spendSecret, ec_secret& secretOut) { int rv = 0; std::vector<uint8_t> vchOutP; BN_CTX* bnCtx = NULL; BIGNUM* bnc = NULL; BIGNUM* bnOrder = NULL; BIGNUM* bnSpend = NULL; EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ecgrp) { printf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n"); return 1; }; if (!(bnCtx = BN_CTX_new())) { printf("StealthSecretSpend(): BN_CTX_new failed.\n"); rv = 1; goto End; }; if (!(bnc = BN_bin2bn(&sharedS.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(bnOrder = BN_new()) || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx)) { printf("StealthSecretSpend(): EC_GROUP_get_order failed\n"); rv = 1; goto End; }; if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n"); rv = 1; goto End; }; //if (!BN_add(r, a, b)) return 0; //return BN_nnmod(r, r, m, ctx); if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx)) { printf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n"); rv = 1; goto End; }; if (BN_is_zero(bnSpend)) // possible? { printf("StealthSecretSpend(): bnSpend is zero.\n"); rv = 1; goto End; }; if (BN_num_bytes(bnSpend) != (int) ec_secret_size || BN_bn2bin(bnSpend, &secretOut.e[0]) != (int) ec_secret_size) { printf("StealthSecretSpend(): bnSpend incorrect length.\n"); rv = 1; goto End; }; End: if (bnSpend) BN_free(bnSpend); if (bnOrder) BN_free(bnOrder); if (bnc) BN_free(bnc); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); return rv; };
int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut) { /* c = H(dP) R' = R + cG [without decrypting wallet] = (f + c)G [after decryption of wallet] Remember: mod curve.order, pad with 0x00s where necessary? */ int rv = 0; std::vector<uint8_t> vchOutP; BN_CTX* bnCtx = NULL; BIGNUM* bnScanSecret = NULL; BIGNUM* bnP = NULL; EC_POINT* P = NULL; BIGNUM* bnOutP = NULL; BIGNUM* bnc = NULL; BIGNUM* bnOrder = NULL; BIGNUM* bnSpend = NULL; EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ecgrp) { printf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n"); return 1; }; if (!(bnCtx = BN_CTX_new())) { printf("StealthSecretSpend(): BN_CTX_new failed.\n"); rv = 1; goto End; }; if (!(bnScanSecret = BN_bin2bn(&scanSecret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): bnScanSecret BN_bin2bn failed.\n"); rv = 1; goto End; }; if (!(bnP = BN_bin2bn(&ephemPubkey[0], ephemPubkey.size(), BN_new()))) { printf("StealthSecretSpend(): bnP BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(P = EC_POINT_bn2point(ecgrp, bnP, NULL, bnCtx))) { printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n"); rv = 1; goto End; }; // -- dP if (!EC_POINT_mul(ecgrp, P, NULL, P, bnScanSecret, bnCtx)) { printf("StealthSecretSpend(): dP EC_POINT_mul failed\n"); rv = 1; goto End; }; if (!(bnOutP = EC_POINT_point2bn(ecgrp, P, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n"); rv = 1; goto End; }; vchOutP.resize(ec_compressed_size); if (BN_num_bytes(bnOutP) != (int) ec_compressed_size || BN_bn2bin(bnOutP, &vchOutP[0]) != (int) ec_compressed_size) { printf("StealthSecretSpend(): bnOutP incorrect length.\n"); rv = 1; goto End; }; uint8_t hash1[32]; SHA256(&vchOutP[0], vchOutP.size(), (uint8_t*)hash1); if (!(bnc = BN_bin2bn(&hash1[0], 32, BN_new()))) { printf("StealthSecretSpend(): BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(bnOrder = BN_new()) || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx)) { printf("StealthSecretSpend(): EC_GROUP_get_order failed\n"); rv = 1; goto End; }; if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n"); rv = 1; goto End; }; //if (!BN_add(r, a, b)) return 0; //return BN_nnmod(r, r, m, ctx); if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx)) { printf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n"); rv = 1; goto End; }; if (BN_is_zero(bnSpend)) // possible? { printf("StealthSecretSpend(): bnSpend is zero.\n"); rv = 1; goto End; }; if (BN_num_bytes(bnSpend) != (int) ec_secret_size || BN_bn2bin(bnSpend, &secretOut.e[0]) != (int) ec_secret_size) { printf("StealthSecretSpend(): bnSpend incorrect length.\n"); rv = 1; goto End; }; End: if (bnSpend) BN_free(bnSpend); if (bnOrder) BN_free(bnOrder); if (bnc) BN_free(bnc); if (bnOutP) BN_free(bnOutP); if (P) EC_POINT_free(P); if (bnP) BN_free(bnP); if (bnScanSecret) BN_free(bnScanSecret); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); return rv; };
static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) { BIGNUM *t; int shifts = 0; bn_check_top(a); bn_check_top(b); /* 0 <= b <= a */ while (!BN_is_zero(b)) { /* 0 < b <= a */ if (BN_is_odd(a)) { if (BN_is_odd(b)) { if (!BN_sub(a, a, b)) goto err; if (!BN_rshift1(a, a)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } else { /* a odd - b even */ if (!BN_rshift1(b, b)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } } else { /* a is even */ if (BN_is_odd(b)) { if (!BN_rshift1(a, a)) goto err; if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } } else { /* a even - b even */ if (!BN_rshift1(a, a)) goto err; if (!BN_rshift1(b, b)) goto err; shifts++; } } /* 0 <= b <= a */ } if (shifts) { if (!BN_lshift(a, a, shifts)) goto err; } bn_check_top(a); return (a); err: return (NULL); }
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 (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 { /* 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 test_div(BIO *bp, BN_CTX *ctx) { BIGNUM a,b,c,d,e; int i; BN_init(&a); BN_init(&b); BN_init(&c); BN_init(&d); BN_init(&e); for (i=0; i<num0+num1; i++) { if (i < num1) { BN_bntest_rand(&a,400,0,0); BN_copy(&b,&a); BN_lshift(&a,&a,i); BN_add_word(&a,i); } else BN_bntest_rand(&b,50+3*(i-num1),0,0); a.neg=rand_neg(); b.neg=rand_neg(); BN_div(&d,&c,&a,&b,ctx); if (bp != NULL) { if (!results) { BN_print(bp,&a); BIO_puts(bp," / "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&d); BIO_puts(bp,"\n"); if (!results) { BN_print(bp,&a); BIO_puts(bp," % "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&c); BIO_puts(bp,"\n"); } BN_mul(&e,&d,&b,ctx); BN_add(&d,&e,&c); BN_sub(&d,&d,&a); if(!BN_is_zero(&d)) { fprintf(stderr,"Division test failed!\n"); return 0; } } BN_free(&a); BN_free(&b); BN_free(&c); BN_free(&d); BN_free(&e); return(1); }
static int vg_regex_test(vg_exec_context_t *vxcp) { vg_regex_context_t *vcrp = (vg_regex_context_t *) vxcp->vxc_vc; unsigned char hash1[32], hash2[32]; int i, zpfx, p, d, nres, re_vec[9]; char b58[40]; BIGNUM bnrem; BIGNUM *bn, *bndiv, *bnptmp; int res = 0; pcre *re; BN_init(&bnrem); /* Hash the hash and write the four byte check code */ SHA256(vxcp->vxc_binres, 21, hash1); SHA256(hash1, sizeof(hash1), hash2); memcpy(&vxcp->vxc_binres[21], hash2, 4); bn = &vxcp->vxc_bntmp; bndiv = &vxcp->vxc_bntmp2; BN_bin2bn(vxcp->vxc_binres, 25, bn); /* Compute the complete encoded address */ for (zpfx = 0; zpfx < 25 && vxcp->vxc_binres[zpfx] == 0; zpfx++); p = sizeof(b58) - 1; b58[p] = '\0'; while (!BN_is_zero(bn)) { BN_div(bndiv, &bnrem, bn, &vxcp->vxc_bnbase, vxcp->vxc_bnctx); bnptmp = bn; bn = bndiv; bndiv = bnptmp; d = BN_get_word(&bnrem); b58[--p] = vg_b58_alphabet[d]; } while (zpfx--) { b58[--p] = vg_b58_alphabet[0]; } /* * Run the regular expressions on it * SLOW, runs in linear time with the number of REs */ restart_loop: nres = vcrp->base.vc_npatterns; if (!nres) { res = 2; goto out; } for (i = 0; i < nres; i++) { d = pcre_exec(vcrp->vcr_regex[i], vcrp->vcr_regex_extra[i], &b58[p], (sizeof(b58) - 1) - p, 0, 0, re_vec, sizeof(re_vec)/sizeof(re_vec[0])); if (d <= 0) { if (d != PCRE_ERROR_NOMATCH) { fprintf(stderr, "PCRE error: %d\n", d); res = 2; goto out; } continue; } re = vcrp->vcr_regex[i]; if (vg_exec_context_upgrade_lock(vxcp) && ((i >= vcrp->base.vc_npatterns) || (vcrp->vcr_regex[i] != re))) goto restart_loop; vg_exec_context_consolidate_key(vxcp); vcrp->base.vc_output_match(&vcrp->base, vxcp->vxc_key, vcrp->vcr_regex_pat[i]); vcrp->base.vc_found++; if (vcrp->base.vc_only_one) { res = 2; goto out; } if (vcrp->base.vc_remove_on_match) { pcre_free(vcrp->vcr_regex[i]); if (vcrp->vcr_regex_extra[i]) pcre_free(vcrp->vcr_regex_extra[i]); nres -= 1; vcrp->base.vc_npatterns = nres; if (!nres) { res = 2; goto out; } vcrp->vcr_regex[i] = vcrp->vcr_regex[nres]; vcrp->vcr_regex_extra[i] = vcrp->vcr_regex_extra[nres]; vcrp->vcr_regex_pat[i] = vcrp->vcr_regex_pat[nres]; vcrp->base.vc_npatterns = nres; vcrp->base.vc_pattern_generation++; } res = 1; } out: BN_clear_free(&bnrem); return res; }
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0, i; BIGNUM *kinv=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; const BIGNUM *priv_key; ecdsa = ecdsa_check(eckey); group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL || ecdsa == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); return NULL; } ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; } i = BN_num_bits(order); /* Need to truncate digest if it is too long: first truncate whole * bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7)/8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } do { if (in_kinv == NULL || in_r == NULL) { if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* if kinv and r have been supplied by the caller * don't to generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else /* s != 0 => we have a valid signature */ break; } while (1); ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } if (ctx) BN_CTX_free(ctx); if (m) BN_clear_free(m); if (tmp) BN_clear_free(tmp); if (order) BN_free(order); if (kinv) BN_clear_free(kinv); return ret; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const uint8_t *digest, size_t digest_len) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *tmp = NULL; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return 0; } } else { ctx = ctx_in; } k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ tmp = BN_new(); if (k == NULL || r == NULL || tmp == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } tmp_point = EC_POINT_new(group); if (tmp_point == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } const BIGNUM *order = EC_GROUP_get0_order(group); do { /* If possible, we'll include the private key and message digest in the k * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is * being used. */ if (digest_len > 0) { do { if (!BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), digest, digest_len, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); } else if (!BN_rand_range_ex(k, 1, order)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } /* We do not want timing information to leak the length of k, * so we compute G*k using an equivalent scalar of fixed * bit-length. */ if (!BN_add(k, k, order)) { goto err; } if (BN_num_bits(k) <= BN_num_bits(order)) { if (!BN_add(k, k, order)) { goto err; } } /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, tmp, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, tmp, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* Compute the inverse of k. The order is a prime, so use Fermat's Little * Theorem. */ if (!BN_set_word(tmp, 2) || !BN_sub(tmp, order, tmp) || /* Note |ec_group_get_mont_data| may return NULL but |BN_mod_exp_mont| * allows it to be. */ !BN_mod_exp_mont(k, k, tmp, order, ctx, ec_group_get_mont_data(group))) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx_in == NULL) { BN_CTX_free(ctx); } EC_POINT_free(tmp_point); BN_clear_free(tmp); return ret; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ i = BN_num_bits(order); /* Need to truncate digest if it is too long: first truncate whole * bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7)/8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (point) EC_POINT_free(point); 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; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point=NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } while (BN_is_zero(k)); /* We do not want timing information to leak the length of k, * so we compute G*k using an equivalent scalar of fixed * bit-length. */ if (!BN_add(k, k, order)) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (!BN_add(k, k, order)) goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); if (*kinvp != NULL) BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order != NULL) BN_free(order); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return(ret); }
/* * 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; }
/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. * This is an array r[] of values that are either zero or odd with an * absolute value less than 2^w satisfying * scalar = \sum_j r[j]*2^j * where at most one of any w+1 consecutive digits is non-zero * with the exception that the most significant digit may be only * w-1 zeros away from that next non-zero digit. */ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { int window_val; int ok = 0; signed char *r = NULL; int sign = 1; int bit, next_bit, mask; size_t len = 0, j; if (BN_is_zero(scalar)) { r = OPENSSL_malloc(1); if (!r) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } r[0] = 0; *ret_len = 1; return r; } if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */ { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } bit = 1 << w; /* at most 128 */ next_bit = bit << 1; /* at most 256 */ mask = next_bit - 1; /* at most 255 */ if (BN_is_negative(scalar)) { sign = -1; } if (scalar->d == NULL || scalar->top == 0) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } len = BN_num_bits(scalar); r = OPENSSL_malloc( len + 1); /* modified wNAF may be one digit longer than binary representation * (*ret_len will be set to the actual length, i.e. at most * BN_num_bits(scalar) + 1) */ if (r == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } window_val = scalar->d[0] & mask; j = 0; while ((window_val != 0) || (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */ { int digit = 0; /* 0 <= window_val <= 2^(w+1) */ if (window_val & 1) { /* 0 < window_val < 2^(w+1) */ if (window_val & bit) { digit = window_val - next_bit; /* -2^w < digit < 0 */ #if 1 /* modified wNAF */ if (j + w + 1 >= len) { /* special case for generating modified wNAFs: * no new bits will be added into window_val, * so using a positive digit here will decrease * the total length of the representation */ digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ } #endif } else {
/* Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) { BIGNUM *x1, *x2, *z1, *z2; int ret = 0, i; BN_ULONG mask, word; if (r == point) { ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); return 0; } /* if result should be point at infinity */ if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || EC_POINT_is_at_infinity(group, point)) { return EC_POINT_set_to_infinity(group, r); } /* only support affine coordinates */ if (!point->Z_is_one) return 0; /* Since point_multiply is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); x1 = BN_CTX_get(ctx); z1 = BN_CTX_get(ctx); if (z1 == NULL) goto err; x2 = &r->X; z2 = &r->Y; bn_wexpand(x1, group->field.top); bn_wexpand(z1, group->field.top); bn_wexpand(x2, group->field.top); bn_wexpand(z2, group->field.top); if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ if (!BN_one(z1)) goto err; /* z1 = 1 */ if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ /* find top most bit and go one past it */ i = scalar->top - 1; mask = BN_TBIT; word = scalar->d[i]; while (!(word & mask)) mask >>= 1; mask >>= 1; /* if top most bit was at word break, go to next word */ if (!mask) { i--; mask = BN_TBIT; } for (; i >= 0; i--) { word = scalar->d[i]; while (mask) { BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); mask >>= 1; } mask = BN_TBIT; } /* convert out of "projective" coordinates */ i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); if (i == 0) goto err; else if (i == 1) { if (!EC_POINT_set_to_infinity(group, r)) goto err; } else { if (!BN_one(&r->Z)) goto err; r->Z_is_one = 1; } /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ BN_set_negative(&r->X, 0); BN_set_negative(&r->Y, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
static void pollard_rho(BIGNUM *val) { BIGNUM *x, *y, *tmp, *num; BN_ULONG a; unsigned int steps_taken, steps_limit; x = BN_new(); y = BN_new(); tmp = BN_new(); num = BN_new(); a = 1; restart: steps_taken = 0; steps_limit = 2; BN_set_word(x, 1); BN_copy(y, x); for (;;) { BN_sqr(tmp, x, ctx); BN_add_word(tmp, a); BN_mod(x, tmp, val, ctx); BN_sub(tmp, x, y); if (BN_is_zero(tmp)) { #ifdef DEBUG printf(" (loop)"); #endif a++; goto restart; } BN_gcd(tmp, tmp, val, ctx); if (!BN_is_one(tmp)) { if (BN_is_prime(tmp, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, tmp); } else { #ifdef DEBUG printf(" (recurse for "); BN_print_dec_fp(stdout, tmp); putchar(')'); #endif pollard_rho(BN_dup(tmp)); #ifdef DEBUG printf(" (back)"); #endif } fflush(stdout); BN_div(num, NULL, val, tmp, ctx); if (BN_is_one(num)) return; if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, num); fflush(stdout); return; } BN_copy(val, num); goto restart; } steps_taken++; if (steps_taken == steps_limit) { BN_copy(y, x); /* teleport the turtle */ steps_taken = 0; steps_limit *= 2; if (steps_limit == 0) { #ifdef DEBUG printf(" (overflow)"); #endif a++; goto restart; } } } }
static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { BIGNUM *r1, *m1, *vrfy; BIGNUM *local_dmp1, *local_dmq1, *local_c, *local_r1; BIGNUM *dmp1, *dmq1, *c, *pr1; int ret = 0; BN_CTX_start(ctx); local_dmp1 = BN_new(); local_dmq1 = BN_new(); local_c = BN_new(); local_r1 = BN_new(); if (!local_dmp1 || !local_dmq1 || !local_c || !local_r1) goto err; r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); { BIGNUM *local_p = NULL, *local_q = NULL; BIGNUM *p = NULL, *q = NULL; /* * Make sure BN_mod_inverse in Montgomery intialization uses the * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { local_p = p = BN_new(); if (!p) goto err; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); local_q = q = BN_new(); if (!q) { BN_free(local_p); goto err; } BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); } else { p = rsa->p; q = rsa->q; } if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { if (!BN_MONT_CTX_set_locked (&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx) || !BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx)) { BN_free(local_p); BN_free(local_q); goto err; } } BN_free(local_p); BN_free(local_q); } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) if (!BN_MONT_CTX_set_locked (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) goto err; /* compute I mod q */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { c = local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->q, ctx)) goto err; } else { if (!BN_mod(r1, I, rsa->q, ctx)) goto err; } /* compute r1^dmq1 mod q */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { dmq1 = local_dmq1; BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); } else dmq1 = rsa->dmq1; if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q)) goto err; /* compute I mod p */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { c = local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->p, ctx)) goto err; } else { if (!BN_mod(r1, I, rsa->p, ctx)) goto err; } /* compute r1^dmp1 mod p */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { dmp1 = local_dmp1; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); } else dmp1 = rsa->dmp1; if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p)) goto err; if (!BN_sub(r0, r0, m1)) goto err; /* * This will help stop the size of r0 increasing, which does affect the * multiply if it optimised for a power of 2 size */ if (BN_is_negative(r0)) if (!BN_add(r0, r0, rsa->p)) goto err; if (!BN_mul(r1, r0, rsa->iqmp, ctx)) goto err; /* Turn BN_FLG_CONSTTIME flag on before division operation */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { pr1 = local_r1; BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); } else pr1 = r1; if (!BN_mod(r0, pr1, rsa->p, ctx)) goto err; /* * If p < q it is occasionally possible for the correction of adding 'p' * if r0 is negative above to leave the result still negative. This can * break the private key operations: the following second correction * should *always* correct this rare occurrence. This will *never* happen * with OpenSSL generated keys because they ensure p > q [steve] */ if (BN_is_negative(r0)) if (!BN_add(r0, r0, rsa->p)) goto err; if (!BN_mul(r1, r0, rsa->q, ctx)) goto err; if (!BN_add(r0, r1, m1)) goto err; if (rsa->e && rsa->n) { if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) goto err; /* * If 'I' was greater than (or equal to) rsa->n, the operation will * be equivalent to using 'I mod n'. However, the result of the * verify will *always* be less than 'n' so we don't check for * absolute equality, just congruency. */ if (!BN_sub(vrfy, vrfy, I)) goto err; if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) goto err; if (BN_is_negative(vrfy)) if (!BN_add(vrfy, vrfy, rsa->n)) goto err; if (!BN_is_zero(vrfy)) { /* * 'I' and 'vrfy' aren't congruent mod n. Don't leak * miscalculated CRT output, just do a raw (slower) mod_exp and * return that instead. */ BIGNUM *local_d = NULL; BIGNUM *d = NULL; if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { local_d = d = BN_new(); if (!d) goto err; BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); } else d = rsa->d; if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->_method_mod_n)) { BN_free(local_d); goto err; } BN_free(local_d); } } ret = 1; err: BN_free(local_dmp1); BN_free(local_dmq1); BN_free(local_c); BN_free(local_r1); BN_CTX_end(ctx); return (ret); }
static int parse_prime(int linenum, char *line, struct dhgroup *dhg) { char *cp, *arg; char *strsize, *gen, *prime; const char *errstr = NULL; long long n; cp = line; if ((arg = strdelim(&cp)) == NULL) return 0; /* Ignore leading whitespace */ if (*arg == '\0') arg = strdelim(&cp); if (!arg || !*arg || *arg == '#') return 0; /* time */ if (cp == NULL || *arg == '\0') goto fail; arg = strsep(&cp, " "); /* type */ if (cp == NULL || *arg == '\0') goto fail; /* Ensure this is a safe prime */ n = strtonum(arg, 0, 5, &errstr); if (errstr != NULL || n != MODULI_TYPE_SAFE) goto fail; arg = strsep(&cp, " "); /* tests */ if (cp == NULL || *arg == '\0') goto fail; /* Ensure prime has been tested and is not composite */ n = strtonum(arg, 0, 0x1f, &errstr); if (errstr != NULL || (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) goto fail; arg = strsep(&cp, " "); /* tries */ if (cp == NULL || *arg == '\0') goto fail; n = strtonum(arg, 0, 1<<30, &errstr); if (errstr != NULL || n == 0) goto fail; strsize = strsep(&cp, " "); /* size */ if (cp == NULL || *strsize == '\0' || (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || errstr) goto fail; /* The whole group is one bit larger */ dhg->size++; gen = strsep(&cp, " "); /* gen */ if (cp == NULL || *gen == '\0') goto fail; prime = strsep(&cp, " "); /* prime */ if (cp != NULL || *prime == '\0') goto fail; if ((dhg->g = BN_new()) == NULL) fatal("parse_prime: BN_new failed"); if ((dhg->p = BN_new()) == NULL) fatal("parse_prime: BN_new failed"); if (BN_hex2bn(&dhg->g, gen) == 0) goto failclean; if (BN_hex2bn(&dhg->p, prime) == 0) goto failclean; if (BN_num_bits(dhg->p) != dhg->size) goto failclean; if (BN_is_zero(dhg->g) || BN_is_one(dhg->g)) goto failclean; return (1); failclean: BN_clear_free(dhg->g); BN_clear_free(dhg->p); fail: error("Bad prime description in line %d", linenum); return (0); }