update master-with-bazel from master branch
This commit is contained in:
@@ -62,34 +62,87 @@
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../bytestring/internal.h"
|
||||
#include "../fipsmodule/ec/internal.h"
|
||||
#include "../fipsmodule/ecdsa/internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static ECDSA_SIG *ecdsa_sig_from_fixed(const EC_KEY *key, const uint8_t *in,
|
||||
size_t len) {
|
||||
const EC_GROUP *group = EC_KEY_get0_group(key);
|
||||
if (group == NULL) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
||||
if (len != 2 * scalar_len) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
ECDSA_SIG *ret = ECDSA_SIG_new();
|
||||
if (ret == NULL ||
|
||||
!BN_bin2bn(in, scalar_len, ret->r) ||
|
||||
!BN_bin2bn(in + scalar_len, scalar_len, ret->s)) {
|
||||
ECDSA_SIG_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ecdsa_sig_to_fixed(const EC_KEY *key, uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const ECDSA_SIG *sig) {
|
||||
const EC_GROUP *group = EC_KEY_get0_group(key);
|
||||
if (group == NULL) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
||||
if (max_out < 2 * scalar_len) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (BN_is_negative(sig->r) ||
|
||||
!BN_bn2bin_padded(out, scalar_len, sig->r) ||
|
||||
BN_is_negative(sig->s) ||
|
||||
!BN_bn2bin_padded(out + scalar_len, scalar_len, sig->s)) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
|
||||
return 0;
|
||||
}
|
||||
*out_len = 2 * scalar_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
|
||||
unsigned int *sig_len, const EC_KEY *eckey) {
|
||||
unsigned int *out_sig_len, const EC_KEY *eckey) {
|
||||
if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
|
||||
return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len,
|
||||
return eckey->ecdsa_meth->sign(digest, digest_len, sig, out_sig_len,
|
||||
(EC_KEY*) eckey /* cast away const */);
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
ECDSA_SIG *s = ECDSA_do_sign(digest, digest_len, eckey);
|
||||
if (s == NULL) {
|
||||
*sig_len = 0;
|
||||
goto err;
|
||||
*out_sig_len = 0;
|
||||
uint8_t fixed[ECDSA_MAX_FIXED_LEN];
|
||||
size_t fixed_len;
|
||||
if (!ecdsa_sign_fixed(digest, digest_len, fixed, &fixed_len, sizeof(fixed),
|
||||
eckey)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(davidben): We can actually do better and go straight from the DER
|
||||
// format to the fixed-width format without a malloc.
|
||||
ECDSA_SIG *s = ecdsa_sig_from_fixed(eckey, fixed, fixed_len);
|
||||
if (s == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
CBB cbb;
|
||||
CBB_init_fixed(&cbb, sig, ECDSA_size(eckey));
|
||||
size_t len;
|
||||
if (!ECDSA_SIG_marshal(&cbb, s) ||
|
||||
!CBB_finish(&cbb, NULL, &len)) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
|
||||
*sig_len = 0;
|
||||
goto err;
|
||||
}
|
||||
*sig_len = (unsigned)len;
|
||||
*out_sig_len = (unsigned)len;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
@@ -99,12 +152,13 @@ err:
|
||||
|
||||
int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len, const EC_KEY *eckey) {
|
||||
ECDSA_SIG *s;
|
||||
// Decode the ECDSA signature.
|
||||
//
|
||||
// TODO(davidben): We can actually do better and go straight from the DER
|
||||
// format to the fixed-width format without a malloc.
|
||||
int ret = 0;
|
||||
uint8_t *der = NULL;
|
||||
|
||||
// Decode the ECDSA signature.
|
||||
s = ECDSA_SIG_from_bytes(sig, sig_len);
|
||||
ECDSA_SIG *s = ECDSA_SIG_from_bytes(sig, sig_len);
|
||||
if (s == NULL) {
|
||||
goto err;
|
||||
}
|
||||
@@ -118,7 +172,10 @@ int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ECDSA_do_verify(digest, digest_len, s, eckey);
|
||||
uint8_t fixed[ECDSA_MAX_FIXED_LEN];
|
||||
size_t fixed_len;
|
||||
ret = ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), s) &&
|
||||
ecdsa_verify_fixed(digest, digest_len, fixed, fixed_len, eckey);
|
||||
|
||||
err:
|
||||
OPENSSL_free(der);
|
||||
@@ -147,6 +204,95 @@ size_t ECDSA_size(const EC_KEY *key) {
|
||||
return ECDSA_SIG_max_len(group_order_size);
|
||||
}
|
||||
|
||||
ECDSA_SIG *ECDSA_SIG_new(void) {
|
||||
ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sig->r = BN_new();
|
||||
sig->s = BN_new();
|
||||
if (sig->r == NULL || sig->s == NULL) {
|
||||
ECDSA_SIG_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
void ECDSA_SIG_free(ECDSA_SIG *sig) {
|
||||
if (sig == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BN_free(sig->r);
|
||||
BN_free(sig->s);
|
||||
OPENSSL_free(sig);
|
||||
}
|
||||
|
||||
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig) {
|
||||
return sig->r;
|
||||
}
|
||||
|
||||
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig) {
|
||||
return sig->s;
|
||||
}
|
||||
|
||||
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **out_r,
|
||||
const BIGNUM **out_s) {
|
||||
if (out_r != NULL) {
|
||||
*out_r = sig->r;
|
||||
}
|
||||
if (out_s != NULL) {
|
||||
*out_s = sig->s;
|
||||
}
|
||||
}
|
||||
|
||||
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
|
||||
if (r == NULL || s == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BN_free(sig->r);
|
||||
BN_free(sig->s);
|
||||
sig->r = r;
|
||||
sig->s = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
|
||||
const ECDSA_SIG *sig, const EC_KEY *eckey) {
|
||||
uint8_t fixed[ECDSA_MAX_FIXED_LEN];
|
||||
size_t fixed_len;
|
||||
return ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), sig) &&
|
||||
ecdsa_verify_fixed(digest, digest_len, fixed, fixed_len, eckey);
|
||||
}
|
||||
|
||||
// This function is only exported for testing and is not called in production
|
||||
// code.
|
||||
ECDSA_SIG *ECDSA_sign_with_nonce_and_leak_private_key_for_testing(
|
||||
const uint8_t *digest, size_t digest_len, const EC_KEY *eckey,
|
||||
const uint8_t *nonce, size_t nonce_len) {
|
||||
uint8_t sig[ECDSA_MAX_FIXED_LEN];
|
||||
size_t sig_len;
|
||||
if (!ecdsa_sign_fixed_with_nonce_for_known_answer_test(
|
||||
digest, digest_len, sig, &sig_len, sizeof(sig), eckey, nonce,
|
||||
nonce_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ecdsa_sig_from_fixed(eckey, sig, sig_len);
|
||||
}
|
||||
|
||||
ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
|
||||
const EC_KEY *eckey) {
|
||||
uint8_t sig[ECDSA_MAX_FIXED_LEN];
|
||||
size_t sig_len;
|
||||
if (!ecdsa_sign_fixed(digest, digest_len, sig, &sig_len, sizeof(sig),
|
||||
eckey)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ecdsa_sig_from_fixed(eckey, sig, sig_len);
|
||||
}
|
||||
|
||||
ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) {
|
||||
ECDSA_SIG *ret = ECDSA_SIG_new();
|
||||
if (ret == NULL) {
|
||||
|
||||
@@ -196,7 +196,7 @@ int BORINGSSL_integrity_test(void) {
|
||||
assert_within(start, RAND_bytes, end);
|
||||
assert_within(start, EC_GROUP_cmp, end);
|
||||
assert_within(start, SHA256_Update, end);
|
||||
assert_within(start, ECDSA_do_verify, end);
|
||||
assert_within(start, ecdsa_verify_fixed, end);
|
||||
assert_within(start, EVP_AEAD_CTX_seal, end);
|
||||
|
||||
#if defined(BORINGSSL_SHARED_LIBRARY)
|
||||
|
||||
@@ -75,10 +75,12 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ex_data.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../delocate.h"
|
||||
#include "../ecdsa/internal.h"
|
||||
#include "../service_indicator/internal.h"
|
||||
#include "../../internal.h"
|
||||
|
||||
@@ -344,15 +346,17 @@ int EC_KEY_check_fips(const EC_KEY *key) {
|
||||
}
|
||||
|
||||
if (key->priv_key) {
|
||||
uint8_t data[16] = {0};
|
||||
ECDSA_SIG *sig = ECDSA_do_sign(data, sizeof(data), key);
|
||||
if (boringssl_fips_break_test("ECDSA_PWCT")) {
|
||||
data[0] = ~data[0];
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
uint8_t sig[ECDSA_MAX_FIXED_LEN];
|
||||
size_t sig_len;
|
||||
if (!ecdsa_sign_fixed(digest, sizeof(digest), sig, &sig_len, sizeof(sig),
|
||||
key)) {
|
||||
goto end;
|
||||
}
|
||||
int ok = sig != NULL &&
|
||||
ECDSA_do_verify(data, sizeof(data), sig, key);
|
||||
ECDSA_SIG_free(sig);
|
||||
if (!ok) {
|
||||
if (boringssl_fips_break_test("ECDSA_PWCT")) {
|
||||
digest[0] = ~digest[0];
|
||||
}
|
||||
if (!ecdsa_verify_fixed(digest, sizeof(digest), sig, sig_len, key)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_PUBLIC_KEY_VALIDATION_FAILED);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -95,61 +95,9 @@ static void digest_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
order->width);
|
||||
}
|
||||
|
||||
ECDSA_SIG *ECDSA_SIG_new(void) {
|
||||
ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sig->r = BN_new();
|
||||
sig->s = BN_new();
|
||||
if (sig->r == NULL || sig->s == NULL) {
|
||||
ECDSA_SIG_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
void ECDSA_SIG_free(ECDSA_SIG *sig) {
|
||||
if (sig == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BN_free(sig->r);
|
||||
BN_free(sig->s);
|
||||
OPENSSL_free(sig);
|
||||
}
|
||||
|
||||
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig) {
|
||||
return sig->r;
|
||||
}
|
||||
|
||||
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig) {
|
||||
return sig->s;
|
||||
}
|
||||
|
||||
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **out_r,
|
||||
const BIGNUM **out_s) {
|
||||
if (out_r != NULL) {
|
||||
*out_r = sig->r;
|
||||
}
|
||||
if (out_s != NULL) {
|
||||
*out_s = sig->s;
|
||||
}
|
||||
}
|
||||
|
||||
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
|
||||
if (r == NULL || s == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BN_free(sig->r);
|
||||
BN_free(sig->s);
|
||||
sig->r = r;
|
||||
sig->s = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_do_verify_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
const ECDSA_SIG *sig, const EC_KEY *eckey) {
|
||||
int ecdsa_verify_fixed_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len,
|
||||
const EC_KEY *eckey) {
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
const EC_POINT *pub_key = EC_KEY_get0_public_key(eckey);
|
||||
if (group == NULL || pub_key == NULL || sig == NULL) {
|
||||
@@ -157,11 +105,13 @@ int ecdsa_do_verify_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
||||
EC_SCALAR r, s, u1, u2, s_inv_mont, m;
|
||||
if (BN_is_zero(sig->r) ||
|
||||
!ec_bignum_to_scalar(group, &r, sig->r) ||
|
||||
BN_is_zero(sig->s) ||
|
||||
!ec_bignum_to_scalar(group, &s, sig->s)) {
|
||||
if (sig_len != 2 * scalar_len ||
|
||||
!ec_scalar_from_bytes(group, &r, sig, scalar_len) ||
|
||||
ec_scalar_is_zero(group, &r) ||
|
||||
!ec_scalar_from_bytes(group, &s, sig + scalar_len, scalar_len) ||
|
||||
ec_scalar_is_zero(group, &s)) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
|
||||
return 0;
|
||||
}
|
||||
@@ -195,24 +145,31 @@ int ecdsa_do_verify_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
|
||||
const ECDSA_SIG *sig, const EC_KEY *eckey) {
|
||||
int ecdsa_verify_fixed(const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len, const EC_KEY *key) {
|
||||
boringssl_ensure_ecc_self_test();
|
||||
|
||||
return ecdsa_do_verify_no_self_test(digest, digest_len, sig, eckey);
|
||||
return ecdsa_verify_fixed_no_self_test(digest, digest_len, sig, sig_len, key);
|
||||
}
|
||||
|
||||
static ECDSA_SIG *ecdsa_sign_impl(const EC_GROUP *group, int *out_retry,
|
||||
const EC_SCALAR *priv_key, const EC_SCALAR *k,
|
||||
const uint8_t *digest, size_t digest_len) {
|
||||
static int ecdsa_sign_impl(const EC_GROUP *group, int *out_retry, uint8_t *sig,
|
||||
size_t *out_sig_len, size_t max_sig_len,
|
||||
const EC_SCALAR *priv_key, const EC_SCALAR *k,
|
||||
const uint8_t *digest, size_t digest_len) {
|
||||
*out_retry = 0;
|
||||
|
||||
// Check that the size of the group order is FIPS compliant (FIPS 186-4
|
||||
// B.5.2).
|
||||
const BIGNUM *order = EC_GROUP_get0_order(group);
|
||||
if (BN_num_bits(order) < 160) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER);
|
||||
return NULL;
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t sig_len = 2 * BN_num_bytes(order);
|
||||
if (sig_len > max_sig_len) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compute r, the x-coordinate of k * generator.
|
||||
@@ -220,12 +177,12 @@ static ECDSA_SIG *ecdsa_sign_impl(const EC_GROUP *group, int *out_retry,
|
||||
EC_SCALAR r;
|
||||
if (!ec_point_mul_scalar_base(group, &tmp_point, k) ||
|
||||
!ec_get_x_coordinate_as_scalar(group, &r, &tmp_point)) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (constant_time_declassify_int(ec_scalar_is_zero(group, &r))) {
|
||||
*out_retry = 1;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// s = priv_key * r. Note if only one parameter is in the Montgomery domain,
|
||||
@@ -252,71 +209,59 @@ static ECDSA_SIG *ecdsa_sign_impl(const EC_GROUP *group, int *out_retry,
|
||||
ec_scalar_mul_montgomery(group, &s, &s, &tmp);
|
||||
if (constant_time_declassify_int(ec_scalar_is_zero(group, &s))) {
|
||||
*out_retry = 1;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CONSTTIME_DECLASSIFY(r.words, sizeof(r.words));
|
||||
CONSTTIME_DECLASSIFY(s.words, sizeof(r.words));
|
||||
ECDSA_SIG *ret = ECDSA_SIG_new();
|
||||
if (ret == NULL || //
|
||||
!bn_set_words(ret->r, r.words, order->width) ||
|
||||
!bn_set_words(ret->s, s.words, order->width)) {
|
||||
ECDSA_SIG_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
size_t len;
|
||||
ec_scalar_to_bytes(group, sig, &len, &r);
|
||||
assert(len == sig_len / 2);
|
||||
ec_scalar_to_bytes(group, sig + len, &len, &s);
|
||||
assert(len == sig_len / 2);
|
||||
*out_sig_len = sig_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ECDSA_SIG *ecdsa_sign_with_nonce_for_known_answer_test(const uint8_t *digest,
|
||||
size_t digest_len,
|
||||
const EC_KEY *eckey,
|
||||
const uint8_t *nonce,
|
||||
size_t nonce_len) {
|
||||
int ecdsa_sign_fixed_with_nonce_for_known_answer_test(
|
||||
const uint8_t *digest, size_t digest_len, uint8_t *sig, size_t *out_sig_len,
|
||||
size_t max_sig_len, const EC_KEY *eckey, const uint8_t *nonce,
|
||||
size_t nonce_len) {
|
||||
if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if (group == NULL || eckey->priv_key == NULL) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
const EC_SCALAR *priv_key = &eckey->priv_key->scalar;
|
||||
|
||||
EC_SCALAR k;
|
||||
if (!ec_scalar_from_bytes(group, &k, nonce, nonce_len)) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
int retry_ignored;
|
||||
return ecdsa_sign_impl(group, &retry_ignored, priv_key, &k, digest,
|
||||
digest_len);
|
||||
return ecdsa_sign_impl(group, &retry_ignored, sig, out_sig_len, max_sig_len,
|
||||
priv_key, &k, digest, digest_len);
|
||||
}
|
||||
|
||||
// This function is only exported for testing and is not called in production
|
||||
// code.
|
||||
ECDSA_SIG *ECDSA_sign_with_nonce_and_leak_private_key_for_testing(
|
||||
const uint8_t *digest, size_t digest_len, const EC_KEY *eckey,
|
||||
const uint8_t *nonce, size_t nonce_len) {
|
||||
boringssl_ensure_ecc_self_test();
|
||||
|
||||
return ecdsa_sign_with_nonce_for_known_answer_test(digest, digest_len, eckey,
|
||||
nonce, nonce_len);
|
||||
}
|
||||
|
||||
ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
|
||||
const EC_KEY *eckey) {
|
||||
int ecdsa_sign_fixed(const uint8_t *digest, size_t digest_len, uint8_t *sig,
|
||||
size_t *out_sig_len, size_t max_sig_len,
|
||||
const EC_KEY *eckey) {
|
||||
boringssl_ensure_ecc_self_test();
|
||||
|
||||
if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if (group == NULL || eckey->priv_key == NULL) {
|
||||
OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
const BIGNUM *order = EC_GROUP_get0_order(group);
|
||||
const EC_SCALAR *priv_key = &eckey->priv_key->scalar;
|
||||
@@ -340,12 +285,11 @@ ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
|
||||
// FIPS) because the probability of requiring even one retry is negligible,
|
||||
// let alone 32.
|
||||
static const int kMaxIterations = 32;
|
||||
ECDSA_SIG *ret = NULL;
|
||||
int ret = 0;
|
||||
int iters = 0;
|
||||
for (;;) {
|
||||
EC_SCALAR k;
|
||||
if (!ec_random_nonzero_scalar(group, &k, additional_data)) {
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -354,8 +298,9 @@ ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
|
||||
CONSTTIME_SECRET(k.words, sizeof(k.words));
|
||||
|
||||
int retry;
|
||||
ret = ecdsa_sign_impl(group, &retry, priv_key, &k, digest, digest_len);
|
||||
if (ret != NULL || !retry) {
|
||||
ret = ecdsa_sign_impl(group, &retry, sig, out_sig_len, max_sig_len,
|
||||
priv_key, &k, digest, digest_len);
|
||||
if (ret || !retry) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,6 +285,14 @@ TEST(ECDSATest, BuiltinCurves) {
|
||||
|
||||
// Verify a tampered signature.
|
||||
TestTamperedSig(kRawAPI, digest, 20, ecdsa_sig.get(), eckey.get(), order);
|
||||
|
||||
// Negative components should not be accepted.
|
||||
BN_set_negative(ecdsa_sig->r, 1);
|
||||
EXPECT_FALSE(ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get()));
|
||||
BN_set_negative(ecdsa_sig->r, 0);
|
||||
BN_set_negative(ecdsa_sig->s, 1);
|
||||
EXPECT_FALSE(ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get()));
|
||||
BN_set_negative(ecdsa_sig->s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,25 +17,42 @@
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#include "../ec/internal.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// ecdsa_sign_with_nonce_for_known_answer_test behaves like |ECDSA_do_sign| but
|
||||
// takes a fixed nonce. This function is used as part of known-answer tests in
|
||||
// the FIPS module.
|
||||
ECDSA_SIG *ecdsa_sign_with_nonce_for_known_answer_test(const uint8_t *digest,
|
||||
size_t digest_len,
|
||||
const EC_KEY *eckey,
|
||||
const uint8_t *nonce,
|
||||
size_t nonce_len);
|
||||
// ECDSA_MAX_FIXED_LEN is the maximum length of an ECDSA signature in the
|
||||
// fixed-width, big-endian format from IEEE P1363.
|
||||
#define ECDSA_MAX_FIXED_LEN (2 * EC_MAX_BYTES)
|
||||
|
||||
// ecdsa_do_verify_no_self_test does the same as |ECDSA_do_verify|, but doesn't
|
||||
// ecdsa_sign_fixed behaves like |ECDSA_sign| but uses the fixed-width,
|
||||
// big-endian format from IEEE P1363.
|
||||
int ecdsa_sign_fixed(const uint8_t *digest, size_t digest_len, uint8_t *sig,
|
||||
size_t *out_sig_len, size_t max_sig_len,
|
||||
const EC_KEY *key);
|
||||
|
||||
// ecdsa_sign_fixed_with_nonce_for_known_answer_test behaves like
|
||||
// |ecdsa_sign_fixed| but takes a caller-supplied nonce. This function is used
|
||||
// as part of known-answer tests in the FIPS module.
|
||||
int ecdsa_sign_fixed_with_nonce_for_known_answer_test(
|
||||
const uint8_t *digest, size_t digest_len, uint8_t *sig, size_t *out_sig_len,
|
||||
size_t max_sig_len, const EC_KEY *key, const uint8_t *nonce,
|
||||
size_t nonce_len);
|
||||
|
||||
// ecdsa_verify_fixed behaves like |ECDSA_verify| but uses the fixed-width,
|
||||
// big-endian format from IEEE P1363.
|
||||
int ecdsa_verify_fixed(const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len, const EC_KEY *key);
|
||||
|
||||
// ecdsa_verify_fixed_no_self_test behaves like ecdsa_verify_fixed, but doesn't
|
||||
// try to run the self-test first. This is for use in the self tests themselves,
|
||||
// to prevent an infinite loop.
|
||||
int ecdsa_do_verify_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
const ECDSA_SIG *sig, const EC_KEY *eckey);
|
||||
int ecdsa_verify_fixed_no_self_test(const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len,
|
||||
const EC_KEY *key);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -77,28 +77,6 @@ static int set_bignum(BIGNUM **out, const uint8_t *in, size_t len) {
|
||||
return *out != NULL;
|
||||
}
|
||||
|
||||
static int serialize_ecdsa_sig(uint8_t *out, size_t out_len,
|
||||
const ECDSA_SIG *sig) {
|
||||
if ((out_len & 1) || //
|
||||
!BN_bn2bin_padded(out, out_len / 2, sig->r) ||
|
||||
!BN_bn2bin_padded(out + out_len / 2, out_len / 2, sig->s)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ECDSA_SIG *parse_ecdsa_sig(const uint8_t *in, size_t in_len) {
|
||||
ECDSA_SIG *ret = ECDSA_SIG_new();
|
||||
if (!ret || //
|
||||
(in_len & 1) ||
|
||||
BN_bin2bn(in, in_len/2, ret->r) == NULL ||
|
||||
BN_bin2bn(in + in_len/2, in_len/2, ret->s) == NULL) {
|
||||
ECDSA_SIG_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RSA *self_test_rsa_key(void) {
|
||||
static const uint8_t kN[] = {
|
||||
0xd3, 0x3a, 0x62, 0x9f, 0x07, 0x77, 0xb0, 0x18, 0xf3, 0xff, 0xfe, 0xcc,
|
||||
@@ -415,7 +393,6 @@ static int boringssl_self_test_ecc(void) {
|
||||
EC_POINT *ec_point_in = NULL;
|
||||
EC_POINT *ec_point_out = NULL;
|
||||
BIGNUM *ec_scalar = NULL;
|
||||
ECDSA_SIG *sig = NULL;
|
||||
|
||||
ec_key = self_test_ecdsa_key();
|
||||
if (ec_key == NULL) {
|
||||
@@ -443,13 +420,12 @@ static int boringssl_self_test_ecc(void) {
|
||||
uint8_t ecdsa_k[32] = {0};
|
||||
ecdsa_k[31] = 42;
|
||||
|
||||
sig = ecdsa_sign_with_nonce_for_known_answer_test(
|
||||
kECDSASignDigest, sizeof(kECDSASignDigest), ec_key, ecdsa_k,
|
||||
sizeof(ecdsa_k));
|
||||
|
||||
uint8_t ecdsa_sign_output[64];
|
||||
if (sig == NULL ||
|
||||
!serialize_ecdsa_sig(ecdsa_sign_output, sizeof(ecdsa_sign_output), sig) ||
|
||||
size_t ecdsa_sign_output_len;
|
||||
if (!ecdsa_sign_fixed_with_nonce_for_known_answer_test(
|
||||
kECDSASignDigest, sizeof(kECDSASignDigest), ecdsa_sign_output,
|
||||
&ecdsa_sign_output_len, sizeof(ecdsa_sign_output), ec_key, ecdsa_k,
|
||||
sizeof(ecdsa_k)) ||
|
||||
!check_test(kECDSASignSig, ecdsa_sign_output, sizeof(ecdsa_sign_output),
|
||||
"ECDSA-sign signature")) {
|
||||
fprintf(stderr, "ECDSA-sign KAT failed.\n");
|
||||
@@ -470,11 +446,9 @@ static int boringssl_self_test_ecc(void) {
|
||||
0x8e, 0x5f, 0x64, 0xc3, 0x7e, 0xa2, 0xcf, 0x05, 0x29,
|
||||
};
|
||||
|
||||
ECDSA_SIG_free(sig);
|
||||
sig = parse_ecdsa_sig(kECDSAVerifySig, sizeof(kECDSAVerifySig));
|
||||
if (!sig ||
|
||||
!ecdsa_do_verify_no_self_test(kECDSAVerifyDigest,
|
||||
sizeof(kECDSAVerifyDigest), sig, ec_key)) {
|
||||
if (!ecdsa_verify_fixed_no_self_test(
|
||||
kECDSAVerifyDigest, sizeof(kECDSAVerifyDigest), kECDSAVerifySig,
|
||||
sizeof(kECDSAVerifySig), ec_key)) {
|
||||
fprintf(stderr, "ECDSA-verify KAT failed.\n");
|
||||
goto err;
|
||||
}
|
||||
@@ -532,7 +506,6 @@ err:
|
||||
EC_POINT_free(ec_point_in);
|
||||
EC_POINT_free(ec_point_out);
|
||||
BN_free(ec_scalar);
|
||||
ECDSA_SIG_free(sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user