diff --git a/configure.ac b/configure.ac index f8b7ae90d..2fb2eb9d8 100644 --- a/configure.ac +++ b/configure.ac @@ -1500,6 +1500,7 @@ fi AM_CONDITIONAL([BUILD_ECC], [test "x$ENABLED_ECC" = "xyes"]) + # ECC Custom Curves AC_ARG_ENABLE([ecccustcurves], [AS_HELP_STRING([--enable-ecccustcurves],[Enable ECC custom curves (default: disabled)])], @@ -1511,7 +1512,7 @@ if test "$ENABLED_ECCCUSTCURVES" != "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" - # For distro or all builds, enable all curve types + # For distro, all or ecccustcurves=all builds, enable all curve types if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" || test "$ENABLED_ECCCUSTCURVES" = "all" then # Enable ECC SECPR2, SECPR3, BRAINPOOL and KOBLITZ curves @@ -1519,6 +1520,12 @@ then # Enable ECC Cofactor support AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_CDH" + + # If fastmath enabled and on x86 use speedups + if test "x$ENABLED_FASTMATH" = "xyes" && test "$host_cpu" = "x86_64" + then + AM_CFLAGS="$AM_CFLAGS -DTFM_ECC192 -DTFM_ECC224 -DTFM_ECC256 -DTFM_ECC384 -DTFM_ECC521" + fi fi fi diff --git a/tests/api.c b/tests/api.c index c29edfda5..39bb6f265 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14821,7 +14821,7 @@ static int test_wc_ecc_sig_size (void) if (ret == 0) { ret = wc_ecc_sig_size(&key); - if (ret == (2 * keySz + SIG_HEADER_SZ + ECC_MAX_PAD_SZ)) { + if (ret <= (2 * keySz + SIG_HEADER_SZ + ECC_MAX_PAD_SZ)) { ret = 0; } } diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index d646e3aea..a1bd06b27 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4295,6 +4295,25 @@ int wc_ecc_set_flags(ecc_key* key, word32 flags) return 0; } + +static int wc_ecc_get_curve_order_bit_count(const ecc_set_type* dp) +{ + int err; + word32 orderBits; + DECLARE_CURVE_SPECS(curve, 1); + + ALLOC_CURVE_SPECS(1); + err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + orderBits = mp_count_bits(curve->order); + + FREE_CURVE_SPECS(); + return (int)orderBits; +} + #ifdef HAVE_ECC_SIGN #ifndef NO_ASN @@ -4317,8 +4336,7 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, #endif { word32 keysize = (word32)key->dp->size; - word32 orderBits; - DECLARE_CURVE_SPECS(curve, 1); + word32 orderBits = wc_ecc_get_curve_order_bit_count(key->dp); /* Check args */ if (keysize > ECC_MAX_CRYPTO_HW_SIZE || *outlen < keysize*2) { @@ -4326,17 +4344,9 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, } /* if the input is larger than curve order, we must truncate */ - ALLOC_CURVE_SPECS(1); - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); - if (err != 0) { - FREE_CURVE_SPECS(); - return err; - } - orderBits = mp_count_bits(curve->order); if ((inlen * WOLFSSL_BIT_SIZE) > orderBits) { inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; } - FREE_CURVE_SPECS(); #if defined(WOLFSSL_ATECC508A) key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); @@ -7299,25 +7309,55 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, /* key size in octets */ int wc_ecc_size(ecc_key* key) { - if (key == NULL) return 0; + if (key == NULL) + return 0; return key->dp->size; } +/* maximum signature size based on key size */ int wc_ecc_sig_size_calc(int sz) { - return (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ; + int maxSigSz = 0; + + /* calculate based on key bits */ + /* maximum possible signature header size is 7 bytes plus 2 bytes padding */ + maxSigSz = (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ; + + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; } -/* worst case estimate, check actual return from wc_ecc_sign_hash for actual - value of signature size in octets */ +/* maximum signature size based on actual key curve */ int wc_ecc_sig_size(ecc_key* key) { - int sz = wc_ecc_size(key); - if (sz <= 0) - return sz; + int maxSigSz; + int orderBits, keySz; - return wc_ecc_sig_size_calc(sz); + if (key == NULL || key->dp == NULL) + return 0; + + /* the signature r and s will always be less than order */ + /* if the order MSB (top bit of byte) is set then ASN encoding needs + extra byte for r and s, so add 2 */ + keySz = key->dp->size; + orderBits = wc_ecc_get_curve_order_bit_count(key->dp); + /* maximum possible signature header size is 7 bytes */ + maxSigSz = (keySz * 2) + SIG_HEADER_SZ; + if ((orderBits % 8) == 0) { + /* MSB can be set, so add 2 */ + maxSigSz += ECC_MAX_PAD_SZ; + } + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; } diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 908ac4961..bedf9a315 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -108,18 +108,21 @@ #define MAX_ECC_BYTES ((MAX_ECC_BITS / 8) + 1) #endif +#ifndef ECC_MAX_PAD_SZ + /* ECC maximum padding size (when MSB is set extra byte required for R and S) */ + #define ECC_MAX_PAD_SZ 2 +#endif enum { ECC_PUBLICKEY = 1, ECC_PRIVATEKEY = 2, ECC_PRIVATEKEY_ONLY = 3, ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ - SIG_HEADER_SZ = 6, /* ECC signature header size */ + SIG_HEADER_SZ = 7, /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */ ECC_BUFSIZE = 256, /* for exported keys temp buffer */ ECC_MINSIZE = 20, /* MIN Private Key size */ ECC_MAXSIZE = 66, /* MAX Private Key size */ ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ - ECC_MAX_PAD_SZ = 4, /* ECC maximum padding size */ ECC_MAX_OID_LEN = 16, ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ),