static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { 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) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_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 == NULL || r == NULL || order == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_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)) { ECerr(EC_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)) { ECerr(EC_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)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (EC_GROUP_get_mont_data(group) != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, 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 != ctx_in) BN_CTX_free(ctx); BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); 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, *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) { 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 */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { 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; } if (!EC_GROUP_get_order(group, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } 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. */ do { int ok; if (digest_len > 0) { ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), digest, digest_len, ctx); } else { ok = BN_rand_range(k, order); } if (!ok) { OPENSSL_PUT_ERROR(ECDSA, 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)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, X, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (!BN_mod_inverse(k, k, order, ctx)) { 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); } BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return ret; }
static int ecdsa_sign_setup(const 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, *kinv = 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(); kinv = 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 || kinv == 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); // Check that the size of the group order is FIPS compliant (FIPS 186-4 // B.5.2). if (BN_num_bits(order) < 160) { OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER); goto err; } 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 (eckey->fixed_k != NULL) { if (!BN_copy(k, eckey->fixed_k)) { goto err; } } else 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; } // Compute the inverse of k. The order is a prime, so use Fermat's Little // Theorem. Note |ec_group_get_order_mont| may return NULL but // |bn_mod_inverse_prime| allows this. if (!bn_mod_inverse_prime(kinv, k, order, ctx, ec_group_get_order_mont(group))) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 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)); // clear old values if necessary BN_clear_free(*rp); BN_clear_free(*kinvp); // save the pre-computed values *rp = r; *kinvp = kinv; ret = 1; err: BN_clear_free(k); if (!ret) { BN_clear_free(kinv); 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_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; }