diff --git a/configure.ac b/configure.ac index ea87c63b9..1598e5a93 100644 --- a/configure.ac +++ b/configure.ac @@ -425,6 +425,39 @@ AC_ARG_ENABLE([haproxy], [ ENABLED_HAPROXY=no ] ) +# wpa_supplicant support +AC_ARG_ENABLE([wpas], + [AS_HELP_STRING([--enable-wpas],[Enable wpa_supplicant support (default: disabled)])], + [ ENABLED_WPAS=$enableval ], + [ ENABLED_WPAS=no ] + ) + +# Fortress build +AC_ARG_ENABLE([fortress], + [AS_HELP_STRING([--enable-fortress],[Enable SSL fortress build (default: disabled)])], + [ ENABLED_FORTRESS=$enableval ], + [ ENABLED_FORTRESS=no ] + ) + +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_FORTRESS="yes" +fi + +# ssl bump build +AC_ARG_ENABLE([bump], + [AS_HELP_STRING([--enable-bump],[Enable SSL Bump build (default: disabled)])], + [ ENABLED_BUMP=$enableval ], + [ ENABLED_BUMP=no ] + ) + +# SNIFFER +AC_ARG_ENABLE([sniffer], + [AS_HELP_STRING([--enable-sniffer],[Enable wolfSSL sniffer support (default: disabled)])], + [ ENABLED_SNIFFER=$enableval ], + [ ENABLED_SNIFFER=no ] + ) + # signal compatibility build AC_ARG_ENABLE([signal], [AS_HELP_STRING([--enable-signal],[Enable signal (default: disabled)])], @@ -453,7 +486,7 @@ AC_ARG_ENABLE([opensslextra], [ ENABLED_OPENSSLEXTRA=$enableval ], [ ENABLED_OPENSSLEXTRA=no ] ) -if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" || test "$ENABLED_BUMP" = "yes" || test "$ENABLED_SNIFFER" = "yes" then ENABLED_OPENSSLEXTRA="yes" fi @@ -506,53 +539,28 @@ fi AM_CONDITIONAL([BUILD_IPV6], [test "x$ENABLED_IPV6" = "xyes"]) -# wpa_supplicant support -AC_ARG_ENABLE([wpas], - [AS_HELP_STRING([--enable-wpas],[Enable wpa_supplicant support (default: disabled)])], - [ ENABLED_WPAS=$enableval ], - [ ENABLED_WPAS=no ] - ) if test "$ENABLED_WPAS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_SECRET_CALLBACK -DWOLFSSL_STATIC_RSA" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PUBLIC_MP -DWOLFSSL_PUBLIC_ECC_ADD_DBL" AM_CFLAGS="$AM_CFLAGS -DATOMIC_USER -DHAVE_EX_DATA -DWOLFSSL_KEEP_PEER_CERT" AM_CFLAGS="$AM_CFLAGS -DHAVE_EXT_CACHE" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_VERIFY_CB -DOPENSSL_EXTRA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_VERIFY_CB" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WPAS" fi -# Fortress build -AC_ARG_ENABLE([fortress], - [AS_HELP_STRING([--enable-fortress],[Enable SSL fortress build (default: disabled)])], - [ ENABLED_FORTRESS=$enableval ], - [ ENABLED_FORTRESS=no ] - ) - -if test "$ENABLED_OPENSSH" = "yes" -then - ENABLED_FORTRESS="yes" -fi - if test "$ENABLED_FORTRESS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DFORTRESS -DWOLFSSL_ALWAYS_VERIFY_CB -DOPENSSL_EXTRA -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD -DWOLFSSL_KEY_GEN" + AM_CFLAGS="$AM_CFLAGS -DFORTRESS -DWOLFSSL_ALWAYS_VERIFY_CB -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD -DWOLFSSL_KEY_GEN" fi -# ssl bump build -AC_ARG_ENABLE([bump], - [AS_HELP_STRING([--enable-bump],[Enable SSL Bump build (default: disabled)])], - [ ENABLED_BUMP=$enableval ], - [ ENABLED_BUMP=no ] - ) - if test "$ENABLED_BUMP" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" + AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" fi ENABLED_SLOWMATH="yes" @@ -716,13 +724,6 @@ fi AM_CONDITIONAL([BUILD_PKCALLBACKS], [ test "x$ENABLED_PKCALLBACKS" = "xyes" ]) -# SNIFFER -AC_ARG_ENABLE([sniffer], - [AS_HELP_STRING([--enable-sniffer],[Enable wolfSSL sniffer support (default: disabled)])], - [ ENABLED_SNIFFER=$enableval ], - [ ENABLED_SNIFFER=no ] - ) - # sniffer doesn't work in maxstrength mode if test "$ENABLED_SNIFFER" = "yes" && test "$ENABLED_MAXSTRENGTH" = "yes" then @@ -732,7 +733,7 @@ fi ENABLED_SNIFFTEST=no AS_IF([ test "x$ENABLED_SNIFFER" = "xyes" ], [ - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER -DOPENSSL_EXTRA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER" AC_CHECK_HEADERS([pcap/pcap.h], [ ENABLED_SNIFFTEST=yes ], [ AC_MSG_WARN([cannot enable sniffer test without having libpcap available.]) ] @@ -2191,7 +2192,6 @@ AC_ARG_ENABLE([ocspstapling], if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" then - echo "ELLO" ENABLED_CERTIFICATE_STATUS_REQUEST="yes" fi @@ -3313,6 +3313,9 @@ AC_ARG_ENABLE([sp], [ ENABLED_SP=no ], ) +ENABLED_SP_RSA=no +ENABLED_SP_DH=no +ENABLED_SP_ECC=no for v in `echo $ENABLED_SP | tr "," " "` do case $v in @@ -3403,6 +3406,38 @@ if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then fi AM_CONDITIONAL([BUILD_SP], [test "x$ENABLED_SP" = "xyes"]) +AC_ARG_ENABLE([sp-math], + [AS_HELP_STRING([--enable-sp-math],[Enable Single Precision math implementation only (default: disabled)])], + [ ENABLED_SP_MATH=$enableval ], + [ ENABLED_SP_MATH=no ], + ) +if test "$ENABLED_SP_MATH" = "yes"; then + if test "$ENABLED_SP" = "no"; then + AC_MSG_ERROR([Must have SP enabled: --enable-sp]) + fi + if test "$ENABLED_ECCCUSTCURVES" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and custom curves]) + fi + if test "$ENABLED_OPENSSLEXTRA" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and OpenSSL extra]) + fi + if test "$ENABLED_DSA" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and DSA]) + fi + if test "$ENABLED_SRP" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and SRP]) + fi + if test "$ENABLED_SP_RSA" = "no" && test "$ENABLED_RSA" = "yes"; then + AC_MSG_ERROR([Cannot use P256 single precision only math and RSA]) + fi + if test "$ENABLED_SP_DH" = "no" && test "$ENABLED_DH" = "yes"; then + AC_MSG_ERROR([Cannot use P256 single precision only math and DH]) + fi +fi +if test "$ENABLED_SP_MATH" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_MATH" +fi + # Fast RSA using Intel IPP ippdir="${srcdir}/IPP" ipplib="lib" # if autoconf guesses 32bit system changes lib directory @@ -3834,6 +3869,9 @@ then fi AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_WOLFSCEP" fi +if test "$ENABLED_SP_MATH" = "yes" && test "$ENABLED_KEYGEN" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and key generation]) +fi if test "x$ENABLED_PKCS7" = "xyes" then diff --git a/examples/client/client.c b/examples/client/client.c index 1a2881727..51298e37e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -2228,10 +2228,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) WOLFSSL_ECC_SECP256R1) != WOLFSSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_ECC_SECP384R1) != WOLFSSL_SUCCESS) { err_sys("unable to use curve secp384r1"); } + #endif #endif #ifdef HAVE_FFDHE_2048 if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) { diff --git a/src/include.am b/src/include.am index fca5e3e88..70ea200b7 100644 --- a/src/include.am +++ b/src/include.am @@ -104,6 +104,7 @@ endif endif if BUILD_SP src_libwolfssl_la_SOURCES += wolfcrypt/src/sp.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_int.c endif if BUILD_AES diff --git a/src/ssl.c b/src/ssl.c index 2c59d8820..a76171ef2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -21495,7 +21495,8 @@ int wolfSSL_RAND_write_file(const char* fname) #ifndef WOLFSSL_SMALL_STACK unsigned char buf[1024]; #else - unsigned char* buf = XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL, + DYNAMIC_TYPE_TMP_BUFFER); if (buf == NULL) { WOLFSSL_MSG("malloc failed"); return SSL_FAILURE; diff --git a/tests/api.c b/tests/api.c index c4f12b7bc..d8ace1f79 100644 --- a/tests/api.c +++ b/tests/api.c @@ -44,36 +44,70 @@ #ifndef ECC_PRIV_KEY_BUF #define ECC_PRIV_KEY_BUF 66 /* For non user defined curves. */ #endif - /* ecc key sizes: 14, 16, 20, 24, 28, 30, 32, 40, 48, 64*/ - #ifndef KEY14 - #define KEY14 14 - #endif - #if !defined(KEY16) - #define KEY16 16 - #endif - #if !defined(KEY20) - #define KEY20 20 - #endif - #if !defined(KEY24) - #define KEY24 24 - #endif - #if !defined(KEY28) - #define KEY28 28 - #endif - #if !defined(KEY30) - #define KEY30 30 - #endif - #if !defined(KEY32) - #define KEY32 32 - #endif - #if !defined(KEY40) - #define KEY40 40 - #endif - #if !defined(KEY48) - #define KEY48 48 - #endif - #if !defined(KEY64) - #define KEY64 64 + #ifdef HAVE_ALL_CURVES + /* ecc key sizes: 14, 16, 20, 24, 28, 30, 32, 40, 48, 64*/ + #ifndef KEY14 + #define KEY14 14 + #endif + #if !defined(KEY16) + #define KEY16 16 + #endif + #if !defined(KEY20) + #define KEY20 20 + #endif + #if !defined(KEY24) + #define KEY24 24 + #endif + #if !defined(KEY28) + #define KEY28 28 + #endif + #if !defined(KEY30) + #define KEY30 30 + #endif + #if !defined(KEY32) + #define KEY32 32 + #endif + #if !defined(KEY40) + #define KEY40 40 + #endif + #if !defined(KEY48) + #define KEY48 48 + #endif + #if !defined(KEY64) + #define KEY64 64 + #endif + #else + /* ecc key sizes: 14, 16, 20, 24, 28, 30, 32, 40, 48, 64*/ + #ifndef KEY14 + #define KEY14 32 + #endif + #if !defined(KEY16) + #define KEY16 32 + #endif + #if !defined(KEY20) + #define KEY20 32 + #endif + #if !defined(KEY24) + #define KEY24 32 + #endif + #if !defined(KEY28) + #define KEY28 32 + #endif + #if !defined(KEY30) + #define KEY30 32 + #endif + #if !defined(KEY32) + #define KEY32 32 + #endif + #if !defined(KEY40) + #define KEY40 32 + #endif + #if !defined(KEY48) + #define KEY48 32 + #endif + #if !defined(KEY64) + #define KEY64 32 + #endif #endif #if !defined(HAVE_COMP_KEY) #if !defined(NOCOMP) @@ -11681,7 +11715,6 @@ static int test_wc_ed25519_exportKey (void) } /* END test_wc_ed25519_exportKey */ - /* * Testing wc_ecc_make_key. */ @@ -12472,10 +12505,20 @@ static int test_wc_ecc_import_raw (void) #ifdef HAVE_ECC ecc_key key; +#ifdef HAVE_ALL_CURVES const char* qx = "07008ea40b08dbe76432096e80a2494c94982d2d5bcf98e6"; const char* qy = "76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477"; const char* d = "e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3"; const char* curveName = "SECP192R1"; +#else + const char* qx = + "6c450448386596485678dcf46ccf75e80ff292443cddab1ff216d0c72cd9341"; + const char* qy = + "9cac72ff8a90e4939e37714bfa07ae4612588535c3fdeab63ceb29b1d80f0d1"; + const char* d = + "1e1dd938e15bdd036b0b0e2a6dc62fe7b46dbe042ac42310c6d5db0cda63e807"; + const char* curveName = "SECP256R1"; +#endif ret = wc_ecc_init(&key); @@ -13108,8 +13151,8 @@ static int test_wc_ecc_shared_secret_ssh (void) #if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) ecc_key key, key2; WC_RNG rng; - int keySz = 32; - int key2Sz = 24; + int keySz = KEY32; + int key2Sz = KEY24; byte secret[keySz]; word32 secretLen = keySz; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 744fb4cc8..81d396a00 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -612,8 +612,10 @@ static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, byte* pub, word32* pubSz) { int ret = 0; +#ifndef WOLFSSL_SP_MATH mp_int x; mp_int y; +#endif #ifdef WOLFSSL_HAVE_SP_DH #ifndef WOLFSSL_SP_NO_2048 @@ -626,6 +628,7 @@ static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, #endif #endif +#ifndef WOLFSSL_SP_MATH if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -643,6 +646,9 @@ static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, mp_clear(&y); mp_clear(&x); +#else + ret = WC_KEY_SIZE_E; +#endif return ret; } @@ -734,6 +740,7 @@ int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) { int ret = 0; +#ifndef WOLFSSL_SP_MATH mp_int x; mp_int y; @@ -767,6 +774,11 @@ int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) mp_clear(&y); mp_clear(&x); +#else + (void)key; + (void)pub; + (void)pubSz; +#endif return ret; } @@ -800,9 +812,11 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) { int ret = 0; - mp_int x; mp_int y; +#ifndef WOLFSSL_SP_MATH + mp_int x; mp_int z; +#endif if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); @@ -842,6 +856,7 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, #endif #endif +#ifndef WOLFSSL_SP_MATH if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -863,6 +878,7 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, mp_clear(&z); mp_clear(&y); mp_forcezero(&x); +#endif return ret; } diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 1daa330bc..3f81ecf8a 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -133,7 +133,9 @@ ECC Curve Sizes: #include #endif -#ifdef USE_FAST_MATH +#ifdef WOLFSSL_SP_MATH + #define GEN_MEM_ERR MP_MEM +#elif defined(USE_FAST_MATH) #define GEN_MEM_ERR FP_MEM #else #define GEN_MEM_ERR MP_MEM @@ -979,12 +981,14 @@ static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); typedef void* ecc_curve_spec; #else +#ifndef WOLFSSL_SP_MATH static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, mp_int* prime, mp_int* order); #ifdef ECC_SHAMIR static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, ecc_point* C, mp_int* a, mp_int* modulus, void* heap); #endif +#endif int mp_jacobi(mp_int* a, mp_int* n, int* c); int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); @@ -1314,6 +1318,8 @@ static void alt_fp_init(fp_int* a) #ifndef WOLFSSL_ATECC508A +#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) + /** Add two ECC points P The point to add @@ -1327,6 +1333,7 @@ static void alt_fp_init(fp_int* a) int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp) { +#ifndef WOLFSSL_SP_MATH mp_int t1, t2; #ifdef ALT_ECC_SIZE mp_int rx, ry, rz; @@ -1589,6 +1596,17 @@ done: mp_clear(&t2); return err; +#else + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + (void)mp; + + return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z, + R->x, R->y, R->z); +#endif } /* ### Point doubling in Jacobian coordinate system ### @@ -1621,6 +1639,7 @@ done: int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, mp_int* modulus, mp_digit mp) { +#ifndef WOLFSSL_SP_MATH mp_int t1, t2; #ifdef ALT_ECC_SIZE mp_int rx, ry, rz; @@ -1857,6 +1876,15 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, mp_clear(&t2); return err; +#else + if (P == NULL || R == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)a; + (void)mp; + + return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z); +#endif } @@ -1869,6 +1897,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, */ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) { +#ifndef WOLFSSL_SP_MATH mp_int t1, t2; #ifdef ALT_ECC_SIZE mp_int rx, ry, rz; @@ -1967,10 +1996,21 @@ done: mp_clear(&t2); return err; +#else + if (P == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)mp; + + return sp_ecc_map_256(P->x, P->y, P->z); +#endif } +#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */ + #if !defined(FREESCALE_LTC_ECC) +#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH) /** Perform a point multiplication k The scalar to multiply by @@ -1992,6 +2032,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, void* heap) #endif { +#ifndef WOLFSSL_SP_MATH #ifndef ECC_TIMING_RESISTANT /* size of sliding window, don't change this! */ #define WINSIZE 4 @@ -2326,8 +2367,19 @@ exit: } return err; +#else + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + + return sp_ecc_mulmod_256(k, G, R, map, heap); +#endif } +#endif /* !FP_ECC || !WOLFSSL_SP_MATH */ + #endif /* !FREESCALE_LTC_ECC */ /** ECC Fixed Point mulmod global @@ -2737,8 +2789,10 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, byte* out, word32* outlen, ecc_curve_spec* curve) { int err; +#ifndef WOLFSSL_SP_MATH ecc_point* result = NULL; word32 x = 0; +#endif mp_int* k = &private_key->k; #ifdef HAVE_ECC_CDH mp_int k_lcl; @@ -2770,6 +2824,11 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, else #endif #endif +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; + + (void)curve; +#else { /* make new point */ result = wc_ecc_new_point_h(private_key->heap); @@ -2799,6 +2858,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, wc_ecc_del_point_h(result, private_key->heap); } +#endif #ifdef HAVE_ECC_CDH if (k == &k_lcl) mp_clear(k); @@ -2959,6 +3019,7 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) return 0; } +#ifndef WOLFSSL_SP_MATH /* generate random and ensure its greater than 0 and less than order */ static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) { @@ -3006,6 +3067,7 @@ static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) return err; } +#endif #endif /* !WOLFSSL_ATECC508A */ static INLINE void wc_ecc_reset(ecc_key* key) @@ -3033,7 +3095,9 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, { int err = MP_OKAY; #ifndef WOLFSSL_ATECC508A +#ifndef WOLFSSL_SP_MATH ecc_point* base = NULL; +#endif ecc_point* pub; DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) #endif @@ -3087,6 +3151,9 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, else #endif #endif +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; +#else { if (err == MP_OKAY) { base = wc_ecc_new_point_h(key->heap); @@ -3109,6 +3176,7 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, wc_ecc_del_point_h(base, key->heap); } +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN /* validate the public key, order * pubkey = point at infinity */ @@ -3220,6 +3288,9 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) else #endif #endif +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; +#else { /* setup the key variables */ err = mp_init(&key->k); @@ -3248,6 +3319,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) /* cleanup allocations */ wc_ecc_curve_free(curve); } +#endif #endif /* WOLFSSL_ATECC508A */ @@ -3613,7 +3685,9 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key* key, mp_int *r, mp_int *s) { int err; +#ifndef WOLFSSL_SP_MATH mp_int e; +#endif DECLARE_CURVE_SPECS(1) if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) @@ -3629,6 +3703,12 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_SP_MATH + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap); + else + return WC_KEY_SIZE_E; +#else #ifdef WOLFSSL_HAVE_SP_ECC #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ defined(WOLFSSL_ASYNC_CRYPT_TEST) @@ -3786,6 +3866,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, mp_clear(&e); wc_ecc_curve_free(curve); +#endif return err; } @@ -3821,6 +3902,7 @@ int wc_ecc_free(ecc_key* key) return 0; } +#ifndef WOLFSSL_SP_MATH #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -4045,6 +4127,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } #endif /* ECC_SHAMIR */ +#endif #ifdef HAVE_ECC_VERIFY @@ -4165,6 +4248,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, { int err; #ifndef WOLFSSL_ATECC508A +#ifndef WOLFSSL_SP_MATH int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; mp_int v; @@ -4173,6 +4257,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_int u2; mp_int e; DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#endif #else byte sigRS[ATECC_KEY_SIZE*2]; #endif @@ -4232,6 +4317,14 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } } +#ifdef WOLFSSL_SP_MATH + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z, r, s, res, key->heap); + } + else + return WC_KEY_SIZE_E; +#else #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ @@ -4414,6 +4507,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, wc_ecc_curve_free(curve); +#endif #endif /* WOLFSSL_ATECC508A */ return err; @@ -4476,6 +4570,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH int did_init = 0; mp_int t1, t2; DECLARE_CURVE_SPECS(3) @@ -4528,6 +4623,9 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, } wc_ecc_curve_free(curve); +#else + sp_ecc_uncompress_256(point->x, in[0], point->y); +#endif } #endif @@ -4726,6 +4824,7 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, /* is ecc point on curve described by dp ? */ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) { +#ifndef WOLFSSL_SP_MATH int err; mp_int t1, t2; @@ -4802,9 +4901,16 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) mp_clear(&t2); return err; +#else + (void)a; + (void)b; + (void)prime; + + return sp_ecc_is_point_256(ecp->x, ecp->y); +#endif } - +#ifndef WOLFSSL_SP_MATH /* validate privkey * generator == pubkey, 0 on success */ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { @@ -4868,6 +4974,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) return err; } +#endif #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -4905,6 +5012,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */ +#ifndef WOLFSSL_SP_MATH /* validate order * pubkey = point at infinity, 0 on success */ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, mp_int* prime, mp_int* order) @@ -4928,15 +5036,23 @@ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, else #endif #endif +#ifndef WOLFSSL_SP_MATH err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap); if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) err = ECC_INF_E; +#else + (void)a; + (void)prime; + + err = WC_KEY_SIZE_E; +#endif } wc_ecc_del_point_h(inf, key->heap); return err; } +#endif #endif /* !WOLFSSL_ATECC508A */ @@ -4945,6 +5061,7 @@ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, int wc_ecc_check_key(ecc_key* key) { int err; +#ifndef WOLFSSL_SP_MATH #ifndef WOLFSSL_ATECC508A mp_int* b; #ifdef USE_ECC_B_PARAM @@ -5019,6 +5136,18 @@ int wc_ecc_check_key(ecc_key* key) #endif #endif /* WOLFSSL_ATECC508A */ +#else + if (key == NULL) + return BAD_FUNC_ARG; + + /* pubkey point cannot be at infinity */ + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k, + key->heap); + } + else + err = WC_KEY_SIZE_E; +#endif return err; } @@ -5091,6 +5220,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH mp_int t1, t2; int did_init = 0; @@ -5146,6 +5276,9 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, } wc_ecc_curve_free(curve); +#else + sp_ecc_uncompress_256(key->pubkey.x, in[0], key->pubkey.y); +#endif } #endif /* HAVE_COMP_KEY */ @@ -5651,6 +5784,7 @@ int wc_ecc_sig_size(ecc_key* key) #endif +#ifndef WOLFSSL_SP_MATH /** Our FP cache */ typedef struct { ecc_point* g; /* cached COPY of base point */ @@ -5668,6 +5802,7 @@ static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES]; static volatile int initMutex = 0; /* prevent multiple mutex inits */ static wolfSSL_Mutex ecc_fp_lock; #endif /* HAVE_THREAD_LS */ +#endif /* WOLFSSL_SP_MATH */ /* simple table to help direct the generation of the LUT */ static const struct { @@ -6199,6 +6334,7 @@ static const struct { #endif }; +#ifndef WOLFSSL_SP_MATH /* find a hole and free as required, return -1 if no hole found */ static int find_hole(void) { @@ -6288,7 +6424,9 @@ static int add_entry(int idx, ecc_point *g) return MP_OKAY; } +#endif +#ifndef WOLFSSL_SP_MATH /* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart * * The algorithm builds patterns in increasing bit order by first making all @@ -6577,8 +6715,10 @@ done: return err; } +#endif #ifdef ECC_SHAMIR +#ifndef WOLFSSL_SP_MATH /* perform a fixed point ECC mulmod */ static int accel_fp_mul2add(int idx1, int idx2, mp_int* kA, mp_int* kB, @@ -6939,6 +7079,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, return err; } +#endif #endif /* ECC_SHAMIR */ /** ECC Fixed Point mulmod global @@ -6954,6 +7095,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap) { +#ifndef WOLFSSL_SP_MATH int idx, err = MP_OKAY; mp_digit mp; mp_int mu; @@ -7030,8 +7172,16 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_clear(&mu); return err; +#else + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + return sp_ecc_mulmod_256(k, G, R, map, heap); +#endif } +#ifndef WOLFSSL_SP_MATH /* helper function for freeing the cache ... must be called with the cache mutex locked */ static void wc_ecc_fp_free_cache(void) @@ -7051,10 +7201,12 @@ static void wc_ecc_fp_free_cache(void) } } } +#endif /** Free the Fixed Point cache */ void wc_ecc_fp_free(void) { +#ifndef WOLFSSL_SP_MATH #ifndef HAVE_THREAD_LS if (initMutex == 0) { wc_InitMutex(&ecc_fp_lock); @@ -7072,6 +7224,7 @@ void wc_ecc_fp_free(void) initMutex = 0; } #endif /* HAVE_THREAD_LS */ +#endif } @@ -7661,6 +7814,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef HAVE_COMP_KEY #ifndef WOLFSSL_ATECC508A +#ifndef WOLFSSL_SP_MATH int do_mp_jacobi(mp_int* a, mp_int* n, int* c); int do_mp_jacobi(mp_int* a, mp_int* n, int* c) @@ -7963,6 +8117,7 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) return res; } +#endif #endif /* !WOLFSSL_ATECC508A */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index a42faaecb..62d756826 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -45,6 +45,8 @@ #ifndef USE_FAST_MATH +#ifndef WOLFSSL_SP_MATH + #include #if defined(FREESCALE_LTC_TFM) @@ -4953,6 +4955,8 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */ +#endif /* WOLFSSL_SP_MATH */ + #endif /* USE_FAST_MATH */ #endif /* NO_BIG_INT */ diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 5df26dc89..df9681866 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -1198,12 +1198,14 @@ static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out, static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { +#ifndef WOLFSSL_SP_MATH mp_int tmp; #ifdef WC_RSA_BLINDING mp_int rnd, rndi; #endif int ret = 0; word32 keyLen, len; +#endif #ifdef WOLFSSL_HAVE_SP_RSA #ifndef WOLFSSL_SP_NO_2048 @@ -1244,6 +1246,9 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #endif #endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_SP_MATH + return WC_KEY_SIZE_E; +#else (void)rng; if (mp_init(&tmp) != MP_OKAY) @@ -1391,6 +1396,7 @@ done: } #endif return ret; +#endif } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) diff --git a/wolfcrypt/src/sp.c b/wolfcrypt/src/sp.c index 5c9031148..95691e208 100644 --- a/wolfcrypt/src/sp.c +++ b/wolfcrypt/src/sp.c @@ -38822,6 +38822,12 @@ static sp_point p256_base = { /* infinity */ 0 }; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[10] = { + 0x3d2604b,0x38f0f89,0x30f63bc,0x2c3314e,0x0651d06,0x1a621af,0x2bbd557, + 0x24f9ecf,0x1d8aa3a,0x016b18d +}; +#endif #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) /* Allocate memory for point and return error. */ @@ -39075,7 +39081,7 @@ static int sp_256_to_mp(sp_digit* a, mp_int* r) { int err; - err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); if (err == MP_OKAY) { #if DIGIT_BIT == 26 XMEMCPY(r->dp, a, sizeof(sp_digit) * 10); @@ -43764,6 +43770,593 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, } #endif /* HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_10(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*10]; + sp_digit t2d[2*10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 10 * 4, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 10; + t2 = d + 2 * 10; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_10(t1, point->y); + sp_256_mod_10(t1, t1, p256_mod); + sp_256_sqr_10(t2, point->x); + sp_256_mod_10(t2, t2, p256_mod); + sp_256_mul_10(t2, t2, point->x); + sp_256_mod_10(t2, t2, p256_mod); + sp_256_sub_10(t2, p256_mod, t2); + sp_256_mont_add_10(t1, t1, t2, p256_mod); + + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_10(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, sizeof(one)); + + err = sp_256_ecc_is_point_10(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[10]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, sizeof(one)); + sp_256_from_mp(priv, 10, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_10(pub->x) && + sp_256_iszero_10(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_10(pub->x, p256_mod) >= 0 || + sp_256_cmp_10(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_10(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_10(p, pub, p256_order, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_10(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_10(p->x) || + !sp_256_iszero_10(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_10(p, priv, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_10(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_10(p->x, pub->x) != 0 || + sp_256_cmp_10(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + sp_256_from_mp(q->x, 10, qX); + sp_256_from_mp(q->y, 10, qY); + sp_256_from_mp(q->z, 10, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_10(p, p, q, tmp); + else +#endif + sp_256_proj_point_add_10(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_dbl_avx2_10(p, p, tmp); + else +#endif + sp_256_proj_point_dbl_10(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_map_10(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_10(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 10]; + sp_digit t2d[2 * 10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 10; + t2 = d + 2 * 10; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_avx2_10(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_avx2_10(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_avx2_10(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_avx2_10(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_avx2_10(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_avx2_10(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_10(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_avx2_10(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_10(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_avx2_10(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_avx2_10(y, t1, 94, p256_mod, p256_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_10(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_10(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_10(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_10(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_10(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_10(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_10(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_10(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 10]; + sp_digit yd[2 * 10]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 10; + y = d + 2 * 10; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 10, xm); + + err = sp_256_mod_mul_norm_10(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_sqr_avx2_10(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_10(y, y, x, p256_mod, p256_mp_mod); + } + else +#endif + { + sp_256_mont_sqr_10(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_10(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_10(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_10(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 10, 0, 10 * sizeof(sp_digit)); + sp_256_mont_reduce_10(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_10(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif #endif /* WOLFSSL_SP_NO_256 */ #endif /* SP_WORD_SIZE == 32 */ #endif @@ -43837,6 +44430,12 @@ static sp_point p256_base = { /* infinity */ 0 }; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[5] = { + 0xe3c3e27d2604bl,0xb0cc53b0f63bcl,0x69886bc651d06l,0x93e7b3ebbd557l, + 0x05ac635d8aa3al +}; +#endif #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) /* Allocate memory for point and return error. */ @@ -44073,7 +44672,7 @@ static int sp_256_to_mp(sp_digit* a, mp_int* r) { int err; - err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); if (err == MP_OKAY) { #if DIGIT_BIT == 52 XMEMCPY(r->dp, a, sizeof(sp_digit) * 5); @@ -48554,6 +49153,593 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, } #endif /* HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_5(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*5]; + sp_digit t2d[2*5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 5 * 4, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 5; + t2 = d + 2 * 5; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_5(t1, point->y); + sp_256_mod_5(t1, t1, p256_mod); + sp_256_sqr_5(t2, point->x); + sp_256_mod_5(t2, t2, p256_mod); + sp_256_mul_5(t2, t2, point->x); + sp_256_mod_5(t2, t2, p256_mod); + sp_256_sub_5(t2, p256_mod, t2); + sp_256_mont_add_5(t1, t1, t2, p256_mod); + + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_5(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, sizeof(one)); + + err = sp_256_ecc_is_point_5(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[5]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, sizeof(one)); + sp_256_from_mp(priv, 5, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_5(pub->x) && + sp_256_iszero_5(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_5(pub->x, p256_mod) >= 0 || + sp_256_cmp_5(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_5(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_5(p, pub, p256_order, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_5(p->x) || + !sp_256_iszero_5(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_5(p, priv, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_5(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_5(p->x, pub->x) != 0 || + sp_256_cmp_5(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + sp_256_from_mp(q->x, 5, qX); + sp_256_from_mp(q->y, 5, qY); + sp_256_from_mp(q->z, 5, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_5(p, p, q, tmp); + else +#endif + sp_256_proj_point_add_5(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 2, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_dbl_avx2_5(p, p, tmp); + else +#endif + sp_256_proj_point_dbl_5(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 4, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + + sp_256_map_5(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_5(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 5]; + sp_digit t2d[2 * 5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 5; + t2 = d + 2 * 5; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_avx2_5(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_avx2_5(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_avx2_5(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_avx2_5(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_avx2_5(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_avx2_5(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_5(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_avx2_5(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_5(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_avx2_5(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_avx2_5(y, t1, 94, p256_mod, p256_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_5(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_5(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_5(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_5(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_5(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_5(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_5(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_5(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 5]; + sp_digit yd[2 * 5]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 5; + y = d + 2 * 5; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 5, xm); + + err = sp_256_mod_mul_norm_5(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_sqr_avx2_5(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_5(y, y, x, p256_mod, p256_mp_mod); + } + else +#endif + { + sp_256_mont_sqr_5(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_5(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_5(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_5(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 5, 0, 5 * sizeof(sp_digit)); + sp_256_mont_reduce_5(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_5(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif #endif /* WOLFSSL_SP_NO_256 */ #endif /* SP_WORD_SIZE == 64 */ #endif @@ -48605,6 +49791,12 @@ static sp_digit p256_norm_order[4] = { /* The Montogmery multiplier for order of the curve P256. */ static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl; #endif +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[4] = { + 0x3bce3c3e27d2604bl,0x651d06b0cc53b0f6l,0xb3ebbd55769886bcl, + 0x5ac635d8aa3a93e7l +}; +#endif #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) /* Allocate memory for point and return error. */ @@ -48792,7 +49984,7 @@ static int sp_256_to_mp(sp_digit* a, mp_int* r) { int err; - err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); if (err == MP_OKAY) { #if DIGIT_BIT == 64 XMEMCPY(r->dp, a, sizeof(sp_digit) * 4); @@ -65720,6 +66912,593 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, } #endif /* HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_4(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*4]; + sp_digit t2d[2*4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_4(t1, point->y); + sp_256_mod_4(t1, t1, p256_mod); + sp_256_sqr_4(t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_mul_4(t2, t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_sub_4(t2, p256_mod, t2); + sp_256_mont_add_4(t1, t1, t2, p256_mod); + + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_4(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + + err = sp_256_ecc_is_point_4(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[4]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + sp_256_from_mp(priv, 4, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_4(pub->x) && + sp_256_iszero_4(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || + sp_256_cmp_4(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_4(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p, pub, p256_order, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_4(p->x) || + !sp_256_iszero_4(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p, priv, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_4(p->x, pub->x) != 0 || + sp_256_cmp_4(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + sp_256_from_mp(q->x, 4, qX); + sp_256_from_mp(q->y, 4, qY); + sp_256_from_mp(q->z, 4, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(p, p, q, tmp); + else +#endif + sp_256_proj_point_add_4(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_dbl_avx2_4(p, p, tmp); + else +#endif + sp_256_proj_point_dbl_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_map_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_4(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 4]; + sp_digit t2d[2 * 4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_avx2_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_avx2_4(y, t1, 94, p256_mod, p256_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 4]; + sp_digit yd[2 * 4]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 4; + y = d + 2 * 4; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 4, xm); + + err = sp_256_mod_mul_norm_4(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_sqr_avx2_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod); + } + else +#endif + { + sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_4(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_4(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 4, 0, 4 * sizeof(sp_digit)); + sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_4(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif #endif /* WOLFSSL_SP_NO_256 */ #endif /* SP_WORD_SIZE == 64 */ #endif diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c new file mode 100644 index 000000000..3b5b3b236 --- /dev/null +++ b/wolfcrypt/src/sp_int.c @@ -0,0 +1,486 @@ +/* sp_int.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SP_MATH + +#include + +/* Initialize the big number to be zero. + * + * a SP integer. + * returns MP_OKAY always. + */ +int sp_init(sp_int* a) +{ + a->used = 0; + a->size = SP_INT_DIGITS; + + return MP_OKAY; +} + +/* Initialize up to six big numbers to be zero. + * + * a SP integer. + * b SP integer. + * c SP integer. + * d SP integer. + * e SP integer. + * f SP integer. + * returns MP_OKAY always. + */ +int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, sp_int* e, + sp_int* f) +{ + if (a != NULL) { + a->used = 0; + a->size = SP_INT_DIGITS; + } + if (b != NULL) { + b->used = 0; + b->size = SP_INT_DIGITS; + } + if (c != NULL) { + c->used = 0; + c->size = SP_INT_DIGITS; + } + if (d != NULL) { + d->used = 0; + d->size = SP_INT_DIGITS; + } + if (e != NULL) { + e->used = 0; + e->size = SP_INT_DIGITS; + } + if (f != NULL) { + f->used = 0; + f->size = SP_INT_DIGITS; + } + + return MP_OKAY; +} + +/* Clear the data from the big number and set to zero. + * + * a SP integer. + */ +void sp_clear(sp_int* a) +{ + int i; + + for (i=0; iused; i++) + a->dp[i] = 0; + a->used = 0; +} + +/* Calculate the number of 8-bit values required to represent the big number. + * + * a SP integer. + * returns the count. + */ +int sp_unsigned_bin_size(sp_int* a) +{ + int size = sp_count_bits(a); + return (size + 7) / 8; +} + +/* Convert a number as an array of bytes in big-endian format to a big number. + * + * a SP integer. + * in Array of bytes. + * inSz Number of data bytes in array. + * returns MP_OKAY always. + */ +int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz) +{ + int i, j = 0, s = 0; + + a->dp[0] = 0; + for (i = inSz-1; i >= 0; i--) { + a->dp[j] |= ((sp_int_digit)in[i]) << s; + if (s == DIGIT_BIT - 8) { + a->dp[++j] = 0; + s = 0; + } + else if (s > DIGIT_BIT - 8) { + s = DIGIT_BIT - s; + if (j + 1 >= a->size) + break; + a->dp[++j] = in[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + a->used = j + 1; + if (a->dp[j] == 0) + a->used--; + + for (j++; j < a->size; j++) + a->dp[j] = 0; + + return MP_OKAY; +} + +/* Convert a number as string in big-endian format to a big number. + * Only supports base-16 (hexadecimal). + * Negative values not supported. + * + * a SP integer. + * in NUL terminated string. + * radix Number of values in a digit. + * returns BAD_FUNC_ARG when radix not supported or value is negative, MP_VAL + * when a character is not valid and MP_OKAY otherwise. + */ +int sp_read_radix(sp_int* a, const char* in, int radix) +{ + int i, j, k; + char ch; + + if (radix != 16) + return BAD_FUNC_ARG; + + if (*in == '-') { + return BAD_FUNC_ARG; + } + + j = 0; + k = 0; + a->dp[0] = 0; + for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) { + ch = in[i]; + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch -= 'A' - 10; + else if (ch >= 'a' && ch <= 'f') + ch -= 'a' - 10; + else + return MP_VAL; + + a->dp[k] |= ((sp_int_digit)ch) << j; + j += 4; + if (j == DIGIT_BIT && k < SP_INT_DIGITS) + a->dp[++k] = 0; + j &= DIGIT_BIT - 1; + } + + a->used = k + 1; + if (a->dp[k] == 0) + a->used--; + + for (k++; k < a->size; k++) + a->dp[k] = 0; + + return MP_OKAY; +} + +/* Compare two big numbers. + * + * a SP integer. + * b SP integer. + * returns MP_GT if a is greater than b, MP_LT if a is less than b and MP_EQ + * when a equals b. + */ +int sp_cmp(sp_int* a, sp_int* b) +{ + int i; + + if (a->used > b->used) + return MP_GT; + else if (a->used < b->used) + return MP_LT; + + for (i = a->used - 1; i >= 0; i--) { + if (a->dp[i] > b->dp[i]) + return MP_GT; + else if (a->dp[i] < b->dp[i]) + return MP_LT; + } + return MP_EQ; +} + +/* Count the number of bits in the big number. + * + * a SP integer. + * returns the number of bits. + */ +int sp_count_bits(sp_int* a) +{ + int r = 0; + sp_int_digit d; + + r = a->used - 1; + while (r >= 0 && a->dp[r] == 0) + r--; + if (r < 0) + r = 0; + else { + d = a->dp[r]; + r *= DIGIT_BIT; + while (d != 0) { + r++; + d >>= 1; + } + } + + return r; +} + +/* Determine if the most significant byte of the encoded big number as the top + * bit set. + * + * a SP integer. + * returns 1 when the top bit is set and 0 otherwise. + */ +int sp_leading_bit(sp_int* a) +{ + int bit = 0; + sp_int_digit d; + + if (a->used > 0) { + d = a->dp[a->used - 1]; + while (d > (sp_int_digit)0xff) + d >>= 8; + bit = d >> 7; + } + + return bit; +} + +/* Convert the big number to an array of bytes in big-endian format. + * The array must be large enough for encoded number - use mp_unsigned_bin_size + * to calculate the number of bytes required. + * + * a SP integer. + * returns MP_OKAY always. + */ +int sp_to_unsigned_bin(sp_int* a, byte* out) +{ + int i, j, b; + + j = sp_unsigned_bin_size(a) - 1; + for (i=0; j>=0; i++) { + for (b = 0; b < SP_WORD_SIZE; b += 8) { + out[j--] = a->dp[i] >> b; + if (j < 0) + break; + } + } + + return MP_OKAY; +} + +/* Ensure the data in the big number is zeroed. + * + * a SP integer. + */ +void sp_forcezero(sp_int* a) +{ + ForceZero(a->dp, a->used * sizeof(sp_int_digit)); + a->used = 0; +} + +/* Copy value of big number a into b. + * + * a SP integer. + * b SP integer. + * returns MP_OKAY always. + */ +int sp_copy(sp_int* a, sp_int* b) +{ + if (a != b) { + XMEMCPY(b->dp, a->dp, a->used * sizeof(sp_int_digit)); + b->used = a->used; + } + return MP_OKAY; +} + +/* Set the big number to be the value of the digit. + * + * a SP integer. + * d Digit to be set. + * returns MP_OKAY always. + */ +int sp_set(sp_int* a, sp_int_digit d) +{ + a->dp[0] = d; + a->used = 1; + return MP_OKAY; +} + +/* Checks whether the value of the big number is zero. + * + * a SP integer. + * returns 1 when value is zero and 0 otherwise. + */ +int sp_iszero(sp_int* a) +{ + return a->used == 0; +} + +/* Recalculate the number of digits used. + * + * a SP integer. + */ +void sp_clamp(sp_int* a) +{ + int i; + + for (i = a->used - 1; i >= 0 && a->dp[i] == 0; i--) { + } + a->used = i + 1; +} + +/* Grow big number to be able to hold l digits. + * This function does nothing as the number of digits is fixed. + * + * a SP integer. + * l Number of digits. + * retuns MP_MEM if the number of digits requested is more than available and + * MP_OKAY otherwise. + */ +int sp_grow(sp_int* a, int l) +{ + if (l > a->size) + return MP_MEM; + (void)a; + (void)l; + return MP_OKAY; +} + +#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT) +/* Clear all data in the big number and sets value to zero. + * + * a SP integer. + */ +void sp_zero(sp_int* a) +{ + XMEMSET(a->dp, 0, a->size); + a->used = 0; +} + +/* Add a one digit number to the big number. + * + * a SP integer. + * d Digit to add. + * r SP integer - result. + * returns MP_OKAY always. + */ +int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r) +{ + int i = 0; + + r->dp[0] = a->dp[0] + d; + if (r->dp[i] < a->dp[i]) { + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + 1; + if (r->dp[i] != 0) + break; + } + + if (i == a->used && r->dp[i] == 0) { + a->used++; + a->dp[i] = 1; + } + } + for (; i < a->used; i++) + r->dp[i] = a->dp[i]; + + return MP_OKAY; +} + +/* Left shift the big number by a number of digits. + * WIll chop off digits overflowing maximum size. + * + * a SP integer. + * s Number of digits to shift. + * returns MP_OKAY always. + */ +int sp_lshd(sp_int* a, int s) +{ + if (a->used + s > a->size) + a->used = a->size - s; + + XMEMMOVE(a->dp + s, a->dp, a->used * SP_INT_DIGITS); + a->used += s; + + return MP_OKAY; +} +#endif + +#ifndef NO_PWDBASED +int sp_add(sp_int* a, sp_int* b, sp_int* r) +{ + int i; + sp_digit c = 0; + + for (i = 0; i < a->used && i < b->used; i++) { + r->dp[i] = a->dp[i] + b->dp[i] + c; + if (c == 0) + c = r->dp[i] < a->dp[i]; + else + c = r->dp[i] <= a->dp[i]; + } + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + c; + c = r->dp[i] == 0; + } + for (; i < b->used; i++) { + r->dp[i] = b->dp[i] + c; + c = r->dp[i] == 0; + } + r->dp[i] = c; + a->used = i + c; + + return MP_OKAY; +} +#endif + +#if !defined(USE_FAST_MATH) +/* Returns the run time settings. + * + * returns the settings value. + */ +word32 CheckRunTimeSettings(void) +{ + return CTC_SETTINGS; +} +#endif + +#endif + diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9728f8193..bbc7f6f32 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9640,6 +9640,7 @@ static int dh_generate_test(WC_RNG *rng) DhKey smallKey; byte p[2] = { 0, 5 }; byte g[2] = { 0, 2 }; +#ifndef WOLFSSL_SP_MATH #ifdef WOLFSSL_DH_CONST /* the table for constant DH lookup will round to the lowest byte size 21 */ byte priv[21]; @@ -9650,6 +9651,7 @@ static int dh_generate_test(WC_RNG *rng) #endif word32 privSz = sizeof(priv); word32 pubSz = sizeof(pub); +#endif ret = wc_InitDhKey_ex(&smallKey, HEAP_HINT, devId); if (ret != 0) @@ -9681,6 +9683,7 @@ static int dh_generate_test(WC_RNG *rng) ERROR_OUT(-5706, exit_gen_test); } +#ifndef WOLFSSL_SP_MATH /* Use API. */ ret = wc_DhGenerateKeyPair(&smallKey, rng, priv, &privSz, pub, &pubSz); #if defined(WOLFSSL_ASYNC_CRYPT) @@ -9689,6 +9692,10 @@ static int dh_generate_test(WC_RNG *rng) if (ret != 0) { ret = -5707; } +#else + (void)rng; + ret = 0; +#endif exit_gen_test: wc_FreeDhKey(&smallKey); @@ -14087,7 +14094,9 @@ static int ecc_test_cert_gen(WC_RNG* rng) } bytes = fread(der, 1, FOURK_BUF, file); fclose(file); +#ifdef ENABLE_ECC384_CERT_GEN_TEST (void)eccCaKey384File; +#endif #endif /* USE_CERT_BUFFERS_256 */ #endif /* ENABLE_ECC384_CERT_GEN_TEST */ @@ -14165,8 +14174,10 @@ static int ecc_test_cert_gen(WC_RNG* rng) sizeof_ca_ecc_cert_der_256); #else ret = wc_SetIssuer(&myCert, eccCaCertFile); +#ifdef ENABLE_ECC384_CERT_GEN_TEST (void)eccCaCert384File; #endif +#endif #endif /* ENABLE_ECC384_CERT_GEN_TEST */ if (ret < 0) { ERROR_OUT(-6731, exit); diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 956ed84a1..682c60f6e 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -91,5 +91,6 @@ endif if BUILD_SP nobase_include_HEADERS+= wolfssl/wolfcrypt/sp.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp_int.h endif diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index f35c08bb0..14767b9ab 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -33,7 +33,9 @@ may not be faster on all */ #include /* will set MP_xxBIT if not default */ -#ifdef USE_FAST_MATH +#ifdef WOLFSSL_SP_MATH + #include +#elif defined(USE_FAST_MATH) #include #else diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 01a39a53e..737b3c8df 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1310,7 +1310,7 @@ extern void uITRON4_free(void *p) ; /* user can specify what curves they want with ECC_USER_CURVES otherwise * all curves are on by default for now */ #ifndef ECC_USER_CURVES - #ifndef HAVE_ALL_CURVES + #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_ALL_CURVES) #define HAVE_ALL_CURVES #endif #endif @@ -1326,6 +1326,10 @@ extern void uITRON4_free(void *p) ; #undef HAVE_ECC_VERIFY #define HAVE_ECC_VERIFY #endif + #ifndef NO_ECC_CHECK_KEY + #undef HAVE_ECC_CHECK_KEY + #define HAVE_ECC_CHECK_KEY + #endif #ifndef NO_ECC_DHE #undef HAVE_ECC_DHE #define HAVE_ECC_DHE diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index 6e0f99194..3e4731f03 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -31,35 +31,10 @@ #include #include +#include + #include -#if defined(NO_64BIT) || !defined(HAVE___UINT128_T) -#define SP_WORD_SIZE 32 -#else -#define SP_WORD_SIZE 64 -#endif - -#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) - #if SP_WORD_SIZE == 32 - typedef int32_t sp_digit; - #elif SP_WORD_SIZE == 64 - typedef int64_t sp_digit; - typedef long int128_t __attribute__ ((mode(TI))); - #else - #error Word size not defined - #endif -#else - #if SP_WORD_SIZE == 32 - typedef uint32_t sp_digit; - #elif SP_WORD_SIZE == 64 - typedef uint64_t sp_digit; - typedef unsigned long uint128_t __attribute__ ((mode(TI))); - typedef long int128_t __attribute__ ((mode(TI))); - #else - #error Word size not defined - #endif -#endif - #if defined(_MSC_VER) #define SP_NOINLINE __declspec(noinline) #elif defined(__GNUC__) @@ -68,6 +43,7 @@ #define 5P_NOINLINE #endif + #ifdef __cplusplus extern "C" { #endif @@ -110,6 +86,15 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, void* heap); int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY); +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap); +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym); #endif /*ifdef WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h new file mode 100644 index 000000000..bf3dd8ae6 --- /dev/null +++ b/wolfssl/wolfcrypt/sp_int.h @@ -0,0 +1,165 @@ +/* sp_int.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SP_INT_H +#define WOLF_CRYPT_SP_INT_H + +#include +#include + +#if defined(NO_64BIT) || !defined(HAVE___UINT128_T) +#define SP_WORD_SIZE 32 +#else +#define SP_WORD_SIZE 64 +#endif + +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) + #if SP_WORD_SIZE == 32 + typedef int32_t sp_digit; + typedef uint32_t sp_int_digit; + #elif SP_WORD_SIZE == 64 + typedef int64_t sp_digit; + typedef uint64_t sp_int_digit; + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#else + #if SP_WORD_SIZE == 32 + typedef uint32_t sp_digit; + typedef uint32_t sp_int_digit; + #elif SP_WORD_SIZE == 64 + typedef uint64_t sp_digit; + typedef uint64_t sp_int_digit; + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#endif + +#ifdef WOLFSSL_SP_MATH +#include + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + + +#if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) + #if !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512) + #define SP_INT_DIGITS ((512 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((256 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#elif !defined(WOLFSSL_SP_NO_3072) + #define SP_INT_DIGITS ((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) +#else + #define SP_INT_DIGITS ((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) +#endif + +#define sp_isodd(a) (a->used != 0 && (a->dp[0] & 1)) + +typedef struct sp_int { + sp_int_digit dp[SP_INT_DIGITS]; + int size; + int used; +} sp_int; + + +WOLFSSL_LOCAL int sp_init(sp_int* a); +WOLFSSL_LOCAL int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, + sp_int* e, sp_int* f); +WOLFSSL_LOCAL void sp_clear(sp_int* a); +WOLFSSL_LOCAL int sp_unsigned_bin_size(sp_int* a); +WOLFSSL_LOCAL int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz); +WOLFSSL_LOCAL int sp_read_radix(sp_int* a, const char* in, int radix); +WOLFSSL_LOCAL int sp_cmp(sp_int* a, sp_int* b); +WOLFSSL_LOCAL int sp_count_bits(sp_int* a); +WOLFSSL_LOCAL int sp_leading_bit(sp_int* a); +WOLFSSL_LOCAL int sp_to_unsigned_bin(sp_int* a, byte* in); +WOLFSSL_LOCAL void sp_forcezero(sp_int* a); +WOLFSSL_LOCAL int sp_copy(sp_int* a, sp_int* b); +WOLFSSL_LOCAL int sp_set(sp_int* a, sp_int_digit d); +WOLFSSL_LOCAL int sp_iszero(sp_int* a); +WOLFSSL_LOCAL void sp_clamp(sp_int* a); +WOLFSSL_LOCAL int sp_grow(sp_int* a, int l); +WOLFSSL_LOCAL void sp_zero(sp_int* a); +WOLFSSL_LOCAL int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); +WOLFSSL_LOCAL int sp_lshd(sp_int* a, int s); +WOLFSSL_LOCAL int sp_add(sp_int* a, sp_int* b, sp_int* r); + +typedef sp_int mp_int; +typedef sp_digit mp_digit; + +#define MP_OKAY 0 +#define MP_NO 0 +#define MP_YES 1 + +#define MP_RADIX_HEX 16 + +#define MP_GT 1 +#define MP_EQ 0 +#define MP_LT -1 + +#define MP_MEM -2 +#define MP_VAL -3 + +#define DIGIT_BIT SP_WORD_SIZE + +#define CheckFastMathSettings() 1 + +#define mp_free(a) + +#define mp_init sp_init +#define mp_init_multi sp_init_multi +#define mp_clear sp_clear +#define mp_read_unsigned_bin sp_read_unsigned_bin +#define mp_unsigned_bin_size sp_unsigned_bin_size +#define mp_read_radix sp_read_radix +#define mp_cmp sp_cmp +#define mp_count_bits sp_count_bits +#define mp_leading_bit sp_leading_bit +#define mp_to_unsigned_bin sp_to_unsigned_bin +#define mp_forcezero sp_forcezero +#define mp_copy sp_copy +#define mp_set sp_set +#define mp_iszero sp_iszero +#define mp_clamp sp_clamp +#define mp_grow sp_grow +#define mp_zero sp_zero +#define mp_add_d sp_add_d +#define mp_lshd sp_lshd +#define mp_add sp_add +#define mp_isodd sp_isodd + +#define MP_INT_DEFINED + +#include +#endif + +#endif /* WOLF_CRYPT_SP_H */ +