Move ECDSA_SIG out of BCM This CL adjusts the libcrypto <-> BCM ECDSA interface. Previously, we used ECDSA_do_sign and ECDSA_do_verify. This meant we have an allocated BIGNUM-based type (ECDSA_SIG) at the boundary. Instead use the fixed-width P1363 format at the boundary, which is nice and straightforward. For now, I haven't exported it out of anything, though we do have some things (Channel ID, WebCrypto) which actually want this format, so that may be worth revisiting later. Bug: 42290602 Change-Id: Ifbe0600fd23addc5f05141d18baad21a669ceca8 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66829 Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: Bob Beck <bbe@google.com> Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/ecdsa_extra/ecdsa_asn1.c b/crypto/ecdsa_extra/ecdsa_asn1.c index 8ddfb3b..b2d4fc6 100644 --- a/crypto/ecdsa_extra/ecdsa_asn1.c +++ b/crypto/ecdsa_extra/ecdsa_asn1.c
@@ -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 @@ 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 @@ 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 @@ 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) {
diff --git a/crypto/fipsmodule/bcm.c b/crypto/fipsmodule/bcm.c index c356730..48becb9 100644 --- a/crypto/fipsmodule/bcm.c +++ b/crypto/fipsmodule/bcm.c
@@ -196,7 +196,7 @@ 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)
diff --git a/crypto/fipsmodule/ec/ec_key.c b/crypto/fipsmodule/ec/ec_key.c index 8cdb5c3..1eef021 100644 --- a/crypto/fipsmodule/ec/ec_key.c +++ b/crypto/fipsmodule/ec/ec_key.c
@@ -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 @@ } 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; }
diff --git a/crypto/fipsmodule/ecdsa/ecdsa.c b/crypto/fipsmodule/ecdsa/ecdsa.c index 3bd018d..cba8972 100644 --- a/crypto/fipsmodule/ecdsa/ecdsa.c +++ b/crypto/fipsmodule/ecdsa/ecdsa.c
@@ -95,61 +95,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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; }
diff --git a/crypto/fipsmodule/ecdsa/ecdsa_test.cc b/crypto/fipsmodule/ecdsa/ecdsa_test.cc index 5876935..1856210 100644 --- a/crypto/fipsmodule/ecdsa/ecdsa_test.cc +++ b/crypto/fipsmodule/ecdsa/ecdsa_test.cc
@@ -285,6 +285,14 @@ // 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); } }
diff --git a/crypto/fipsmodule/ecdsa/internal.h b/crypto/fipsmodule/ecdsa/internal.h index 645959f..0ae08ac 100644 --- a/crypto/fipsmodule/ecdsa/internal.h +++ b/crypto/fipsmodule/ecdsa/internal.h
@@ -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)
diff --git a/crypto/fipsmodule/self_check/self_check.c b/crypto/fipsmodule/self_check/self_check.c index 1984630..7afcb75 100644 --- a/crypto/fipsmodule/self_check/self_check.c +++ b/crypto/fipsmodule/self_check/self_check.c
@@ -77,28 +77,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ EC_POINT_free(ec_point_in); EC_POINT_free(ec_point_out); BN_free(ec_scalar); - ECDSA_SIG_free(sig); return ret; }