Expose ECDSA_SIG_max_len to size a DER ECDSA-Sig-Value.
Also implement it without reference to crypto/asn1 or fake ASN1_INTEGERs and
add a test. Some platform crypto APIs only give back the key size, and not the
encoded signature length. No sense in implementing it twice.
BUG=347404,499653
Change-Id: I9aa27d52674375f8b036e57bb5850f091c9b25dd
Reviewed-on: https://boringssl-review.googlesource.com/5080
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ecdsa/ecdsa_test.cc b/crypto/ecdsa/ecdsa_test.cc
index a6bd7a1..615741f 100644
--- a/crypto/ecdsa/ecdsa_test.cc
+++ b/crypto/ecdsa/ecdsa_test.cc
@@ -325,11 +325,50 @@
return true;
}
+static bool TestECDSA_SIG_max_len(size_t order_len) {
+ /* Create the largest possible |ECDSA_SIG| of the given constraints. */
+ ScopedECDSA_SIG sig(ECDSA_SIG_new());
+ if (!sig) {
+ return false;
+ }
+ std::vector<uint8_t> bytes(order_len, 0xff);
+ if (!BN_bin2bn(bssl::vector_data(&bytes), bytes.size(), sig->r) ||
+ !BN_bin2bn(bssl::vector_data(&bytes), bytes.size(), sig->s)) {
+ return false;
+ }
+ /* Serialize it. */
+ int len = i2d_ECDSA_SIG(sig.get(), nullptr);
+ if (len < 0) {
+ return false;
+ }
+ std::vector<uint8_t> der(len);
+ uint8_t *ptr = bssl::vector_data(&der);
+ len = i2d_ECDSA_SIG(sig.get(), &ptr);
+ if (len < 0) {
+ return false;
+ }
+ der.resize(len);
+
+ size_t max_len = ECDSA_SIG_max_len(order_len);
+ if (max_len != static_cast<size_t>(len)) {
+ fprintf(stderr, "ECDSA_SIG_max_len(%u) returned %u, wanted %d\n",
+ static_cast<unsigned>(order_len), static_cast<unsigned>(max_len),
+ len);
+ return false;
+ }
+ return true;
+}
+
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
- if (!TestBuiltin(stdout)) {
+ if (!TestBuiltin(stdout) ||
+ !TestECDSA_SIG_max_len(224/8) ||
+ !TestECDSA_SIG_max_len(256/8) ||
+ !TestECDSA_SIG_max_len(384/8) ||
+ !TestECDSA_SIG_max_len(512/8) ||
+ !TestECDSA_SIG_max_len(10000)) {
printf("\nECDSA test failed\n");
ERR_print_errors_fp(stdout);
return 1;