From 8065139050002375a822c90543aa1affa0189255 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 24 Mar 2023 15:02:15 +1000 Subject: [PATCH] SP int: improve use of stack Minimize use of stack. Make very large stack allocations dynamic memory allocations unless WOLFSSL_SP_NO_MALLOC. ProcessBufferTryDecode() split up into a function for each type. ProcessBufferTryDecodeRsa() decodes the data and gets key size rather than having or allocating an RsaKey. Added wc_RsaPrivateKeyValidate() that only validates the encoding is an RSA key and returns the key size in bytes. For SP int, only create sp_ints of required size in RSA and ECC implementation. For WOLFSSL_SMALL_STACK, memory is allocated to have just enough bytes and size is set to maximum supported. Otherwise, relies on dynamic stack variables. For ECC, MAX_ECC_BITS_USE used when dynamic stack variables not supported. Significantly reduces memory usage when RSA/DH is also built. Add macros to sp_int.h, tfm.h and integer.h to support declaring, allocating, initializing and freeing mp_ints. For integer.h, mp_int is always static as size is no more than 32 bytes. For tfm.h, WOLFSSL_SMALL_STACK has a full mp_int allocated, otherwise the full mp_int is put on the stack. For sp_int.h with new macros, dynamically allocate sp_int to minimal size when WOLFSSL_SMALL_STACK, or when dynamic stack variables, declare them to be of minimal size or otherwise declare with a fixed max. Added mp_bitsused(), for all implementations, to get the number of bits available based on used. Included for RSA to get the size of the modulus. SP int now always uses dynamic stack variables if possible rather than for builds with WOLFSSL_SP_SMALL. Moved code out into separate functions so that stack allocations don't happen when not going down code path. --- src/ssl.c | 950 ++++++++------- wolfcrypt/src/asn.c | 223 +++- wolfcrypt/src/ecc.c | 2082 +++++++++++++++++--------------- wolfcrypt/src/rsa.c | 557 +++++---- wolfcrypt/src/sp_int.c | 373 +++--- wolfssl/internal.h | 2 + wolfssl/wolfcrypt/asn_public.h | 9 +- wolfssl/wolfcrypt/integer.h | 22 + wolfssl/wolfcrypt/rsa.h | 5 + wolfssl/wolfcrypt/settings.h | 3 + wolfssl/wolfcrypt/sp_int.h | 106 +- wolfssl/wolfcrypt/tfm.h | 52 + 12 files changed, 2486 insertions(+), 1898 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 4b33be8dd..efd9afb93 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6641,8 +6641,535 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, return ret; } -static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der, - int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId) +#ifndef NO_RSA +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) +static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + int devId) +{ + int ret; + + (void)devId; + + *idx = 0; + ret = wc_RsaPrivateKeyValidate(der->buffer, idx, keySz, der->length); +#ifdef WOLF_PRIVATE_KEY_ID + if ((ret != 0) && (devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ctx) + #endif + )) { + word32 nSz; + + /* if using crypto or PK callbacks, try public key decode */ + *idx = 0; + ret = wc_RsaPublicKeyDecode_ex(der->buffer, idx, der->length, NULL, + &nSz, NULL, NULL); + if (ret == 0) { + *keySz = (int)nSz; + } + } +#endif + if (ret != 0) { + #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) && !defined(HAVE_PQC) + WOLFSSL_MSG("RSA decode failed and other algorithms " + "not enabled to try"); + ret = WOLFSSL_BAD_FILE; + #else + ret = 0; /* continue trying other algorithms */ + #endif + } + else { + /* check that the size of the RSA key is enough */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; + if (*keySz < minRsaSz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Private Key size too small"); + } + + if (ssl) { + ssl->buffers.keyType = rsa_sa_algo; + ssl->buffers.keySz = *keySz; + } + else { + ctx->privateKeyType = rsa_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = RSAk; + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + *resetSuites = 1; + } + } + + return ret; +} +#else +static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap, int devId) +{ + int ret; + + /* make sure RSA key can be used */ +#ifdef WOLFSSL_SMALL_STACK + RsaKey* key; +#else + RsaKey key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); + if (key == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey_ex(key, heap, devId); + if (ret == 0) { + *idx = 0; + ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + if (ret != 0 && (devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ctx) + #endif + )) { + /* if using crypto or PK callbacks, try public key decode */ + *idx = 0; + ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length); + } + #endif + if (ret != 0) { + #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) && !defined(HAVE_PQC) + WOLFSSL_MSG("RSA decode failed and other algorithms " + "not enabled to try"); + ret = WOLFSSL_BAD_FILE; + #else + ret = 0; /* continue trying other algorithms */ + #endif + } + else { + /* check that the size of the RSA key is enough */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; + *keySz = wc_RsaEncryptSize((RsaKey*)key); + if (*keySz < minRsaSz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Private Key size too small"); + } + + if (ssl) { + ssl->buffers.keyType = rsa_sa_algo; + ssl->buffers.keySz = *keySz; + } + else { + ctx->privateKeyType = rsa_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = RSAk; + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + *resetSuites = 1; + } + } + + wc_FreeRsaKey(key); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_RSA); +#endif + + return ret; +} +#endif +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap, int devId) +{ + int ret = 0; + /* make sure ECC key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ecc_key* key; +#else + ecc_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); + if (key == NULL) + return MEMORY_E; +#endif + + if (wc_ecc_init_ex(key, heap, devId) == 0) { + *idx = 0; + ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + if (ret != 0 && (devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ctx) + #endif + )) { + /* if using crypto or PK callbacks, try public key decode */ + *idx = 0; + ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length); + } + #endif + if (ret == 0) { + /* check for minimum ECC key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + *keySz = wc_ecc_size(key); + if (*keySz < minKeySz) { + WOLFSSL_MSG("ECC private key too small"); + ret = ECC_KEY_SIZE_E; + } + + *keyFormat = ECDSAk; + if (ssl) { + ssl->options.haveStaticECC = 1; + ssl->buffers.keyType = ecc_dsa_sa_algo; + ssl->buffers.keySz = *keySz; + } + else { + ctx->haveStaticECC = 1; + ctx->privateKeyType = ecc_dsa_sa_algo; + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + else { + ret = 0; /* continue trying other algorithms */ + } + + wc_ecc_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ECC); +#endif + return ret; +} +#endif /* HAVE_ECC */ + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) +static int ProcessBufferTryDecodeEd25519(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap, int devId) +{ + int ret; + /* make sure Ed25519 key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ed25519_key* key; +#else + ed25519_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, + DYNAMIC_TYPE_ED25519); + if (key == NULL) + return MEMORY_E; +#endif + + ret = wc_ed25519_init_ex(key, heap, devId); + if (ret == 0) { + *idx = 0; + ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + if (ret != 0 && (devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ctx) + #endif + )) { + /* if using crypto or PK callbacks, try public key decode */ + *idx = 0; + ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key, der->length); + } + #endif + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + *keySz = ED25519_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("ED25519 private key too small"); + ret = ECC_KEY_SIZE_E; + } + if (ret == 0) { + if (ssl) { + ssl->buffers.keyType = ed25519_sa_algo; + ssl->buffers.keySz = *keySz; + } + else if (ctx) { + ctx->privateKeyType = ed25519_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = ED25519k; + if (ssl != NULL) { + /* ED25519 requires caching enabled for tracking message + * hash used in EdDSA_Update for signing */ + ssl->options.cacheMessages = 1; + if (ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + } + } + else { + ret = 0; /* continue trying other algorithms */ + } + + wc_ed25519_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ED25519); +#endif + return ret; +} +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) +static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap, int devId) +{ + int ret; + /* make sure Ed448 key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ed448_key* key = NULL; +#else + ed448_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); + if (key == NULL) + return MEMORY_E; +#endif + + ret = wc_ed448_init_ex(key, heap, devId); + if (ret == 0) { + *idx = 0; + ret = wc_Ed448PrivateKeyDecode(der->buffer, idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + if (ret != 0 && (devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ctx) + #endif + )) { + /* if using crypto or PK callbacks, try public key decode */ + *idx = 0; + ret = wc_Ed448PublicKeyDecode(der->buffer, idx, key, der->length); + } + #endif + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + *keySz = ED448_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("ED448 private key too small"); + ret = ECC_KEY_SIZE_E; + } + } + if (ret == 0) { + if (ssl) { + ssl->buffers.keyType = ed448_sa_algo; + ssl->buffers.keySz = *keySz; + } + else if (ctx) { + ctx->privateKeyType = ed448_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = ED448k; + if (ssl != NULL) { + /* ED448 requires caching enabled for tracking message + * hash used in EdDSA_Update for signing */ + ssl->options.cacheMessages = 1; + if (ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + } + + wc_ed448_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ED448); +#endif + return ret; +} +#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ + +#if defined(HAVE_PQC) +#if defined(HAVE_FALCON) +static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap) +{ + int ret; + /* make sure Falcon key can be used */ + falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, + DYNAMIC_TYPE_FALCON); + if (key == NULL) { + return MEMORY_E; + } + ret = wc_falcon_init(key); + if (ret == 0) { + if (*keyFormat == FALCON_LEVEL1k) { + ret = wc_falcon_set_level(key, 1); + } + else if (*keyFormat == FALCON_LEVEL5k) { + ret = wc_falcon_set_level(key, 5); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + wc_falcon_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + *idx = 0; + ret = wc_falcon_import_private_only(der->buffer, der->length, key); + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz; + *keySz = FALCON_MAX_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("Falcon private key too small"); + ret = FALCON_KEY_SIZE_E; + } + if (ssl) { + if (*keyFormat == FALCON_LEVEL1k) { + ssl->buffers.keyType = falcon_level1_sa_algo; + } + else { + ssl->buffers.keyType = falcon_level5_sa_algo; + } + ssl->buffers.keySz = *keySz; + } + else { + if (*keyFormat == FALCON_LEVEL1k) { + ctx->privateKeyType = falcon_level1_sa_algo; + } + else { + ctx->privateKeyType = falcon_level5_sa_algo; + } + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + wc_falcon_free(key); + } + XFREE(key, heap, DYNAMIC_TYPE_FALCON); + return ret; +} +#endif + +#if defined(HAVE_DILITHIUM) +static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap) +{ + int ret; + /* make sure Dilithium key can be used */ + dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap, + DYNAMIC_TYPE_DILITHIUM); + if (key == NULL) { + return MEMORY_E; + } + ret = wc_dilithium_init(key); + if (ret == 0) { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ret = wc_dilithium_set_level(key, 2); + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ret = wc_dilithium_set_level(key, 3); + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ret = wc_dilithium_set_level(key, 5); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + wc_dilithium_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + *idx = 0; + ret = wc_dilithium_import_private_only(der->buffer, der->length, key); + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz; + *keySz = DILITHIUM_MAX_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("Dilithium private key too small"); + ret = DILITHIUM_KEY_SIZE_E; + } + if (ssl) { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ssl->buffers.keyType = dilithium_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ssl->buffers.keyType = dilithium_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ssl->buffers.keyType = dilithium_level5_sa_algo; + } + ssl->buffers.keySz = *keySz; + } + else { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ctx->privateKeyType = dilithium_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ctx->privateKeyType = dilithium_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ctx->privateKeyType = dilithium_level5_sa_algo; + } + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + wc_dilithium_free(key); + } + XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); + + return ret; +} +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ + +static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, + void* heap, int devId) { int ret = 0; @@ -6656,294 +7183,38 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der #ifndef NO_RSA if ((*keyFormat == 0 || *keyFormat == RSAk)) { - /* make sure RSA key can be used */ - #ifdef WOLFSSL_SMALL_STACK - RsaKey* key; - #else - RsaKey key[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); - if (key == NULL) - return MEMORY_E; - #endif - - ret = wc_InitRsaKey_ex(key, heap, devId); - if (ret == 0) { - *idx = 0; - ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || wolfSSL_CTX_IsPrivatePkSet(ctx) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret != 0) { - #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) && !defined(HAVE_PQC) - WOLFSSL_MSG("RSA decode failed and other algorithms " - "not enabled to try"); - ret = WOLFSSL_BAD_FILE; - #else - ret = 0; /* continue trying other algorithms */ - #endif - } - else { - /* check that the size of the RSA key is enough */ - int minRsaSz = ssl ? ssl->options.minRsaKeySz : - ctx->minRsaKeySz; - *keySz = wc_RsaEncryptSize((RsaKey*)key); - if (*keySz < minRsaSz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Private Key size too small"); - } - - if (ssl) { - ssl->buffers.keyType = rsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->privateKeyType = rsa_sa_algo; - ctx->privateKeySz = *keySz; - } - - *keyFormat = RSAk; - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - ssl->options.haveStaticECC = 0; - *resetSuites = 1; - } - } - - wc_FreeRsaKey(key); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_RSA); - #endif +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keySz, idx, resetSuites, + keyFormat, devId); +#else + ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keySz, idx, resetSuites, + keyFormat, heap, devId); +#endif if (ret != 0) return ret; } #endif #ifdef HAVE_ECC if ((*keyFormat == 0 || *keyFormat == ECDSAk)) { - /* make sure ECC key can be used */ - #ifdef WOLFSSL_SMALL_STACK - ecc_key* key; - #else - ecc_key key[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); - if (key == NULL) - return MEMORY_E; - #endif - - if (wc_ecc_init_ex(key, heap, devId) == 0) { - *idx = 0; - ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || wolfSSL_CTX_IsPrivatePkSet(ctx) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret == 0) { - /* check for minimum ECC key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : - ctx->minEccKeySz; - *keySz = wc_ecc_size(key); - if (*keySz < minKeySz) { - WOLFSSL_MSG("ECC private key too small"); - ret = ECC_KEY_SIZE_E; - } - - *keyFormat = ECDSAk; - if (ssl) { - ssl->options.haveStaticECC = 1; - ssl->buffers.keyType = ecc_dsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->haveStaticECC = 1; - ctx->privateKeyType = ecc_dsa_sa_algo; - ctx->privateKeySz = *keySz; - } - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - else { - ret = 0; /* continue trying other algorithms */ - } - - wc_ecc_free(key); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ECC); - #endif + ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keySz, idx, resetSuites, + keyFormat, heap, devId); if (ret != 0) return ret; } #endif /* HAVE_ECC */ #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) if ((*keyFormat == 0 || *keyFormat == ED25519k)) { - /* make sure Ed25519 key can be used */ - #ifdef WOLFSSL_SMALL_STACK - ed25519_key* key; - #else - ed25519_key key[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, - DYNAMIC_TYPE_ED25519); - if (key == NULL) - return MEMORY_E; - #endif - - ret = wc_ed25519_init_ex(key, heap, devId); - if (ret == 0) { - *idx = 0; - ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || wolfSSL_CTX_IsPrivatePkSet(ctx) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key, - der->length); - } - #endif - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : - ctx->minEccKeySz; - *keySz = ED25519_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("ED25519 private key too small"); - ret = ECC_KEY_SIZE_E; - } - if (ret == 0) { - if (ssl) { - ssl->buffers.keyType = ed25519_sa_algo; - ssl->buffers.keySz = *keySz; - } - else if (ctx) { - ctx->privateKeyType = ed25519_sa_algo; - ctx->privateKeySz = *keySz; - } - - *keyFormat = ED25519k; - if (ssl != NULL) { - /* ED25519 requires caching enabled for tracking message - * hash used in EdDSA_Update for signing */ - ssl->options.cacheMessages = 1; - if (ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - } - } - else { - ret = 0; /* continue trying other algorithms */ - } - - wc_ed25519_free(key); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED25519); - #endif + ret = ProcessBufferTryDecodeEd25519(ctx, ssl, der, keySz, idx, + resetSuites, keyFormat, heap, devId); if (ret != 0) return ret; } #endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) if ((*keyFormat == 0 || *keyFormat == ED448k)) { - /* make sure Ed448 key can be used */ - #ifdef WOLFSSL_SMALL_STACK - ed448_key* key = NULL; - #else - ed448_key key[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); - if (key == NULL) - return MEMORY_E; - #endif - - ret = wc_ed448_init(key); - if (ret == 0) { - *idx = 0; - ret = wc_Ed448PrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || wolfSSL_CTX_IsPrivatePkSet(ctx) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_Ed448PublicKeyDecode(der->buffer, idx, key, - der->length); - } - #endif - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : - ctx->minEccKeySz; - *keySz = ED448_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("ED448 private key too small"); - ret = ECC_KEY_SIZE_E; - } - } - if (ret == 0) { - if (ssl) { - ssl->buffers.keyType = ed448_sa_algo; - ssl->buffers.keySz = *keySz; - } - else if (ctx) { - ctx->privateKeyType = ed448_sa_algo; - ctx->privateKeySz = *keySz; - } - - *keyFormat = ED448k; - if (ssl != NULL) { - /* ED448 requires caching enabled for tracking message - * hash used in EdDSA_Update for signing */ - ssl->options.cacheMessages = 1; - if (ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - } - - wc_ed448_free(key); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED448); - #endif + ret = ProcessBufferTryDecodeEd448(ctx, ssl, der, keySz, idx, + resetSuites, keyFormat, heap, devId); if (ret != 0) return ret; } @@ -6952,66 +7223,8 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der #if defined(HAVE_FALCON) if (((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) || (*keyFormat == FALCON_LEVEL5k))) { - /* make sure Falcon key can be used */ - falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, - DYNAMIC_TYPE_FALCON); - if (key == NULL) { - return MEMORY_E; - } - ret = wc_falcon_init(key); - if (ret == 0) { - if (*keyFormat == FALCON_LEVEL1k) { - ret = wc_falcon_set_level(key, 1); - } - else if (*keyFormat == FALCON_LEVEL5k) { - ret = wc_falcon_set_level(key, 5); - } - else { - /* What if *keyformat is 0? We might want to do something more - * graceful here. */ - wc_falcon_free(key); - ret = ALGO_ID_E; - } - } - - if (ret == 0) { - *idx = 0; - ret = wc_falcon_import_private_only(der->buffer, der->length, key); - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minFalconKeySz : - ctx->minFalconKeySz; - *keySz = FALCON_MAX_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("Falcon private key too small"); - ret = FALCON_KEY_SIZE_E; - } - if (ssl) { - if (*keyFormat == FALCON_LEVEL1k) { - ssl->buffers.keyType = falcon_level1_sa_algo; - } - else { - ssl->buffers.keyType = falcon_level5_sa_algo; - } - ssl->buffers.keySz = *keySz; - } - else { - if (*keyFormat == FALCON_LEVEL1k) { - ctx->privateKeyType = falcon_level1_sa_algo; - } - else { - ctx->privateKeyType = falcon_level5_sa_algo; - } - ctx->privateKeySz = *keySz; - } - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - wc_falcon_free(key); - } - XFREE(key, heap, DYNAMIC_TYPE_FALCON); + ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keySz, idx, + resetSuites, keyFormat, heap); if (ret != 0) return ret; } @@ -7021,77 +7234,8 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der (*keyFormat == DILITHIUM_LEVEL2k) || (*keyFormat == DILITHIUM_LEVEL3k) || (*keyFormat == DILITHIUM_LEVEL5k)) { - /* make sure Dilithium key can be used */ - dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), - heap, - DYNAMIC_TYPE_DILITHIUM); - if (key == NULL) { - return MEMORY_E; - } - ret = wc_dilithium_init(key); - if (ret == 0) { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ret = wc_dilithium_set_level(key, 2); - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ret = wc_dilithium_set_level(key, 3); - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ret = wc_dilithium_set_level(key, 5); - } - else { - /* What if *keyformat is 0? We might want to do something more - * graceful here. */ - wc_dilithium_free(key); - ret = ALGO_ID_E; - } - } - - if (ret == 0) { - *idx = 0; - ret = wc_dilithium_import_private_only(der->buffer, der->length, - key); - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minDilithiumKeySz : - ctx->minDilithiumKeySz; - *keySz = DILITHIUM_MAX_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("Dilithium private key too small"); - ret = DILITHIUM_KEY_SIZE_E; - } - if (ssl) { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ssl->buffers.keyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ssl->buffers.keyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ssl->buffers.keyType = dilithium_level5_sa_algo; - } - ssl->buffers.keySz = *keySz; - } - else { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ctx->privateKeyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ctx->privateKeyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ctx->privateKeyType = dilithium_level5_sa_algo; - } - ctx->privateKeySz = *keySz; - } - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - wc_dilithium_free(key); - } - XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); + ret = ProcessBufferTryDecodeDilithium(ctx, ssl, der, keySz, idx, + resetSuites, keyFormat, heap); if (ret != 0) { return ret; } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a7c72c021..716491eca 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3273,8 +3273,6 @@ static int GetIntPositive(mp_int* mpi, const byte* input, word32* inOutIdx, #endif /* (ECC || !NO_DSA) && !WOLFSSL_ASN_TEMPLATE */ #ifndef WOLFSSL_ASN_TEMPLATE -#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \ - || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA)) #if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || !defined(NO_DSA) static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx) { @@ -3291,7 +3289,6 @@ static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx) return 0; } #endif -#endif #endif /* !WOLFSSL_ASN_TEMPLATE */ #ifdef WOLFSSL_ASN_TEMPLATE @@ -6350,9 +6347,12 @@ enum { * @param [in] input Buffer holding BER encoded data. * @param [in, out] inOutIdx On in, start of RSA private key. * On out, start of ASN.1 item after RSA private key. - * @param [in, out] key RSA key object. + * @param [in, out] key RSA key object. May be NULL. + * @param [out] keySz Size of key in bytes. May be NULL. * @param [in] inSz Number of bytes in buffer. * @return 0 on success. + * @return BAD_FUNC_ARG when input or inOutIdx is NULL. + * @return BAD_FUNC_ARG when key and keySz are NULL. * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or * is invalid. * @return BUFFER_E when data in buffer is too small. @@ -6361,14 +6361,14 @@ enum { * @return MP_INIT_E when the unable to initialize an mp_int. * @return ASN_GETINT_E when the unable to convert data to an mp_int. */ -int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, - word32 inSz) +static int _RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey* key, int* keySz, word32 inSz) { #ifndef WOLFSSL_ASN_TEMPLATE int version, length; word32 algId = 0; - if (inOutIdx == NULL || input == NULL || key == NULL) { + if (inOutIdx == NULL || input == NULL || (key == NULL && keySz == NULL)) { return BAD_FUNC_ARG; } @@ -6383,50 +6383,66 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) return ASN_PARSE_E; - key->type = RSA_PRIVATE; + if (key == NULL) { + int i; -#ifdef WOLFSSL_CHECK_MEM_ZERO - mp_memzero_add("Decode RSA key d", &key->d); - mp_memzero_add("Decode RSA key p", &key->p); - mp_memzero_add("Decode RSA key q", &key->q); -#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ - !defined(RSA_LOW_MEM)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) - mp_memzero_add("Decode RSA key dP", &key->dP); - mp_memzero_add("Decode RSA key dQ", &key->dQ); - mp_memzero_add("Decode RSA key u", &key->u); -#endif -#endif - - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 || -#ifndef WOLFSSL_RSA_PUBLIC_ONLY - GetInt(&key->d, input, inOutIdx, inSz) < 0 || - GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 -#else - SkipInt(input, inOutIdx, inSz) < 0 || - SkipInt(input, inOutIdx, inSz) < 0 || - SkipInt(input, inOutIdx, inSz) < 0 -#endif - ) { - return ASN_RSA_KEY_E; - } -#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \ - && !defined(WOLFSSL_RSA_PUBLIC_ONLY) - if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 || - GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || - GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; -#else - if (SkipInt(input, inOutIdx, inSz) < 0 || - SkipInt(input, inOutIdx, inSz) < 0 || - SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; -#endif - -#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) - if (wc_InitRsaHw(key) != 0) { - return BAD_STATE_E; + /* Modulus */ + if (GetASNInt(input, inOutIdx, keySz, inSz) < 0) { + return ASN_PARSE_E; + } + *inOutIdx += *keySz; + for (i = 1; i < RSA_INTS; i++) { + if (SkipInt(input, inOutIdx, inSz) < 0) { + return ASN_RSA_KEY_E; + } + } + } + else { + key->type = RSA_PRIVATE; + + #ifdef WOLFSSL_CHECK_MEM_ZERO + mp_memzero_add("Decode RSA key d", &key->d); + mp_memzero_add("Decode RSA key p", &key->p); + mp_memzero_add("Decode RSA key q", &key->q); + #if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ + !defined(RSA_LOW_MEM)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + mp_memzero_add("Decode RSA key dP", &key->dP); + mp_memzero_add("Decode RSA key dQ", &key->dQ); + mp_memzero_add("Decode RSA key u", &key->u); + #endif + #endif + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + GetInt(&key->d, input, inOutIdx, inSz) < 0 || + GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 + #else + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 + #endif + ) { + return ASN_RSA_KEY_E; + } + #if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \ + && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || + GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + #else + if (SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + #endif + + #if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } + #endif } -#endif return 0; #else @@ -6436,12 +6452,20 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, #if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) word32 algId = 0; #endif + void* heap = NULL; + + (void)heap; /* Check validity of parameters. */ - if (inOutIdx == NULL || input == NULL || key == NULL) { + if ((inOutIdx == NULL) || (input == NULL) || ((key == NULL) && + (keySz == NULL))) { ret = BAD_FUNC_ARG; } + if ((ret == 0) && (key != NULL)) { + heap = key->heap; + } + #if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) if (ret == 0) { /* if has pkcs8 header skip it */ @@ -6451,7 +6475,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, } #endif - CALLOC_ASNGETDATA(dataASN, rsaKeyASN_Length, ret, key->heap); + CALLOC_ASNGETDATA(dataASN, rsaKeyASN_Length, ret, heap); if (ret == 0) { int i; @@ -6459,20 +6483,21 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, GetASN_Int8Bit(&dataASN[RSAKEYASN_IDX_VER], &version); /* Setup data to store INTEGER data in mp_int's in RSA object. */ #if defined(WOLFSSL_RSA_PUBLIC_ONLY) - /* Extract all public fields. */ - for (i = 0; i < RSA_PUB_INTS; i++) { - GetASN_MP(&dataASN[(byte)RSAKEYASN_IDX_N + i], GetRsaInt(key, i)); - } + #define RSA_ASN_INTS RSA_PUB_INTS /* Not extracting all data from BER encoding. */ #define RSA_ASN_COMPLETE 0 #else - /* Extract all private fields. */ - for (i = 0; i < RSA_INTS; i++) { - GetASN_MP(&dataASN[(byte)RSAKEYASN_IDX_N + i], GetRsaInt(key, i)); - } + #define RSA_ASN_INTS RSA_INTS /* Extracting all data from BER encoding. */ #define RSA_ASN_COMPLETE 1 #endif + if (key != NULL) { + /* Extract all public fields. */ + for (i = 0; i < RSA_ASN_INTS; i++) { + GetASN_MP(&dataASN[(byte)RSAKEYASN_IDX_N + i], + GetRsaInt(key, i)); + } + } /* Parse BER encoding for RSA private key. */ ret = GetASN_Items(rsaKeyASN, dataASN, rsaKeyASN_Length, RSA_ASN_COMPLETE, input, inOutIdx, inSz); @@ -6484,7 +6509,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if ((ret == 0) && (version > PKCS1v1)) { ret = ASN_PARSE_E; } - if (ret == 0) { + if ((ret == 0) && (key != NULL)) { #if !defined(WOLFSSL_RSA_PUBLIC_ONLY) /* RSA key object has all private key values. */ key->type = RSA_PRIVATE; @@ -6498,11 +6523,78 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, ret = BAD_STATE_E; #endif } + else if (ret == 0) { + /* Not filling in key but do want key size. */ + *keySz = dataASN[(byte)RSAKEYASN_IDX_N].length; + /* Check whether first byte of data is 0x00 and drop it. */ + if (input[dataASN[(byte)RSAKEYASN_IDX_E].offset - *keySz] == 0) { + (*keySz)--; + } + } - FREE_ASNGETDATA(dataASN, key->heap); + FREE_ASNGETDATA(dataASN, heap); return ret; #endif /* WOLFSSL_ASN_TEMPLATE */ } + +/* Decode RSA private key. + * + * PKCS #1: RFC 8017, A.1.2 - RSAPrivateKey + * + * Compiling with WOLFSSL_RSA_PUBLIC_ONLY will result in only the public fields + * being extracted. + * + * @param [in] input Buffer holding BER encoded data. + * @param [in, out] inOutIdx On in, start of RSA private key. + * On out, start of ASN.1 item after RSA private key. + * @param [in, out] key RSA key object. + * @param [in] inSz Number of bytes in buffer. + * @return 0 on success. + * @return BAD_FUNC_ARG when input, inOutIdx or key is NULL. + * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or + * is invalid. + * @return BUFFER_E when data in buffer is too small. + * @return ASN_EXPECT_0_E when the INTEGER has the MSB set or NULL has a + * non-zero length. + * @return MP_INIT_E when the unable to initialize an mp_int. + * @return ASN_GETINT_E when the unable to convert data to an mp_int. + */ +int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + return _RsaPrivateKeyDecode(input, inOutIdx, key, NULL, inSz); +} + +/* Valdidate RSA private key ASN.1 encoding. + * + * PKCS #1: RFC 8017, A.1.2 - RSAPrivateKey + * + * Compiling with WOLFSSL_RSA_PUBLIC_ONLY will result in only the public fields + * being extracted. + * + * @param [in] input Buffer holding BER encoded data. + * @param [in, out] inOutIdx On in, start of RSA private key. + * On out, start of ASN.1 item after RSA private key. + * @param [in] inSz Number of bytes in buffer. + * @return 0 on success. + * @return BAD_FUNC_ARG when input, inOutIdx or keySz is NULL. + * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or + * is invalid. + * @return BUFFER_E when data in buffer is too small. + * @return ASN_EXPECT_0_E when the INTEGER has the MSB set or NULL has a + * non-zero length. + * @return MP_INIT_E when the unable to initialize an mp_int. + * @return ASN_GETINT_E when the unable to convert data to an mp_int. + */ +int wc_RsaPrivateKeyValidate(const byte* input, word32* inOutIdx, int* keySz, + word32 inSz) +{ + return _RsaPrivateKeyDecode(input, inOutIdx, NULL, keySz, inSz); +} + #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ @@ -31167,14 +31259,17 @@ static int EccSpecifiedECDomainDecode(const byte* input, word32 inSz, /* Allocate a new parameter set. */ curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap, DYNAMIC_TYPE_ECC_BUFFER); - if (curve == NULL) + if (curve == NULL) { ret = MEMORY_E; + } + else { + /* Clear out parameters and set fields to indicate it is custom. */ + XMEMSET(curve, 0, sizeof(*curve)); + } CALLOC_ASNGETDATA(dataASN, eccSpecifiedASN_Length, ret, key->heap); if (ret == 0) { - /* Clear out parameters and set fields to indicate it is custom. */ - XMEMSET(curve, 0, sizeof(*curve)); /* Set name to be: "Custom" */ #ifndef WOLFSSL_ECC_CURVE_STATIC curve->name = ecSetCustomName; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 5a6ac7162..3003443ae 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -222,6 +222,15 @@ ECC Curve Sizes: #define HAVE_ECC_MAKE_PUB #endif +#if defined(WOLFSSL_SP_MATH_ALL) && SP_INT_BITS < MAX_ECC_BITS_NEEDED +#define MAX_ECC_BITS_USE SP_INT_BITS +#else +#define MAX_ECC_BITS_USE MAX_ECC_BITS_NEEDED +#endif +#define ECC_KEY_MAX_BITS(key) \ + (((key == NULL) || (key->dp == NULL)) ? MAX_ECC_BITS_USE \ + : (key->dp->size * 8)) + /* forward declarations */ static int wc_ecc_new_point_ex(ecc_point** point, void* heap); static void wc_ecc_del_point_ex(ecc_point* p, void* heap); @@ -1305,8 +1314,12 @@ typedef struct ecc_curve_spec { mp_int order_lcl; mp_int Gx_lcl; mp_int Gy_lcl; +#else +#ifdef WOLFSSL_SP_MATH_ALL + unsigned char* spec_ints; #else mp_int* spec_ints; +#endif word32 spec_count; word32 spec_use; #endif @@ -1390,6 +1403,23 @@ static int xil_mpi_import(mp_int *mpi, #define ALLOC_CURVE_SPECS(intcount, err) #define FREE_CURVE_SPECS() #elif defined(WOLFSSL_SMALL_STACK) +#ifdef WOLFSSL_SP_MATH_ALL + #define DECLARE_CURVE_SPECS(intcount) \ + unsigned char* spec_ints = NULL; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_count = intcount + + #define ALLOC_CURVE_SPECS(intcount, err) \ + spec_ints = (unsigned char*)XMALLOC(MP_INT_SIZEOF(MP_BITS_CNT( \ + MAX_ECC_BITS_USE)) * (intcount), NULL, \ + DYNAMIC_TYPE_ECC); \ + if (spec_ints == NULL) \ + (err) = MEMORY_E; \ + else \ + curve->spec_ints = spec_ints +#else #define DECLARE_CURVE_SPECS(intcount) \ mp_int* spec_ints = NULL; \ ecc_curve_spec curve_lcl; \ @@ -1404,16 +1434,28 @@ static int xil_mpi_import(mp_int *mpi, (err) = MEMORY_E; \ else \ curve->spec_ints = spec_ints +#endif #define FREE_CURVE_SPECS() \ XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC) #else - #define DECLARE_CURVE_SPECS(intcount) \ - mp_int spec_ints[(intcount)]; \ - ecc_curve_spec curve_lcl; \ - ecc_curve_spec* curve = &curve_lcl; \ - XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ - curve->spec_ints = spec_ints; \ +#ifdef WOLFSSL_SP_MATH_ALL + #define DECLARE_CURVE_SPECS(intcount) \ + unsigned char spec_ints[MP_INT_SIZEOF(MP_BITS_CNT( \ + MAX_ECC_BITS_USE)) * intcount]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ curve->spec_count = (intcount) +#else + #define DECLARE_CURVE_SPECS(intcount) \ + mp_int spec_ints[(intcount)]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ + curve->spec_count = (intcount) +#endif #define ALLOC_CURVE_SPECS(intcount, err) #define FREE_CURVE_SPECS() #endif /* ECC_CACHE_CURVE */ @@ -1481,10 +1523,19 @@ static int wc_ecc_curve_cache_load_item(ecc_curve_spec* curve, const char* src, WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count"); return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_SP_MATH_ALL + *dst = (mp_int*)(curve->spec_ints + MP_INT_SIZEOF(MP_BITS_CNT( + MAX_ECC_BITS_USE)) * curve->spec_use++); +#else *dst = &curve->spec_ints[curve->spec_use++]; #endif +#endif +#ifdef WOLFSSL_SP_MATH_ALL + err = mp_init_size(*dst, MP_BITS_CNT(MAX_ECC_BITS_USE)); +#else err = mp_init(*dst); +#endif if (err == MP_OKAY) { curve->load_mask |= mask; @@ -1725,19 +1776,12 @@ static int _ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp) { #if !defined(WOLFSSL_SP_MATH) -#ifdef WOLFSSL_SMALL_STACK - mp_int* t1 = NULL; - mp_int* t2 = NULL; + DECL_MP_INT_SIZE_DYN(t1, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(t2, mp_bitsused(modulus), MAX_ECC_BITS_USE); #ifdef ALT_ECC_SIZE - mp_int* rx = NULL; - mp_int* ry = NULL; - mp_int* rz = NULL; -#endif -#else - mp_int t1[1], t2[1]; -#ifdef ALT_ECC_SIZE - mp_int rx[1], ry[1], rz[1]; -#endif + DECL_MP_INT_SIZE_DYN(rx, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(ry, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(rz, mp_bitsused(modulus), MAX_ECC_BITS_USE); #endif mp_int *x, *y, *z; int err; @@ -1762,78 +1806,86 @@ static int _ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, } else #endif /* WOLFSSL_SMALL_STACK_CACHE */ +#endif /* WOLFSSL_SMALL_STACK */ { - t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (t1 == NULL || t2 == NULL) { - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } + NEW_MP_INT_SIZE(t1, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(t2, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (t1 == NULL || t2 == NULL) { + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif #ifdef ALT_ECC_SIZE - rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (rx == NULL || ry == NULL || rz == NULL) { - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } + NEW_MP_INT_SIZE(rx, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(ry, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(rz, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (rx == NULL || ry == NULL || rz == NULL) { + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif #endif } -#endif /* WOLFSSL_SMALL_STACK */ - if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + err = INIT_MP_INT_SIZE(t1, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(t2, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK_CACHE - if (R->key == NULL) + if (R->key == NULL) #endif - { - #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - } #endif + { + #ifdef ALT_ECC_SIZE + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + } return err; } /* should we dbl instead? */ if (err == MP_OKAY) { #ifdef ECC_TIMING_RESISTANT - err = mp_submod_ct(modulus, Q->y, modulus, t1); + err = mp_submod_ct(modulus, Q->y, modulus, t1); #else - err = mp_sub(modulus, Q->y, t1); + err = mp_sub(modulus, Q->y, t1); #endif } if (err == MP_OKAY) { - if ( (mp_cmp(P->x, Q->x) == MP_EQ) && - (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && - (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) { - mp_clear(t1); - mp_clear(t2); - #ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SMALL_STACK_CACHE - if (R->key == NULL) - #endif - { - #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - } - #endif - return _ecc_projective_dbl_point(P, R, a, modulus, mp); - } + if ( (mp_cmp(P->x, Q->x) == MP_EQ) && + (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && + (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + #endif + { + #ifdef ALT_ECC_SIZE + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + } + return _ecc_projective_dbl_point(P, R, a, modulus, mp); + } } if (err != MP_OKAY) { @@ -1848,7 +1900,14 @@ static int _ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, y = ry; z = rz; - if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + err = INIT_MP_INT_SIZE(x, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(y, mp_bitsused(modulus)); + } + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(z, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { goto done; } #else @@ -2020,17 +2079,17 @@ done: #ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK_CACHE if (R->key == NULL) +#endif #endif { #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); } -#endif return err; #else @@ -2111,19 +2170,12 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, mp_int* modulus, mp_digit mp) { #if !defined(WOLFSSL_SP_MATH) -#ifdef WOLFSSL_SMALL_STACK - mp_int* t1 = NULL; - mp_int* t2 = NULL; + DECL_MP_INT_SIZE_DYN(t1, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(t2, mp_bitsused(modulus), MAX_ECC_BITS_USE); #ifdef ALT_ECC_SIZE - mp_int* rx = NULL; - mp_int* ry = NULL; - mp_int* rz = NULL; -#endif -#else - mp_int t1[1], t2[1]; -#ifdef ALT_ECC_SIZE - mp_int rx[1], ry[1], rz[1]; -#endif + DECL_MP_INT_SIZE_DYN(rx, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(ry, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(rz, mp_bitsused(modulus), MAX_ECC_BITS_USE); #endif mp_int *x, *y, *z; int err; @@ -2141,45 +2193,53 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, } else #endif /* WOLFSSL_SMALL_STACK_CACHE */ +#endif { - t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (t1 == NULL || t2 == NULL) { - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } - #ifdef ALT_ECC_SIZE - rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (rx == NULL || ry == NULL || rz == NULL) { - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } - #endif - } -#endif + NEW_MP_INT_SIZE(t1, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(t2, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (t1 == NULL || t2 == NULL) { + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + #ifdef ALT_ECC_SIZE + NEW_MP_INT_SIZE(rx, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(ry, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(rz, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (rx == NULL || ry == NULL || rz == NULL) { + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + #endif + } - if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + err = INIT_MP_INT_SIZE(t1, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(t2, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK -#ifdef WOLFSSL_SMALL_STACK_CACHE - if (R->key == NULL) -#endif - { - #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - } + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif #endif + { + #ifdef ALT_ECC_SIZE + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + } return err; } @@ -2191,24 +2251,29 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, y = ry; z = rz; - if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - mp_clear(t1); - mp_clear(t2); - #ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SMALL_STACK_CACHE - if (R->key == NULL) - #endif - { - #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - } - #endif - return err; + err = INIT_MP_INT_SIZE(x, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(y, mp_bitsused(modulus)); + } + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(z, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif +#endif + { + #ifdef ALT_ECC_SIZE + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + } + return err; } #else /* Use destination directly */ @@ -2246,7 +2311,7 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, /* Use a and prime to determine if a == 3 */ err = mp_submod(modulus, a, modulus, t2); } - if (err == MP_OKAY && mp_iszero(t2)) { + if (err == MP_OKAY && mp_iszero((MP_INT_SIZE*)t2)) { /* T2 = X * X */ if (err == MP_OKAY) err = mp_sqr(x, t2); @@ -2378,17 +2443,17 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, #ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK_CACHE if (R->key == NULL) +#endif #endif { #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); } -#endif return err; #else @@ -2446,20 +2511,13 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) { #if !defined(WOLFSSL_SP_MATH) -#ifdef WOLFSSL_SMALL_STACK - mp_int* t1 = NULL; - mp_int* t2 = NULL; + DECL_MP_INT_SIZE_DYN(t1, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(t2, mp_bitsused(modulus), MAX_ECC_BITS_USE); #ifdef ALT_ECC_SIZE - mp_int* rx = NULL; - mp_int* ry = NULL; - mp_int* rz = NULL; + DECL_MP_INT_SIZE_DYN(rx, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(ry, mp_bitsused(modulus), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(rz, mp_bitsused(modulus), MAX_ECC_BITS_USE); #endif -#else - mp_int t1[1], t2[1]; -#ifdef ALT_ECC_SIZE - mp_int rx[1], ry[1], rz[1]; -#endif -#endif /* WOLFSSL_SMALL_STACK */ mp_int *x, *y, *z; int err; @@ -2491,45 +2549,53 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) } else #endif /* WOLFSSL_SMALL_STACK_CACHE */ - { - t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (t1 == NULL || t2 == NULL) { - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } -#ifdef ALT_ECC_SIZE - rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); - if (rx == NULL || ry == NULL || rz == NULL) { - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); - return MEMORY_E; - } #endif + { + NEW_MP_INT_SIZE(t1, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(t2, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (t1 == NULL || t2 == NULL) { + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + #ifdef ALT_ECC_SIZE + NEW_MP_INT_SIZE(rx, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(ry, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(rz, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL + if (rx == NULL || ry == NULL || rz == NULL) { + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + #endif } -#endif /* WOLFSSL_SMALL_STACK */ - if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + err = INIT_MP_INT_SIZE(t1, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(t2, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK -#ifdef WOLFSSL_SMALL_STACK_CACHE + #ifdef WOLFSSL_SMALL_STACK_CACHE if (P->key == NULL) + #endif #endif { #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); } -#endif return MEMORY_E; } @@ -2539,16 +2605,23 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) y = ry; z = rz; - if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - goto done; + err = INIT_MP_INT_SIZE(x, mp_bitsused(modulus)); + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(y, mp_bitsused(modulus)); + } + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(z, mp_bitsused(modulus)); + } + if (err != MP_OKAY) { + goto done; } if (err == MP_OKAY) - err = mp_copy(P->x, x); + err = mp_copy(P->x, x); if (err == MP_OKAY) - err = mp_copy(P->y, y); + err = mp_copy(P->y, y); if (err == MP_OKAY) - err = mp_copy(P->z, z); + err = mp_copy(P->z, z); if (err != MP_OKAY) { goto done; @@ -2621,17 +2694,17 @@ done: #ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK_CACHE if (P->key == NULL) +#endif #endif { #ifdef ALT_ECC_SIZE - XFREE(rz, NULL, DYNAMIC_TYPE_ECC); - XFREE(ry, NULL, DYNAMIC_TYPE_ECC); - XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rz, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(ry, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(rx, NULL, DYNAMIC_TYPE_ECC); #endif - XFREE(t2, NULL, DYNAMIC_TYPE_ECC); - XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t2, NULL, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(t1, NULL, DYNAMIC_TYPE_ECC); } -#endif return err; #else @@ -2823,24 +2896,20 @@ static int ecc_mulmod(const mp_int* k, ecc_point* tG, ecc_point* R, #else -static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, - mp_int* modulus, mp_digit mp, mp_int* tx, mp_int* ty) +static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, mp_int* modulus, + mp_digit mp, mp_int* tx, mp_int* ty) { int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK - mp_int* mu = NULL; -#else - mp_int mu[1]; -#endif + DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE); -#ifdef WOLFSSL_SMALL_STACK - mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (mu == NULL) err = MEMORY_E; #endif if (err == MP_OKAY) - err = mp_init(mu); + err = INIT_MP_INT_SIZE(mu, mp_bitsused(modulus)); if (err == MP_OKAY) err = mp_montgomery_calc_normalization(mu, modulus); /* Generate random value to multiply into p->z. */ @@ -2875,14 +2944,8 @@ static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, if (err == MP_OKAY) err = mp_montgomery_reduce(p->y, modulus, mp); -#ifdef WOLFSSL_SMALL_STACK - if (mu != NULL) { - mp_clear(mu); - XFREE(mu, NULL, DYNAMIC_TYPE_ECC); - } -#else mp_clear(mu); -#endif + FREE_MP_INT_SIZE(mu, NULL, DYNAMIC_TYPE_ECC); return err; } @@ -3251,21 +3314,17 @@ static int ecc_point_to_mont(ecc_point* p, ecc_point* r, mp_int* modulus, void* heap) { int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK - mp_int* mu = NULL; -#else - mp_int mu[1]; -#endif + DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE); (void)heap; -#ifdef WOLFSSL_SMALL_STACK - mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (mu == NULL) err = MEMORY_E; #endif if (err == MP_OKAY) - err = mp_init(mu); + err = INIT_MP_INT_SIZE(mu, mp_bitsused(modulus)); if (err == MP_OKAY) { err = mp_montgomery_calc_normalization(mu, modulus); @@ -3288,10 +3347,8 @@ static int ecc_point_to_mont(ecc_point* p, ecc_point* r, mp_int* modulus, mp_clear(mu); } -#ifdef WOLFSSL_SMALL_STACK - if (mu != NULL) - XFREE(mu, heap, DYNAMIC_TYPE_ECC); -#endif + + FREE_MP_INT_SIZE(mu, heap, DYNAMIC_TYPE_ECC); return err; } @@ -3504,6 +3561,53 @@ exit: #endif /* !WOLFSSL_SP_MATH || !FP_ECC */ #ifndef FP_ECC +#if !defined(WOLFSSL_SP_MATH) +#ifdef ECC_TIMING_RESISTANT +static int ecc_check_order_minus_1(const mp_int* k, ecc_point* tG, ecc_point* R, + mp_int* modulus, mp_int* order) +{ + int err; + DECL_MP_INT_SIZE_DYN(t, mp_bitsused(order), MAX_ECC_BITS_USE); + + NEW_MP_INT_SIZE(t, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (t == NULL) { + err = MEMORY_E; + } + else +#endif + { + err = INIT_MP_INT_SIZE(t, mp_bitsused(modulus)); + } + if (err == MP_OKAY) { + /* Check for k == order - 1. Result will be 0 point which is not correct + * Calculates order / 2 and adds order / 2 + 1 and gets infinity. + * (with constant time implementation) + */ + err = mp_sub_d(order, 1, t); + if (err == MP_OKAY) { + int kIsMinusOne = (mp_cmp((mp_int*)k, t) == MP_EQ); + err = mp_cond_copy(tG->x, kIsMinusOne, R->x); + if (err == MP_OKAY) { + err = mp_sub(modulus, tG->y, t); + } + if (err == MP_OKAY) { + err = mp_cond_copy(t, kIsMinusOne, R->y); + } + if (err == MP_OKAY) { + err = mp_cond_copy(tG->z, kIsMinusOne, R->z); + } + } + + mp_free(t); + } + + FREE_MP_INT_SIZE(t, NULL, DYNAMIC_TYPE_ECC); + return err; +} +#endif /* ECC_TIMING_RESISTANT */ +#endif + /** Perform a point multiplication k The scalar to multiply by @@ -3515,7 +3619,7 @@ exit: (1==map, 0 == leave in projective) return MP_OKAY on success */ -int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point* G, ecc_point* R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap) #if !defined(WOLFSSL_SP_MATH) @@ -3529,9 +3633,6 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, ecc_key key; #endif mp_digit mp; -#ifdef ECC_TIMING_RESISTANT - mp_int t; -#endif if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; @@ -3592,37 +3693,12 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, goto exit; } -#ifdef ECC_TIMING_RESISTANT - if ((err = mp_init(&t)) != MP_OKAY) - goto exit; - - if (err == MP_OKAY) - err = ecc_mulmod(k, tG, R, M, a, modulus, mp, rng); - - /* Check for k == order - 1. Result will be 0 point which is not correct - * Calculates order / 2 and adds order / 2 + 1 and gets infinity. - * (with constant time implementation) - */ - if (err == MP_OKAY) - err = mp_sub_d(order, 1, &t); - if (err == MP_OKAY) { - int kIsMinusOne = (mp_cmp((mp_int*)k, &t) == MP_EQ); - err = mp_cond_copy(tG->x, kIsMinusOne, R->x); - if (err == MP_OKAY) { - err = mp_sub(modulus, tG->y, &t); - } - if (err == MP_OKAY) { - err = mp_cond_copy(&t, kIsMinusOne, R->y); - } - if (err == MP_OKAY) { - err = mp_cond_copy(tG->z, kIsMinusOne, R->z); - } - } - - mp_free(&t); -#else err = ecc_mulmod(k, tG, R, M, a, modulus, mp, rng); - +#ifdef ECC_TIMING_RESISTANT + if (err == MP_OKAY) { + err = ecc_check_order_minus_1(k, tG, R, modulus, order); + } +#else (void)order; #endif /* map R back from projective space */ @@ -4954,7 +5030,7 @@ static WC_INLINE void wc_ecc_reset(ecc_key* key) /* create the public ECC key from a private key * * key an initialized private key to generate public part from - * curveIn [in]curve for key, can be NULL + * curve [in]curve for key, cannot be NULL * pubOut [out]ecc_point holding the public key, if NULL then public key part * is cached in key instead. * @@ -4966,13 +5042,12 @@ static WC_INLINE void wc_ecc_reset(ecc_key* key) * * returns MP_OKAY on success */ -static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, +static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, ecc_point* pubOut, WC_RNG* rng) { int err = MP_OKAY; #ifdef HAVE_ECC_MAKE_PUB ecc_point* pub; - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); #endif /* HAVE_ECC_MAKE_PUB */ (void)rng; @@ -4995,20 +5070,6 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, key->type = ECC_PRIVATEKEY_ONLY; } - /* avoid loading the curve unless it is not passed in */ - if (curveIn != NULL) { - curve = curveIn; - } - else { - /* load curve info */ - if (err == MP_OKAY) { - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); - } - if (err == MP_OKAY) { - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); - } - } - if ((err == MP_OKAY) && (mp_iszero(&key->k) || mp_isneg(&key->k) || (mp_cmp(&key->k, curve->order) != MP_LT))) { @@ -5125,15 +5186,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, #endif } - /* free up local curve */ - if (curveIn == NULL) { - wc_ecc_curve_free(curve); - FREE_CURVE_SPECS(); - } - #else /* Using hardware crypto, that does not support ecc_make_pub_ex */ - (void)curveIn; + (void)curve; err = NOT_COMPILED_IN; #endif /* HAVE_ECC_MAKE_PUB */ @@ -5161,7 +5216,7 @@ int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut) { WOLFSSL_ENTER("wc_ecc_make_pub"); - return ecc_make_pub_ex(key, NULL, pubOut, NULL); + return wc_ecc_make_pub_ex(key, pubOut, NULL); } /* create the public ECC key from a private key - mask timing use random z @@ -5175,9 +5230,28 @@ int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut) */ int wc_ecc_make_pub_ex(ecc_key* key, ecc_point* pubOut, WC_RNG* rng) { + int err = MP_OKAY; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + WOLFSSL_ENTER("wc_ecc_make_pub_ex"); - return ecc_make_pub_ex(key, NULL, pubOut, rng); + if (key == NULL) { + return BAD_FUNC_ARG; + } + + /* load curve info */ + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + if (err == MP_OKAY) { + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + } + if (err == MP_OKAY) { + err = ecc_make_pub_ex(key, curve, pubOut, rng); + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; } @@ -5185,9 +5259,6 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, int flags) { int err = 0; -#if defined(HAVE_ECC_MAKE_PUB) && !defined(WOLFSSL_SP_MATH) - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); -#endif #if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) const CRYS_ECPKI_Domain_t* pDomain; @@ -5449,28 +5520,28 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, #endif /* WOLFSSL_SP_384 */ #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { -#ifndef WC_ECC_NONBLOCK - err = sp_ecc_make_key_521(rng, &key->k, &key->pubkey, key->heap); -#else - if (key->nb_ctx) { - err = sp_ecc_make_key_521_nb(&key->nb_ctx->sp_ctx, rng, &key->k, - &key->pubkey, key->heap); - } - else { - #ifdef WC_ECC_NONBLOCK_ONLY - do { /* perform blocking call to non-blocking function */ - err = sp_ecc_make_key_521_nb(&nb_ctx.sp_ctx, rng, &key->k, - &key->pubkey, key->heap); - } while (err == FP_WOULDBLOCK); - #else + #ifndef WC_ECC_NONBLOCK err = sp_ecc_make_key_521(rng, &key->k, &key->pubkey, key->heap); - #endif /* WC_ECC_NONBLOCK_ONLY */ - } -#endif /* !WC_ECC_NONBLOCK */ + #else + if (key->nb_ctx) { + err = sp_ecc_make_key_521_nb(&key->nb_ctx->sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_make_key_521_nb(&nb_ctx.sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_make_key_521(rng, &key->k, &key->pubkey, key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ - if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - } + if (err == MP_OKAY) { + key->type = ECC_PRIVATEKEY; + } } else #endif /* WOLFSSL_SP_521 */ @@ -5480,6 +5551,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, #if defined(WOLFSSL_SP_MATH) err = WC_KEY_SIZE_E; #else + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); /* setup the key variables */ err = mp_init(&key->k); @@ -6193,13 +6265,9 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, ecc_key* key) { int err; - #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC) -#ifdef WOLFSSL_SMALL_STACK - mp_int *r = NULL, *s = NULL; -#else - mp_int r[1], s[1]; -#endif + DECL_MP_INT_SIZE_DYN(r, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(s, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); #endif if (in == NULL || out == NULL || outlen == NULL || key == NULL) { @@ -6233,24 +6301,29 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key); #else -#ifdef WOLFSSL_SMALL_STACK - r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(r, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (r == NULL) return MEMORY_E; - s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); +#endif + NEW_MP_INT_SIZE(s, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (s == NULL) { - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); return MEMORY_E; } #endif - XMEMSET(r, 0, sizeof(mp_int)); - XMEMSET(s, 0, sizeof(mp_int)); - if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ - #ifdef WOLFSSL_SMALL_STACK - XFREE(s, key->heap, DYNAMIC_TYPE_ECC); - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); - #endif + err = INIT_MP_INT_SIZE(r, ECC_KEY_MAX_BITS(key)); + if (err != 0) { + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); + return err; + } + err = INIT_MP_INT_SIZE(s, ECC_KEY_MAX_BITS(key)); + if (err != 0) { + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); return err; } @@ -6266,10 +6339,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, if (err < 0) { mp_clear(r); mp_clear(s); - #ifdef WOLFSSL_SMALL_STACK - XFREE(s, key->heap, DYNAMIC_TYPE_ECC); - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); - #endif + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); return err; } @@ -6280,10 +6351,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, mp_clear(r); mp_clear(s); -#ifdef WOLFSSL_SMALL_STACK - XFREE(s, key->heap, DYNAMIC_TYPE_ECC); - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); -#endif + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); #endif /* WOLFSSL_ASYNC_CRYPT */ #else (void)rng; @@ -6376,20 +6445,16 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, { int err = MP_OKAY; int loop_check = 0; -#ifdef WOLFSSL_SMALL_STACK - mp_int* b = NULL; -#else - mp_int b[1]; -#endif + DECL_MP_INT_SIZE_DYN(b, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); -#ifdef WOLFSSL_SMALL_STACK - b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(b, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (b == NULL) err = MEMORY_E; #endif if (err == MP_OKAY) { - err = mp_init(b); + err = INIT_MP_INT_SIZE(b, ECC_KEY_MAX_BITS(key)); } #ifdef WOLFSSL_CUSTOM_CURVES @@ -6540,9 +6605,8 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, mp_forcezero(&pubkey->k); } mp_forcezero(b); -#ifdef WOLFSSL_SMALL_STACK - XFREE(b, key->heap, DYNAMIC_TYPE_ECC); -#elif defined(WOLFSSL_CHECK_MEM_ZERO) + FREE_MP_INT_SIZE(b, key->heap, DYNAMIC_TYPE_ECC); +#if !defined(WOLFSSL_SMALL_STACK) && defined(WOLFSSL_CHECK_MEM_ZERO) mp_memzero_check(b); #endif @@ -6550,96 +6614,10 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, } #endif -/** - Sign a message digest - in The message digest to sign - inlen The length of the digest - key A private ECC key - r [out] The destination for r component of the signature - s [out] The destination for s component of the signature - return MP_OKAY if successful -*/ -int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, - ecc_key* key, mp_int *r, mp_int *s) +#ifdef WOLFSSL_HAVE_SP_ECC +static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s) { - int err = 0; -#if !defined(WOLFSSL_SP_MATH) - mp_int* e; -#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \ - !defined(WOLFSSL_SMALL_STACK) - mp_int e_lcl; -#endif - -#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ - defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ - defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) || \ - (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ - (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA))) - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); -#else - DECLARE_CURVE_SPECS(1); -#endif -#endif /* !WOLFSSL_SP_MATH */ - - if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) { - return ECC_BAD_ARG_E; - } - - /* is this a private key? */ - if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) { - return ECC_BAD_ARG_E; - } - - /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { - return ECC_BAD_ARG_E; - } - -#if defined(WOLFSSL_SP_MATH) - if (key->idx == ECC_CUSTOM_IDX || (1 - #ifndef WOLFSSL_SP_NO_256 - && ecc_sets[key->idx].id != ECC_SECP256R1 - #endif - #ifdef WOLFSSL_SP_384 - && ecc_sets[key->idx].id != ECC_SECP384R1 - #endif - #ifdef WOLFSSL_SP_521 - && ecc_sets[key->idx].id != ECC_SECP521R1 - #endif - )) { - return WC_KEY_SIZE_E; - } -#endif - -#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ - defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) - /* generate deterministic 'k' value to be used either with SP or normal */ - if (key->deterministic == 1) { - if (deterministic_sign_helper(in, inlen, key)) { - WOLFSSL_MSG("Error generating deterministic k to sign"); - return ECC_PRIV_KEY_E; - } - } -#endif - - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ - defined(WOLFSSL_ASYNC_CRYPT_SW) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_ECC_SIGN)) { - WC_ASYNC_SW* sw = &key->asyncDev.sw; - sw->eccSign.in = in; - sw->eccSign.inSz = inlen; - sw->eccSign.rng = rng; - sw->eccSign.key = key; - sw->eccSign.r = r; - sw->eccSign.s = s; - return WC_PENDING_E; - } - } -#endif - -#if defined(WOLFSSL_HAVE_SP_ECC) if (key->idx != ECC_CUSTOM_IDX) { #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) \ || defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ @@ -6736,6 +6714,105 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #endif (void)sign_k; } + + /* SP doesn't support curve. */ + return WC_KEY_SIZE_E; +} +#endif + +/** + Sign a message digest + in The message digest to sign + inlen The length of the digest + key A private ECC key + r [out] The destination for r component of the signature + s [out] The destination for s component of the signature + return MP_OKAY if successful +*/ +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 = 0; +#if !defined(WOLFSSL_SP_MATH) + mp_int* e; +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + DECL_MP_INT_SIZE_DYN(e_lcl, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); +#endif + +#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA))) + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); +#else + DECLARE_CURVE_SPECS(1); +#endif +#endif /* !WOLFSSL_SP_MATH */ + + if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) { + return ECC_BAD_ARG_E; + } + + /* is this a private key? */ + if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) { + return ECC_BAD_ARG_E; + } + + /* is the IDX valid ? */ + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { + return ECC_BAD_ARG_E; + } + +#if defined(WOLFSSL_SP_MATH) + if (key->idx == ECC_CUSTOM_IDX || (1 + #ifndef WOLFSSL_SP_NO_256 + && ecc_sets[key->idx].id != ECC_SECP256R1 + #endif + #ifdef WOLFSSL_SP_384 + && ecc_sets[key->idx].id != ECC_SECP384R1 + #endif + #ifdef WOLFSSL_SP_521 + && ecc_sets[key->idx].id != ECC_SECP521R1 + #endif + )) { + return WC_KEY_SIZE_E; + } +#endif + +#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) + /* generate deterministic 'k' value to be used either with SP or normal */ + if (key->deterministic == 1) { + if (deterministic_sign_helper(in, inlen, key)) { + WOLFSSL_MSG("Error generating deterministic k to sign"); + return ECC_PRIV_KEY_E; + } + } +#endif + + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_SW) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_ECC_SIGN)) { + WC_ASYNC_SW* sw = &key->asyncDev.sw; + sw->eccSign.in = in; + sw->eccSign.inSz = inlen; + sw->eccSign.rng = rng; + sw->eccSign.key = key; + sw->eccSign.r = r; + sw->eccSign.s = s; + return WC_PENDING_E; + } + } +#endif + +#if defined(WOLFSSL_HAVE_SP_ECC) + err = ecc_sign_hash_sp(in, inlen, rng, key, r, s); + if (err != WC_KEY_SIZE_E) { + return err; + } #else (void)inlen; #endif @@ -6748,21 +6825,20 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return err; } e = key->e; -#elif !defined(WOLFSSL_SMALL_STACK) - e = &e_lcl; #else - e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (e == NULL) { + NEW_MP_INT_SIZE(e_lcl, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (e_lcl == NULL) { return MEMORY_E; } #endif + e = e_lcl; +#endif /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ - if ((err = mp_init(e)) != MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(e, key->heap, DYNAMIC_TYPE_ECC); - #endif + if ((err = INIT_MP_INT_SIZE(e, ECC_KEY_MAX_BITS(key))) != MP_OKAY) { + FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); return err; } @@ -6806,6 +6882,80 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } /* make up a key and export the public copy */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if ((err == MP_OKAY) && (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC)) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + word32 keySz = key->dp->size; + mp_int* k; + #ifdef HAVE_CAVIUM_V + err = wc_ecc_alloc_mpint(key, &key->signK); + if (err != 0) + return err; + k = key->signK; + #else + mp_int k_lcl; + k = &k_lcl; + #endif + + err = mp_init(k); + + /* make sure r and s are allocated */ + #ifdef HAVE_CAVIUM_V + /* Nitrox V needs single buffer for R and S */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2); + /* Nitrox V only needs Prime and Order */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER)); + #else + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + #endif + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->s->raw, key->dp->size); + + /* load e and k */ + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz); + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(k, &k->raw, keySz); + + #ifdef HAVE_CAVIUM_V + if (err == MP_OKAY) + err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw, + &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); + #else + if (err == MP_OKAY) + err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw, + &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, + &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, + &curve->Gy->raw); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + mp_clear(k); + #endif + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; + } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + if (err == MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK ecc_key* pubkey; @@ -6813,80 +6963,6 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key pubkey[1]; #endif - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) - #ifdef HAVE_CAVIUM_V - if (NitroxEccIsCurveSupported(key)) - #endif - { - word32 keySz = key->dp->size; - mp_int* k; - #ifdef HAVE_CAVIUM_V - err = wc_ecc_alloc_mpint(key, &key->signK); - if (err != 0) - return err; - k = key->signK; - #else - mp_int k_lcl; - k = &k_lcl; - #endif - - err = mp_init(k); - - /* make sure r and s are allocated */ - #ifdef HAVE_CAVIUM_V - /* Nitrox V needs single buffer for R and S */ - if (err == MP_OKAY) - err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2); - /* Nitrox V only needs Prime and Order */ - if (err == MP_OKAY) - err = wc_ecc_curve_load(key->dp, &curve, - (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER)); - #else - if (err == MP_OKAY) - err = wc_bigint_alloc(&key->r->raw, key->dp->size); - if (err == MP_OKAY) - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); - #endif - if (err == MP_OKAY) - err = wc_bigint_alloc(&key->s->raw, key->dp->size); - - /* load e and k */ - if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(e, &e->raw, keySz); - if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz); - if (err == MP_OKAY) - err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order); - if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(k, &k->raw, keySz); - - #ifdef HAVE_CAVIUM_V - if (err == MP_OKAY) - err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw, - &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); - #else - if (err == MP_OKAY) - err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw, - &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, - &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, - &curve->Gy->raw); - #endif - - #ifndef HAVE_CAVIUM_V - mp_clear(e); - mp_clear(k); - #endif - wc_ecc_curve_free(curve); - FREE_CURVE_SPECS(); - - return err; - } - #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ - } - #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ - #ifdef WOLFSSL_SMALL_STACK pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC); if (pubkey == NULL) @@ -6908,9 +6984,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, mp_clear(e); wc_ecc_curve_free(curve); -#ifdef WOLFSSL_SMALL_STACK - XFREE(e, key->heap, DYNAMIC_TYPE_ECC); -#endif + FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); FREE_CURVE_SPECS(); #endif /* !WOLFSSL_SP_MATH */ @@ -7495,6 +7569,51 @@ int ecc_projective_dbl_point_safe(ecc_point *P, ecc_point *R, mp_int* a, !defined(WOLFSSL_KCAPI_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) #ifdef ECC_SHAMIR +static int ecc_mont_norm_points(ecc_point* A, ecc_point* Am, ecc_point* B, + ecc_point* Bm, mp_int* modulus, void* heap) +{ + int err = MP_OKAY; + DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE); + + (void)heap; + + NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (mu == NULL) + err = MEMORY_E; +#endif + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(mu, mp_bitsused(modulus)); + } + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(mu, modulus); + + if (err == MP_OKAY) { + /* copy ones ... */ + err = mp_mulmod(A->x, mu, modulus, Am->x); + } + + if (err == MP_OKAY) + err = mp_mulmod(A->y, mu, modulus, Am->y); + if (err == MP_OKAY) + err = mp_mulmod(A->z, mu, modulus, Am->z); + + if (err == MP_OKAY) + err = mp_mulmod(B->x, mu, modulus, Bm->x); + if (err == MP_OKAY) + err = mp_mulmod(B->y, mu, modulus, Bm->y); + if (err == MP_OKAY) + err = mp_mulmod(B->z, mu, modulus, Bm->z); + + /* done with mu */ + mp_clear(mu); + } + + FREE_MP_INT_SIZE(mu, heap, DYNAMIC_TYPE_ECC); + + return err; +} + /** Computes kA*A + kB*B = C using Shamir's Trick A First point to multiply kA What to multiple A by @@ -7660,45 +7779,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = mp_montgomery_setup(modulus, &mp); if (err == MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - mp_int* mu; - #else - mp_int mu[1]; - #endif - #ifdef WOLFSSL_SMALL_STACK - mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); - if (mu == NULL) - err = MEMORY_E; - else - #endif - err = mp_init(mu); - if (err == MP_OKAY) { - err = mp_montgomery_calc_normalization(mu, modulus); - - if (err == MP_OKAY) - /* copy ones ... */ - err = mp_mulmod(A->x, mu, modulus, precomp[1]->x); - - if (err == MP_OKAY) - err = mp_mulmod(A->y, mu, modulus, precomp[1]->y); - if (err == MP_OKAY) - err = mp_mulmod(A->z, mu, modulus, precomp[1]->z); - - if (err == MP_OKAY) - err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x); - if (err == MP_OKAY) - err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y); - if (err == MP_OKAY) - err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z); - - /* done with mu */ - mp_clear(mu); - } - #ifdef WOLFSSL_SMALL_STACK - if (mu != NULL) { - XFREE(mu, heap, DYNAMIC_TYPE_ECC); - } - #endif + err = ecc_mont_norm_points(A, precomp[1], B, precomp[1<<2], modulus, heap); } if (err == MP_OKAY) { @@ -7870,10 +7951,11 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, { int err; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) mp_int *r = NULL, *s = NULL; -#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)) && \ - !defined(WOLFSSL_SMALL_STACK) - mp_int r_lcl, s_lcl; +#else + DECL_MP_INT_SIZE_DYN(r, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(s, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); #endif #ifdef WOLFSSL_ASYNC_CRYPT int isPrivateKeyOnly = 0; @@ -7908,21 +7990,30 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, r = key->r; s = key->s; #else - #ifndef WOLFSSL_SMALL_STACK - r = &r_lcl; - s = &s_lcl; - #else - r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + NEW_MP_INT_SIZE(r, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (r == NULL) return MEMORY_E; - s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); +#endif + NEW_MP_INT_SIZE(s, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL if (s == NULL) { - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); return MEMORY_E; } - #endif - XMEMSET(r, 0, sizeof(mp_int)); - XMEMSET(s, 0, sizeof(mp_int)); +#endif + err = INIT_MP_INT_SIZE(r, ECC_KEY_MAX_BITS(key)); + if (err != 0) { + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); + return err; + } + err = INIT_MP_INT_SIZE(s, ECC_KEY_MAX_BITS(key)); + if (err != 0) { + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); + return err; + } #endif /* WOLFSSL_ASYNC_CRYPT */ switch (key->state) { @@ -7957,9 +8048,9 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, /* done with R/S */ mp_clear(r); mp_clear(s); - #ifdef WOLFSSL_SMALL_STACK - XFREE(s, key->heap, DYNAMIC_TYPE_ECC); - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); + #ifdef MP_INT_SIZE_CHECK_NULL r = NULL; s = NULL; #endif @@ -7991,11 +8082,9 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, /* cleanup */ #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) wc_ecc_free_async(key); -#elif defined(WOLFSSL_SMALL_STACK) - XFREE(s, key->heap, DYNAMIC_TYPE_ECC); - XFREE(r, key->heap, DYNAMIC_TYPE_ECC); - r = NULL; - s = NULL; +#else + FREE_MP_INT_SIZE(s, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(r, key->heap, DYNAMIC_TYPE_ECC); #endif /* make sure required variables are reset */ @@ -8003,10 +8092,6 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, #else (void)siglen; (void)hashlen; - #ifndef WOLFSSL_SMALL_STACK - (void)s_lcl; - (void)r_lcl; - #endif (void)s; (void)r; (void)err; @@ -8048,6 +8133,387 @@ static int wc_ecc_check_r_s_range(ecc_key* key, mp_int* r, mp_int* s) } #endif /* !WOLFSSL_STM32_PKA && !WOLFSSL_PSOC6_CRYPTO */ +#ifndef WOLF_CRYPTO_CB_ONLY_ECC +static int ecc_verify_hash_sp(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + (void)r; + (void)s; + (void)hash; + (void)hashlen; + (void)res; + (void)key; + +#if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC) + if (key->handle != -1) { + return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + } + if (wolfSSL_GetHandleCbSet() == 1) { + return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + } +#endif + +#if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) + if (key->idx == ECC_CUSTOM_IDX || (1 + #ifndef WOLFSSL_SP_NO_256 + && ecc_sets[key->idx].id != ECC_SECP256R1 + #endif + #ifdef WOLFSSL_SP_384 + && ecc_sets[key->idx].id != ECC_SECP384R1 + #endif + #ifdef WOLFSSL_SP_521 + && ecc_sets[key->idx].id != ECC_SECP521R1 + #endif + )) { + return WC_KEY_SIZE_E; + } +#endif + +#if defined(WOLFSSL_HAVE_SP_ECC) + if (key->idx != ECC_CUSTOM_IDX) { + #if defined(WC_ECC_NONBLOCK) && defined(WC_ECC_NONBLOCK_ONLY) + /* perform blocking call to non-blocking function */ + ecc_nb_ctx_t nb_ctx; + XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); + err = NOT_COMPILED_IN; /* set default error */ + #endif + #ifndef WOLFSSL_SP_NO_256 + if (ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_verify_256_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + { + int ret; + SAVE_VECTOR_REGISTERS(return _svr_ret;); + ret = sp_ecc_verify_256(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + RESTORE_VECTOR_REGISTERS(); + return ret; + } + #endif + } + #endif + #ifdef WOLFSSL_SP_384 + if (ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_verify_384_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + { + int ret; + SAVE_VECTOR_REGISTERS(return _svr_ret;); + ret = sp_ecc_verify_384(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + RESTORE_VECTOR_REGISTERS(); + return ret; + } + #endif + } + #endif + #ifdef WOLFSSL_SP_521 + if (ecc_sets[key->idx].id == ECC_SECP521R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_521_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_verify_521_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + { + int ret; + SAVE_VECTOR_REGISTERS(return _svr_ret;); + ret = sp_ecc_verify_521(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + RESTORE_VECTOR_REGISTERS(); + return ret; + } + #endif + } + #endif + } +#endif + + return 0; +} + +#if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) +static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key, ecc_curve_spec* curve) +{ + int err; + ecc_point* mG = NULL; + ecc_point* mQ = NULL; +#ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_mG; + ecc_point lcl_mQ; +#endif + DECL_MP_INT_SIZE_DYN(v, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); + DECL_MP_INT_SIZE_DYN(w, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + DECL_MP_INT_SIZE_DYN(e_lcl, ECC_KEY_MAX_BITS(key), MAX_ECC_BITS_USE); +#endif + mp_int* e; + mp_int* u1 = NULL; /* Will be e. */ + mp_int* u2 = NULL; /* Will be w. */ + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) + err = wc_ecc_alloc_mpint(key, &key->e); + if (err != 0) { + return err; + } + e = key->e; + + err = mp_init(e); +#else + NEW_MP_INT_SIZE(e_lcl, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (e_lcl == NULL) { + return MEMORY_E; + } +#endif + e = e_lcl; + + err = INIT_MP_INT_SIZE(e, ECC_KEY_MAX_BITS(key)); +#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM_V */ + if (err != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); + #endif +#endif + return MEMORY_E; + } + + /* read hash */ + if (err == MP_OKAY) { + /* we may need to truncate if hash is longer than key size */ + unsigned int orderBits = mp_count_bits(curve->order); + + /* truncate down to byte size, may be all that's needed */ + if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) + hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + err = mp_read_unsigned_bin(e, hash, hashlen); + + /* may still need bit truncation too */ + if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits) + mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); + } + + /* check for async hardware acceleration */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (err == MP_OKAY && key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + err = wc_mp_to_bigint_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz); + if (err == MP_OKAY) + #ifdef HAVE_CAVIUM_V + err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, + &curve->prime->raw, &curve->order->raw, res); + #else + err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, + &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, + &curve->Gx->raw, &curve->Gy->raw, res); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + #endif + + return err; + } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + NEW_MP_INT_SIZE(v, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (v == NULL) { + err = MEMORY_E; + } +#endif + NEW_MP_INT_SIZE(w, ECC_KEY_MAX_BITS(key), key->heap, DYNAMIC_TYPE_ECC); +#ifdef MP_INT_SIZE_CHECK_NULL + if (w == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u1 = e; + u2 = w; + + err = INIT_MP_INT_SIZE(v, ECC_KEY_MAX_BITS(key)); + } + if (err == MP_OKAY) { + err = INIT_MP_INT_SIZE(w, ECC_KEY_MAX_BITS(key)); + } + + /* allocate points */ + if (err == MP_OKAY) { + #ifdef WOLFSSL_NO_MALLOC + mG = &lcl_mG; + #endif + err = wc_ecc_new_point_ex(&mG, key->heap); + } + if (err == MP_OKAY) { + #ifdef WOLFSSL_NO_MALLOC + mQ = &lcl_mQ; + #endif + err = wc_ecc_new_point_ex(&mQ, key->heap); + } + + /* w = s^-1 mod n */ + if (err == MP_OKAY) + err = mp_invmod(s, curve->order, w); + + /* u1 = ew */ + if (err == MP_OKAY) + err = mp_mulmod(e, w, curve->order, u1); + + /* u2 = rw */ + if (err == MP_OKAY) + err = mp_mulmod(r, w, curve->order, u2); + + /* find mG and mQ */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, mG->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, mG->y); + if (err == MP_OKAY) + err = mp_set(mG->z, 1); + + if (err == MP_OKAY) + err = mp_copy(key->pubkey.x, mQ->x); + if (err == MP_OKAY) + err = mp_copy(key->pubkey.y, mQ->y); + if (err == MP_OKAY) + err = mp_copy(key->pubkey.z, mQ->z); + +#if defined(FREESCALE_LTC_ECC) + /* use PKHA to compute u1*mG + u2*mQ */ + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap); + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); + if (err == MP_OKAY) + err = wc_ecc_point_add(mG, mQ, mG, curve->prime); +#else +#ifndef ECC_SHAMIR + if (err == MP_OKAY) + { + mp_digit mp = 0; + + if (!mp_iszero((MP_INT_SIZE*)u1)) { + /* compute u1*mG + u2*mQ = mG */ + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, + key->heap); + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, + key->heap); + } + + /* find the montgomery mp */ + if (err == MP_OKAY) + err = mp_montgomery_setup(curve->prime, &mp); + + /* add them */ + if (err == MP_OKAY) + err = ecc_projective_add_point_safe(mQ, mG, mG, curve->Af, + curve->prime, mp, NULL); + } + else { + /* compute 0*mG + u2*mQ = mG */ + err = wc_ecc_mulmod_ex(u2, mQ, mG, curve->Af, curve->prime, 0, + key->heap); + /* find the montgomery mp */ + if (err == MP_OKAY) + err = mp_montgomery_setup(curve->prime, &mp); + } + + /* reduce */ + if (err == MP_OKAY) + err = ecc_map(mG, curve->prime, mp); + } +#else + /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ + if (err == MP_OKAY) { + err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime, + key->heap); + } +#endif /* ECC_SHAMIR */ +#endif /* FREESCALE_LTC_ECC */ + /* v = X_x1 mod n */ + if (err == MP_OKAY) + err = mp_mod(mG->x, curve->order, v); + + /* does v == r */ + if (err == MP_OKAY) { + if (mp_cmp(v, r) == MP_EQ) + *res = 1; + } + + /* cleanup */ + wc_ecc_del_point_ex(mG, key->heap); + wc_ecc_del_point_ex(mQ, key->heap); + + mp_clear(e); + mp_clear(v); + mp_clear(w); + FREE_MP_INT_SIZE(w, key->heap, DYNAMIC_TYPE_ECC); + FREE_MP_INT_SIZE(v, key->heap, DYNAMIC_TYPE_ECC); +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + FREE_MP_INT_SIZE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif /* !WOLFSSL_SP_MATH || FREESCALE_LTC_ECC */ + /** Verify an ECC signature r The signature R component to verify @@ -8060,19 +8526,14 @@ static int wc_ecc_check_r_s_range(ecc_key* key, mp_int* r, mp_int* s) Caller should check the *res value to determine if the signature is valid or invalid. Other negative values are returned on error. */ -#ifndef WOLF_CRYPTO_CB_ONLY_ECC int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, word32 hashlen, int* res, ecc_key* key) +{ #if defined(WOLFSSL_STM32_PKA) -{ return stm32_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); -} #elif defined(WOLFSSL_PSOC6_CRYPTO) -{ return psoc6_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); -} #else -{ int err; word32 keySz = 0; #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) @@ -8089,31 +8550,8 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #elif defined(WOLFSSL_XILINX_CRYPT_VERSAL) byte sigRS[ECC_MAX_CRYPTO_HW_SIZE * 2]; byte hashcopy[ECC_MAX_CRYPTO_HW_SIZE] = {0}; -#elif (!defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC)) && \ - !defined(WOLFSSL_SE050) - int did_init = 0; - ecc_point *mG = NULL, *mQ = NULL; - #ifdef WOLFSSL_NO_MALLOC - ecc_point lcl_mG, lcl_mQ; - #endif - #ifdef WOLFSSL_SMALL_STACK - mp_int* v = NULL; - mp_int* w = NULL; - mp_int* u1 = NULL; - mp_int* u2 = NULL; - #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) - mp_int* e_lcl = NULL; - #endif - #else /* WOLFSSL_SMALL_STACK */ - mp_int v[1]; - mp_int w[1]; - mp_int u1[1]; - mp_int u2[1]; - #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) - mp_int e_lcl[1]; - #endif - #endif /* WOLFSSL_SMALL_STACK */ - mp_int* e; +#else + int curveLoaded = 0; DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); #endif @@ -8252,392 +8690,62 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* checking if private key with no public part */ if (key->type == ECC_PRIVATEKEY_ONLY) { WOLFSSL_MSG("Verify called with private key, generating public part"); - err = ecc_make_pub_ex(key, NULL, NULL, NULL); + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); if (err != MP_OKAY) { - WOLFSSL_MSG("Unable to extract public key"); - return err; - } - } - -#if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC) - if (key->handle != -1) { - return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z, r, s, res, key->heap); - } - if (wolfSSL_GetHandleCbSet() == 1) { - return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z, r, s, res, key->heap); - } -#endif - -#if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) - if (key->idx == ECC_CUSTOM_IDX || (1 - #ifndef WOLFSSL_SP_NO_256 - && ecc_sets[key->idx].id != ECC_SECP256R1 - #endif - #ifdef WOLFSSL_SP_384 - && ecc_sets[key->idx].id != ECC_SECP384R1 - #endif - #ifdef WOLFSSL_SP_521 - && ecc_sets[key->idx].id != ECC_SECP521R1 - #endif - )) { - return WC_KEY_SIZE_E; - } -#endif - -#if defined(WOLFSSL_HAVE_SP_ECC) - if (key->idx != ECC_CUSTOM_IDX) { - #if defined(WC_ECC_NONBLOCK) && defined(WC_ECC_NONBLOCK_ONLY) - /* perform blocking call to non-blocking function */ - ecc_nb_ctx_t nb_ctx; - XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); - err = NOT_COMPILED_IN; /* set default error */ - #endif - #ifndef WOLFSSL_SP_NO_256 - if (ecc_sets[key->idx].id == ECC_SECP256R1) { - #ifdef WC_ECC_NONBLOCK - if (key->nb_ctx) { - return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } - #ifdef WC_ECC_NONBLOCK_ONLY - do { /* perform blocking call to non-blocking function */ - err = sp_ecc_verify_256_nb(&nb_ctx.sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } while (err == FP_WOULDBLOCK); - return err; - #endif - #endif /* WC_ECC_NONBLOCK */ - #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - { - int ret; - SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_verify_256(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z, r, s, res, key->heap); - RESTORE_VECTOR_REGISTERS(); - return ret; - } - #endif - } - #endif - #ifdef WOLFSSL_SP_384 - if (ecc_sets[key->idx].id == ECC_SECP384R1) { - #ifdef WC_ECC_NONBLOCK - if (key->nb_ctx) { - return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } - #ifdef WC_ECC_NONBLOCK_ONLY - do { /* perform blocking call to non-blocking function */ - err = sp_ecc_verify_384_nb(&nb_ctx.sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } while (err == FP_WOULDBLOCK); - return err; - #endif - #endif /* WC_ECC_NONBLOCK */ - #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - { - int ret; - SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_verify_384(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z, r, s, res, key->heap); - RESTORE_VECTOR_REGISTERS(); - return ret; - } - #endif - } - #endif - #ifdef WOLFSSL_SP_521 - if (ecc_sets[key->idx].id == ECC_SECP521R1) { - #ifdef WC_ECC_NONBLOCK - if (key->nb_ctx) { - return sp_ecc_verify_521_nb(&key->nb_ctx->sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } - #ifdef WC_ECC_NONBLOCK_ONLY - do { /* perform blocking call to non-blocking function */ - err = sp_ecc_verify_521_nb(&nb_ctx.sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, - key->heap); - } while (err == FP_WOULDBLOCK); - return err; - #endif - #endif /* WC_ECC_NONBLOCK */ - #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - { - int ret; - SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_verify_521(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z, r, s, res, key->heap); - RESTORE_VECTOR_REGISTERS(); - return ret; - } - #endif - } - #endif - } -#endif - -#if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); - if (err != 0) { - return err; - } - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) - err = wc_ecc_alloc_mpint(key, &key->e); - if (err != 0) { - FREE_CURVE_SPECS(); - return err; - } - e = key->e; -#else -#ifdef WOLFSSL_SMALL_STACK - e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (e_lcl == NULL) { - FREE_CURVE_SPECS(); - return MEMORY_E; - } -#endif - e = e_lcl; -#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM_V */ - - err = mp_init(e); - if (err != MP_OKAY) { - FREE_CURVE_SPECS(); - return MEMORY_E; - } - - /* read in the specs for this curve */ - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); - - /* read hash */ - if (err == MP_OKAY) { - /* we may need to truncate if hash is longer than key size */ - unsigned int orderBits = mp_count_bits(curve->order); - - /* truncate down to byte size, may be all that's needed */ - if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; - err = mp_read_unsigned_bin(e, hash, hashlen); - - /* may still need bit truncation too */ - if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); - } - - /* check for async hardware acceleration */ -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (err == MP_OKAY && key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) - #ifdef HAVE_CAVIUM_V - if (NitroxEccIsCurveSupported(key)) - #endif - { - err = wc_mp_to_bigint_sz(e, &e->raw, keySz); - if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz); - if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz); - if (err == MP_OKAY) - #ifdef HAVE_CAVIUM_V - err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw, - &key->pubkey.y->raw, &r->raw, &s->raw, - &curve->prime->raw, &curve->order->raw, res); - #else - err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw, - &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, - &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, - &curve->Gx->raw, &curve->Gy->raw, res); - #endif - - #ifndef HAVE_CAVIUM_V - mp_clear(e); - #endif - wc_ecc_curve_free(curve); - FREE_CURVE_SPECS(); - return err; } - #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ - } -#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + if (err != MP_OKAY) { + FREE_CURVE_SPECS(); + return err; + } + err = ecc_make_pub_ex(key, curve, NULL, NULL); + if (err != MP_OKAY) { + WOLFSSL_MSG("Unable to extract public key"); + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + return err; + } + curveLoaded = 1; + } -#ifdef WOLFSSL_SMALL_STACK - if (err == MP_OKAY) { - v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (v == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (w == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); - if (u2 == NULL) - err = MEMORY_E; - } -#endif + err = ecc_verify_hash_sp(r, s, hash, hashlen, res, key); + if (err != 0) { + if (curveLoaded) { + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + } + return err; + } - /* allocate ints */ - if (err == MP_OKAY) { - if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) { - err = MEMORY_E; - } else { - did_init = 1; +#if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) + if (!curveLoaded) { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + if (err != 0) { + return err; + } + /* read in the specs for this curve */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; } } - /* allocate points */ - if (err == MP_OKAY) { - #ifdef WOLFSSL_NO_MALLOC - mG = &lcl_mG; - #endif - err = wc_ecc_new_point_ex(&mG, key->heap); - } - if (err == MP_OKAY) { - #ifdef WOLFSSL_NO_MALLOC - mQ = &lcl_mQ; - #endif - err = wc_ecc_new_point_ex(&mQ, key->heap); - } - - /* w = s^-1 mod n */ - if (err == MP_OKAY) - err = mp_invmod(s, curve->order, w); - - /* u1 = ew */ - if (err == MP_OKAY) - err = mp_mulmod(e, w, curve->order, u1); - - /* u2 = rw */ - if (err == MP_OKAY) - err = mp_mulmod(r, w, curve->order, u2); - - /* find mG and mQ */ - if (err == MP_OKAY) - err = mp_copy(curve->Gx, mG->x); - if (err == MP_OKAY) - err = mp_copy(curve->Gy, mG->y); - if (err == MP_OKAY) - err = mp_set(mG->z, 1); - - if (err == MP_OKAY) - err = mp_copy(key->pubkey.x, mQ->x); - if (err == MP_OKAY) - err = mp_copy(key->pubkey.y, mQ->y); - if (err == MP_OKAY) - err = mp_copy(key->pubkey.z, mQ->z); - -#if defined(FREESCALE_LTC_ECC) - /* use PKHA to compute u1*mG + u2*mQ */ - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap); - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); - if (err == MP_OKAY) - err = wc_ecc_point_add(mG, mQ, mG, curve->prime); -#else -#ifndef ECC_SHAMIR - if (err == MP_OKAY) - { - mp_digit mp = 0; - - if (!mp_iszero(u1)) { - /* compute u1*mG + u2*mQ = mG */ - err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, - key->heap); - if (err == MP_OKAY) { - err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, - key->heap); - } - - /* find the montgomery mp */ - if (err == MP_OKAY) - err = mp_montgomery_setup(curve->prime, &mp); - - /* add them */ - if (err == MP_OKAY) - err = ecc_projective_add_point_safe(mQ, mG, mG, curve->Af, - curve->prime, mp, NULL); - } - else { - /* compute 0*mG + u2*mQ = mG */ - err = wc_ecc_mulmod_ex(u2, mQ, mG, curve->Af, curve->prime, 0, - key->heap); - /* find the montgomery mp */ - if (err == MP_OKAY) - err = mp_montgomery_setup(curve->prime, &mp); - } - - /* reduce */ - if (err == MP_OKAY) - err = ecc_map(mG, curve->prime, mp); - } -#else - /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ - if (err == MP_OKAY) { - err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime, - key->heap); - } -#endif /* ECC_SHAMIR */ -#endif /* FREESCALE_LTC_ECC */ - /* v = X_x1 mod n */ - if (err == MP_OKAY) - err = mp_mod(mG->x, curve->order, v); - - /* does v == r */ - if (err == MP_OKAY) { - if (mp_cmp(v, r) == MP_EQ) - *res = 1; - } - - /* cleanup */ - wc_ecc_del_point_ex(mG, key->heap); - wc_ecc_del_point_ex(mQ, key->heap); - - mp_clear(e); - if (did_init) { - mp_clear(v); - mp_clear(w); - mp_clear(u1); - mp_clear(u2); - } -#ifdef WOLFSSL_SMALL_STACK - XFREE(u2, key->heap, DYNAMIC_TYPE_ECC); - XFREE(u1, key->heap, DYNAMIC_TYPE_ECC); - XFREE(w, key->heap, DYNAMIC_TYPE_ECC); - XFREE(v, key->heap, DYNAMIC_TYPE_ECC); -#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) - XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); -#endif -#endif + err = ecc_verify_hash(r, s, hash, hashlen, res, key, curve); +#endif /* !WOLFSSL_SP_MATH || FREESCALE_LTC_ECC */ + (void)curveLoaded; wc_ecc_curve_free(curve); FREE_CURVE_SPECS(); - -#endif /* !WOLFSSL_SP_MATH || FREESCALE_LTC_ECC */ #endif /* WOLFSSL_ATECC508A */ (void)keySz; (void)hashlen; return err; -} #endif /* WOLFSSL_STM32_PKA */ +} #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ #endif /* HAVE_ECC_VERIFY */ diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index c15f00040..eca9729cc 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -764,11 +764,10 @@ static int _ifc_pairwise_consistency_test(RsaKey* key, WC_RNG* rng) int wc_CheckRsaKey(RsaKey* key) { + DECL_MP_INT_SIZE_DYN(tmp, mp_bitsused(&key->n), RSA_MAX_SIZE); #ifdef WOLFSSL_SMALL_STACK - mp_int *tmp = NULL; WC_RNG *rng = NULL; #else - mp_int tmp[1]; WC_RNG rng[1]; #endif int ret = 0; @@ -782,11 +781,14 @@ int wc_CheckRsaKey(RsaKey* key) #ifdef WOLFSSL_SMALL_STACK rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (rng != NULL) - tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_RSA); - if (rng == NULL || tmp == NULL) { + if (rng == NULL) { + return MEMORY_E; + } +#endif + NEW_MP_INT_SIZE(tmp, mp_bitsused(&key->n), NULL, DYNAMIC_TYPE_RSA); +#ifdef MP_INT_SIZE_CHECK_NULL + if (tmp == NULL) { XFREE(rng, NULL, DYNAMIC_TYPE_RNG); - XFREE(tmp, NULL, DYNAMIC_TYPE_RSA); return MEMORY_E; } #endif @@ -797,7 +799,7 @@ int wc_CheckRsaKey(RsaKey* key) SAVE_VECTOR_REGISTERS(ret = _svr_ret;); if (ret == 0) { - if (mp_init(tmp) != MP_OKAY) + if (INIT_MP_INT_SIZE(tmp, mp_bitsused(&key->n)) != MP_OKAY) ret = MP_INIT_E; } @@ -916,8 +918,8 @@ int wc_CheckRsaKey(RsaKey* key) RESTORE_VECTOR_REGISTERS(); wc_FreeRng(rng); + FREE_MP_INT_SIZE(tmp, NULL, DYNAMIC_TYPE_RSA); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, NULL, DYNAMIC_TYPE_RSA); XFREE(rng, NULL, DYNAMIC_TYPE_RNG); #elif defined(WOLFSSL_CHECK_MEM_ZERO) mp_memzero_check(tmp); @@ -2471,35 +2473,12 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, } #else #ifndef WOLF_CRYPTO_CB_ONLY_RSA -static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, - word32* outLen, int type, RsaKey* key, WC_RNG* rng) -{ -#if !defined(WOLFSSL_SP_MATH) -#ifdef WOLFSSL_SMALL_STACK - mp_int* tmp; -#ifdef WC_RSA_BLINDING - mp_int* rnd; - mp_int* rndi; -#endif -#else - mp_int tmp[1]; -#ifdef WC_RSA_BLINDING - mp_int rnd[1], rndi[1]; -#endif -#endif - int ret = 0; -#endif - word32 keyLen = wc_RsaEncryptSize(key); - - if (inLen > keyLen) { - WOLFSSL_MSG("Expected that inLen be no longer RSA key length"); - return BAD_FUNC_ARG; - } - - if (mp_iseven(&key->n)) { - return MP_VAL; - } #ifdef WOLFSSL_HAVE_SP_RSA +static int RsaFunction_SP(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + (void)rng; + #ifndef WOLFSSL_SP_NO_2048 if (mp_count_bits(&key->n) == 2048) { switch(type) { @@ -2593,61 +2572,184 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, } } #endif -#endif /* WOLFSSL_HAVE_SP_RSA */ -#if defined(WOLFSSL_SP_MATH) - (void)rng; - #ifndef WOLFSSL_HAVE_SP_RSA - (void)in; - (void)inLen; - (void)out; - (void)outLen; - (void)type; - (void)key; - #error RSA SP option invalid (enable WOLFSSL_HAVE_SP_RSA or disable WOLFSSL_SP_MATH) - return NOT_COMPILED_IN; - #else - WOLFSSL_MSG("SP Key Size Error"); + /* SP not able to do operation. */ return WC_KEY_SIZE_E; - #endif -#else +} +#endif + +#if !defined(WOLFSSL_SP_MATH) +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +static int RsaFunctionPrivate(mp_int* tmp, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; +#if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + DECL_MP_INT_SIZE_DYN(rnd, mp_bitsused(&key->n), RSA_MAX_SIZE); + DECL_MP_INT_SIZE_DYN(rndi, mp_bitsused(&key->n), RSA_MAX_SIZE); +#endif /* WC_RSA_BLINDING && !WC_NO_RNG */ + (void)rng; -#ifdef WOLFSSL_SMALL_STACK - tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) - return MEMORY_E; -#ifdef WC_RSA_BLINDING -#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) - rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); - if (rnd == NULL) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); +#if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + NEW_MP_INT_SIZE(rnd, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA); + NEW_MP_INT_SIZE(rndi, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA); +#ifdef MP_INT_SIZE_CHECK_NULL + if ((rnd == NULL) || (rndi == NULL)) { + FREE_MP_INT_SIZE(rnd, key->heap, DYNAMIC_TYPE_RSA); + FREE_MP_INT_SIZE(rndi, key->heap, DYNAMIC_TYPE_RSA); return MEMORY_E; } - rndi = rnd + 1; -#else - rnd = NULL; - rndi = NULL; #endif -#endif /* WC_RSA_BLINDING */ -#endif /* WOLFSSL_SMALL_STACK */ - if (mp_init(tmp) != MP_OKAY) + if ((INIT_MP_INT_SIZE(rnd, mp_bitsused(&key->n)) != MP_OKAY) || + (INIT_MP_INT_SIZE(rndi, mp_bitsused(&key->n)) != MP_OKAY)) { ret = MP_INIT_E; + } -#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) -#ifdef WC_RSA_BLINDING if (ret == 0) { - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) { - mp_clear(tmp); - ret = MP_INIT_E; - } + /* blind */ + ret = mp_rand(rnd, get_digit_count(&key->n), rng); + } + if (ret == 0) { + /* rndi = 1/rnd mod n */ + if (mp_invmod(rnd, &key->n, rndi) != MP_OKAY) { + ret = MP_INVMOD_E; } } + if (ret == 0) { + #ifdef WOLFSSL_CHECK_MEM_ZERO + mp_memzero_add("RSA Private rnd", rnd); + mp_memzero_add("RSA Private rndi", rndi); + #endif + + /* rnd = rnd^e */ + #ifndef WOLFSSL_SP_MATH_ALL + if (mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + #else + if (mp_exptmod_nct(rnd, &key->e, &key->n, rnd) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + #endif + } + + if (ret == 0) { + /* tmp = tmp*rnd mod n */ + if (mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY) { + ret = MP_MULMOD_E; + } + } +#endif /* WC_RSA_BLINDING && !WC_NO_RNG */ + +#ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (ret == 0) { + if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } +#else + if (ret == 0) { + mp_int* tmpa = tmp; +#if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + mp_int* tmpb = rnd; +#else + DECL_MP_INT_SIZE_DYN(tmpb, mp_bitsused(&key->n), RSA_MAX_SIZE); #endif + +#if !defined(WC_RSA_BLINDING) || defined(WC_NO_RNG) + NEW_MP_INT_SIZE(tmpb, mp_bitsused(&key->n), key->heap, + DYNAMIC_TYPE_RSA); + #ifdef MP_INT_SIZE_CHECK_NULL + if (tmpb == NULL) { + ret = MEMORY_E; + } + #endif + if ((ret == 0) && INIT_MP_INT_SIZE(tmpb, mp_bitsused(&key->n)) != + MP_OKAY) { + ret = MP_INIT_E; + } #endif + #ifdef WOLFSSL_CHECK_MEM_ZERO + if (ret == 0) { + mp_memzero_add("RSA Sync tmpb", tmpb); + } + #endif + + /* tmpb = tmp^dQ mod q */ + if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q, tmpb) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmpa = tmp^dP mod p */ + if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p, tmpa) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = (tmp - tmpb) * qInv (mod p) */ + #if (defined(WOLFSSL_SP_MATH) || (defined(WOLFSSL_SP_MATH_ALL)) && \ + !defined(WOLFSSL_SP_INT_NEGATIVE)) + if (ret == 0 && mp_submod(tmpa, tmpb, &key->p, tmp) != MP_OKAY) + ret = MP_SUB_E; + #else + if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY) + ret = MP_SUB_E; + #endif + + if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + + /* tmp = tmpb + q * tmp */ + if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY) + ret = MP_MUL_E; + + if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY) + ret = MP_ADD_E; + +#if !defined(WC_RSA_BLINDING) || defined(WC_NO_RNG) + mp_forcezero(tmpb); + FREE_MP_INT_SIZE(tmpb, key->heap, DYNAMIC_TYPE_RSA); + #if !defined(MP_INT_SIZE_CHECK_NULL) && defined(WOLFSSL_CHECK_MEM_ZERO) + mp_memzero_check(tmpb); + #endif +#endif + } +#endif /* RSA_LOW_MEM */ + +#if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + /* unblind */ + if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + + mp_forcezero(rndi); + mp_forcezero(rnd); + FREE_MP_INT_SIZE(rndi, key->heap, DYNAMIC_TYPE_RSA); + FREE_MP_INT_SIZE(rnd, key->heap, DYNAMIC_TYPE_RSA); +#if !defined(MP_INT_SIZE_CHECK_NULL) && defined(WOLFSSL_CHECK_MEM_ZERO) + mp_memzero_check(rnd); + mp_memzero_check(rndi); +#endif +#endif /* WC_RSA_BLINDING && !WC_NO_RNG */ + return ret; +} +#endif + +static int RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + DECL_MP_INT_SIZE_DYN(tmp, mp_bitsused(&key->n), RSA_MAX_SIZE); + int ret = 0; + + (void)rng; + + NEW_MP_INT_SIZE(tmp, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA); +#ifdef MP_INT_SIZE_CHECK_NULL + if (tmp == NULL) + return MEMORY_E; +#endif + + if (INIT_MP_INT_SIZE(tmp, mp_bitsused(&key->n)) != MP_OKAY) + ret = MP_INIT_E; + #ifndef TEST_UNPAD_CONSTANT_TIME if (ret == 0 && mp_read_unsigned_bin(tmp, in, inLen) != MP_OKAY) ret = MP_READ_E; @@ -2664,144 +2766,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, case RSA_PRIVATE_DECRYPT: case RSA_PRIVATE_ENCRYPT: { - #if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) - /* blind */ - ret = mp_rand(rnd, get_digit_count(&key->n), rng); - if (ret != 0) - break; - /* rndi = 1/rnd mod n */ - if (mp_invmod(rnd, &key->n, rndi) != MP_OKAY) { - ret = MP_INVMOD_E; - break; - } - #ifdef WOLFSSL_CHECK_MEM_ZERO - mp_memzero_add("RSA sync rnd", rnd); - mp_memzero_add("RSA sync rndi", rndi); - #endif - - /* rnd = rnd^e */ - #ifndef WOLFSSL_SP_MATH_ALL - if (mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY) { - ret = MP_EXPTMOD_E; - break; - } - #else - if (mp_exptmod_nct(rnd, &key->e, &key->n, rnd) != MP_OKAY) { - ret = MP_EXPTMOD_E; - break; - } - #endif - - /* tmp = tmp*rnd mod n */ - if (mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY) { - ret = MP_MULMOD_E; - break; - } - #endif /* WC_RSA_BLINDING && !WC_NO_RNG */ - - #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ - if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) { - ret = MP_EXPTMOD_E; - break; - } - #else - { - #ifdef WOLFSSL_SMALL_STACK - mp_int* tmpa; - mp_int* tmpb = NULL; - #else - mp_int tmpa[1], tmpb[1]; - #endif - int cleara = 0, clearb = 0; - - #ifdef WOLFSSL_SMALL_STACK - tmpa = (mp_int*)XMALLOC(sizeof(mp_int) * 2, - key->heap, DYNAMIC_TYPE_RSA); - if (tmpa != NULL) - tmpb = tmpa + 1; - else - ret = MEMORY_E; - if (ret == 0) - #endif - { - if (mp_init(tmpa) != MP_OKAY) - ret = MP_INIT_E; - else - cleara = 1; - } - - if (ret == 0) { - if (mp_init(tmpb) != MP_OKAY) - ret = MP_INIT_E; - else - clearb = 1; - } - - #ifdef WOLFSSL_CHECK_MEM_ZERO - if (ret == 0) { - mp_memzero_add("RSA Sync tmpa", tmpa); - mp_memzero_add("RSA Sync tmpb", tmpb); - } - #endif - - /* tmpa = tmp^dP mod p */ - if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p, - tmpa) != MP_OKAY) - ret = MP_EXPTMOD_E; - - /* tmpb = tmp^dQ mod q */ - if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q, - tmpb) != MP_OKAY) - ret = MP_EXPTMOD_E; - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ -#if defined(WOLFSSL_SP_MATH) || (defined(WOLFSSL_SP_MATH_ALL) && \ - !defined(WOLFSSL_SP_INT_NEGATIVE)) - if (ret == 0 && mp_submod(tmpa, tmpb, &key->p, tmp) != MP_OKAY) - ret = MP_SUB_E; -#else - if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY) - ret = MP_SUB_E; -#endif - - if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p, - tmp) != MP_OKAY) - ret = MP_MULMOD_E; - - /* tmp = tmpb + q * tmp */ - if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY) - ret = MP_MUL_E; - - if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY) - ret = MP_ADD_E; - - #ifdef WOLFSSL_SMALL_STACK - if (tmpa != NULL) - #endif - { - if (cleara) { - mp_forcezero(tmpa); - } - if (clearb) { - mp_forcezero(tmpb); - } - #ifdef WOLFSSL_SMALL_STACK - /* tmpb is allocated after tmpa. */ - XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA); - #elif defined(WOLFSSL_CHECK_MEM_ZERO) - mp_memzero_check(tmpb); - mp_memzero_check(tmpa); - #endif - } - } /* tmpa/b scope */ - #endif /* RSA_LOW_MEM */ - - #ifdef WC_RSA_BLINDING - /* unblind */ - if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY) - ret = MP_MULMOD_E; - #endif /* WC_RSA_BLINDING */ - + ret = RsaFunctionPrivate(tmp, key, rng); break; } #endif @@ -2817,43 +2782,70 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, } if (ret == 0) { - if (keyLen > *outLen) - ret = RSA_BUFFER_E; - } - - if (ret == 0) { - *outLen = keyLen; - if (mp_to_unsigned_bin_len(tmp, out, keyLen) != MP_OKAY) + if (mp_to_unsigned_bin_len(tmp, out, *outLen) != MP_OKAY) ret = MP_TO_E; } #else (void)type; (void)key; XMEMCPY(out, in, inLen); - *outLen = inLen; #endif mp_forcezero(tmp); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); -#elif defined(WOLFSSL_CHECK_MEM_ZERO) + FREE_MP_INT_SIZE(tmp, key->heap, DYNAMIC_TYPE_RSA); +#if !defined(MP_INT_SIZE_CHECK_NULL) && defined(WOLFSSL_CHECK_MEM_ZERO) mp_memzero_check(tmp); #endif -#ifdef WC_RSA_BLINDING - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - mp_forcezero(rndi); - mp_forcezero(rnd); - } -#ifdef WOLFSSL_SMALL_STACK - XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA); -#elif defined(WOLFSSL_CHECK_MEM_ZERO) - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - mp_memzero_check(rnd); - mp_memzero_check(rndi); - } -#endif -#endif /* WC_RSA_BLINDING */ return ret; +} +#endif /* !WOLFSSL_SP_MATH */ + +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ +#ifdef WOLFSSL_HAVE_SP_RSA + int ret; +#endif + + word32 keyLen = wc_RsaEncryptSize(key); + + if (inLen > keyLen) { + WOLFSSL_MSG("Expected that inLen be no longer RSA key length"); + return BAD_FUNC_ARG; + } + if (keyLen > *outLen) { + WOLFSSL_MSG("Expected that outLen be no shorter RSA key length"); + return RSA_BUFFER_E; + } + + if (mp_iseven(&key->n)) { + return MP_VAL; + } + +#ifdef WOLFSSL_HAVE_SP_RSA + ret = RsaFunction_SP(in, inLen, out, outLen, type, key, rng); + if (ret != WC_KEY_SIZE_E) + return ret; +#endif /* WOLFSSL_HAVE_SP_RSA */ + +#if defined(WOLFSSL_SP_MATH) + (void)rng; +#ifndef WOLFSSL_HAVE_SP_RSA + (void)in; + (void)inLen; + (void)out; + (void)outLen; + (void)type; + (void)key; + #error RSA SP option invalid (enable WOLFSSL_HAVE_SP_RSA or disable WOLFSSL_SP_MATH) + return NOT_COMPILED_IN; +#else + WOLFSSL_MSG("SP Key Size Error"); + return WC_KEY_SIZE_E; +#endif +#else + *outLen = keyLen; + return RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif /* WOLFSSL_SP_MATH */ } #endif /* WOLF_CRYPTO_CB_ONLY_RSA */ @@ -3129,6 +3121,53 @@ int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig, } #endif /* WOLFSSL_CRYPTOCELL */ +#ifndef WOLF_CRYPTO_CB_ONLY_RSA +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(TEST_UNPAD_CONSTANT_TIME) && !defined(NO_RSA_BOUNDS_CHECK) +/* Check that 1 < in < n-1. (Requirement of 800-56B.) */ +static int RsaFunctionCheckIn(const byte* in, word32 inLen, RsaKey* key, + int checkSmallCt) +{ + int ret = 0; + DECL_MP_INT_SIZE_DYN(c, mp_bitsused(&key->n), RSA_MAX_SIZE); + + NEW_MP_INT_SIZE(c, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA); +#ifdef MP_INT_SIZE_CHECK_NULL + if (c == NULL) + ret = MEMORY_E; +#endif + + if (ret == 0 && INIT_MP_INT_SIZE(c, mp_bitsused(&key->n)) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0) { + if (mp_read_unsigned_bin(c, in, inLen) != 0) + ret = MP_READ_E; + } + if (ret == 0) { + /* check c > 1 */ + if (checkSmallCt && (mp_cmp_d(c, 1) != MP_GT)) + ret = RSA_OUT_OF_RANGE_E; + } + if (ret == 0) { + /* add c+1 */ + if (mp_add_d(c, 1, c) != MP_OKAY) + ret = MP_ADD_E; + } + if (ret == 0) { + /* check c+1 < n */ + if (mp_cmp(c, &key->n) != MP_LT) + ret = RSA_OUT_OF_RANGE_E; + } + mp_clear(c); + + FREE_MP_INT_SIZE(c, key->heap, DYNAMIC_TYPE_RSA); + + return ret; +} +#endif /* !WOLFSSL_RSA_VERIFY_ONLY && !TEST_UNPAD_CONSTANT_TIME && + * !NO_RSA_BOUNDS_CHECK */ +#endif /* WOLF_CRYPTO_CB_ONLY_RSA */ + static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng, int checkSmallCt) @@ -3169,47 +3208,7 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, if (type == RSA_PRIVATE_DECRYPT && key->state == RSA_STATE_DECRYPT_EXPTMOD) { - /* Check that 1 < in < n-1. (Requirement of 800-56B.) */ -#ifdef WOLFSSL_SMALL_STACK - mp_int* c; -#else - mp_int c[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - c = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); - if (c == NULL) - ret = MEMORY_E; -#endif - - if (ret == 0 && mp_init(c) != MP_OKAY) - ret = MP_INIT_E; - if (ret == 0) { - if (mp_read_unsigned_bin(c, in, inLen) != 0) - ret = MP_READ_E; - } - if (ret == 0) { - /* check c > 1 */ - if (checkSmallCt && (mp_cmp_d(c, 1) != MP_GT)) - ret = RSA_OUT_OF_RANGE_E; - } - if (ret == 0) { - /* add c+1 */ - if (mp_add_d(c, 1, c) != MP_OKAY) - ret = MP_ADD_E; - } - if (ret == 0) { - /* check c+1 < n */ - if (mp_cmp(c, &key->n) != MP_LT) - ret = RSA_OUT_OF_RANGE_E; - } - mp_clear(c); - -#ifdef WOLFSSL_SMALL_STACK - if (c != NULL) - XFREE(c, key->heap, DYNAMIC_TYPE_RSA); -#endif - + ret = RsaFunctionCheckIn(in, inLen, key, checkSmallCt); if (ret != 0) { RESTORE_VECTOR_REGISTERS(); return ret; diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index a959a317c..99cec0760 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -34,6 +34,19 @@ This library provides single precision (SP) integer math functions. #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) +#if (!defined(WOLFSSL_SMALL_STACK) && !defined(SP_ALLOC)) || \ + defined(WOLFSSL_SP_NO_MALLOC) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(WOLFSSL_SP_NO_DYN_STACK) +#pragma GCC diagnostic push +/* We are statically declaring a variable smaller than sp_int. + * We track available memory in the 'size' field. + * Disable warnings of sp_int being partly outside array bounds of variable. + */ +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif +#endif + #ifdef NO_INLINE #include #else @@ -89,8 +102,9 @@ This library provides single precision (SP) integer math functions. * WOLFSSL_SP_INT_DIGIT_ALIGN Enable when unaligned access of sp_int_digit * pointer is not allowed. * WOLFSSL_SP_NO_DYN_STACK Disable use of dynamic stack items. - * Used with small code size and not small stack. + * Dynamic arrays used when not small stack. * WOLFSSL_SP_FAST_MODEXP Allow fast mod_exp with small C code + * WOLFSSL_SP_LOW_MEM Use algorithms that use less memory. */ /* TODO: WOLFSSL_SP_SMALL is incompatible with clang-12+ -Os. */ @@ -109,7 +123,7 @@ This library provides single precision (SP) integer math functions. sp_int* n = NULL #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) /* Declare a variable on the stack with the required data size. */ #define DECL_SP_INT(n, s) \ byte n##d[MP_INT_SIZEOF(s)]; \ @@ -187,16 +201,20 @@ This library provides single precision (SP) integer math functions. #endif +/* Declare a variable that will be assigned a value on XMALLOC. */ +#define DECL_DYN_SP_INT_ARRAY(n, s, c) \ + sp_int* n##d = NULL; \ + sp_int* (n)[c] = { NULL, } + /* DECL_SP_INT_ARRAY: Declare array of 'sp_int'. */ #if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \ !defined(WOLFSSL_SP_NO_MALLOC) /* Declare a variable that will be assigned a value on XMALLOC. */ #define DECL_SP_INT_ARRAY(n, s, c) \ - sp_int* n##d = NULL; \ - sp_int* (n)[c] = { NULL, } + DECL_DYN_SP_INT_ARRAY(n, s, c) #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) /* Declare a variable on the stack with the required data size. */ #define DECL_SP_INT_ARRAY(n, s, c) \ byte n##d[MP_INT_SIZEOF(s) * (c)]; \ @@ -209,38 +227,41 @@ This library provides single precision (SP) integer math functions. #endif #endif -/* ALLOC_SP_INT_ARRAY: Allocate an array of 'sp_int's of required size. */ -#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \ - !defined(WOLFSSL_SP_NO_MALLOC) - /* Dynamically allocate just enough data to support multiple sp_ints of the - * required size. Use pointers into data to make up array and set sizes. - */ - #define ALLOC_SP_INT_ARRAY(n, s, c, err, h) \ - do { \ - if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) { \ - (err) = MP_VAL; \ - } \ - if ((err) == MP_OKAY) { \ - n##d = (sp_int*)XMALLOC(MP_INT_SIZEOF(s) * (c), (h), \ +/* Dynamically allocate just enough data to support multiple sp_ints of the + * required size. Use pointers into data to make up array and set sizes. + */ +#define ALLOC_DYN_SP_INT_ARRAY(n, s, c, err, h) \ +do { \ + if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) { \ + (err) = MP_VAL; \ + } \ + if ((err) == MP_OKAY) { \ + n##d = (sp_int*)XMALLOC(MP_INT_SIZEOF(s) * (c), (h), \ DYNAMIC_TYPE_BIGINT); \ - if (n##d == NULL) { \ - (err) = MP_MEM; \ - } \ - else { \ - int n##ii; \ - (n)[0] = n##d; \ - (n)[0]->size = (s); \ - for (n##ii = 1; n##ii < (c); n##ii++) { \ - (n)[n##ii] = MP_INT_NEXT((n)[n##ii-1], s); \ - (n)[n##ii]->size = (s); \ - } \ + if (n##d == NULL) { \ + (err) = MP_MEM; \ + } \ + else { \ + int n##ii; \ + (n)[0] = n##d; \ + (n)[0]->size = (s); \ + for (n##ii = 1; n##ii < (c); n##ii++) { \ + (n)[n##ii] = MP_INT_NEXT((n)[n##ii-1], s); \ + (n)[n##ii]->size = (s); \ } \ } \ } \ - while (0) +} \ +while (0) + +/* ALLOC_SP_INT_ARRAY: Allocate an array of 'sp_int's of required size. */ +#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \ + !defined(WOLFSSL_SP_NO_MALLOC) + #define ALLOC_SP_INT_ARRAY(n, s, c, err, h) \ + ALLOC_DYN_SP_INT_ARRAY(n, s, c, err, h) #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) /* Data declared on stack that supports multiple sp_ints of the * required size. Use pointers into data to make up array and set sizes. */ @@ -281,17 +302,20 @@ This library provides single precision (SP) integer math functions. #endif #endif +/* Free data variable that was dynamically allocated. */ +#define FREE_DYN_SP_INT_ARRAY(n, h) \ +do { \ + if (n##d != NULL) { \ + XFREE(n##d, h, DYNAMIC_TYPE_BIGINT); \ + } \ +} \ +while (0) + /* FREE_SP_INT_ARRAY: Free an array of 'sp_int'. */ #if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \ !defined(WOLFSSL_SP_NO_MALLOC) - /* Free data variable that was dynamically allocated. */ #define FREE_SP_INT_ARRAY(n, h) \ - do { \ - if (n##d != NULL) { \ - XFREE(n##d, h, DYNAMIC_TYPE_BIGINT); \ - } \ - } \ - while (0) + FREE_DYN_SP_INT_ARRAY(n, h) #else /* Nothing to do as data declared on stack. */ #define FREE_SP_INT_ARRAY(n, h) @@ -8256,13 +8280,18 @@ int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem) /* Set to temporary when not reusing. */ if (sa == NULL) { sa = td[i++]; + _sp_init_size(sa, a->used + 1); } if (tr == NULL) { tr = td[i]; + _sp_init_size(tr, a->used - d->used + 2); } #else sa = td[2]; tr = td[3]; + + _sp_init_size(sa, a->used + 1); + _sp_init_size(tr, a->used - d->used + 2); #endif sd = td[0]; trial = td[1]; @@ -8270,18 +8299,6 @@ int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem) /* Initialize sizes to minimal values. */ _sp_init_size(sd, d->used + 1); _sp_init_size(trial, a->used + 1); - #if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \ - !defined(WOLFSSL_SP_NO_MALLOC) - if (sa != rem) { - _sp_init_size(sa, a->used + 1); - } - if (tr != r) { - _sp_init_size(tr, a->used - d->used + 2); - } - #else - _sp_init_size(sa, a->used + 1); - _sp_init_size(tr, a->used - d->used + 2); - #endif /* Move divisor to top of word. Adjust dividend as well. */ s = sp_count_bits(d); @@ -8348,6 +8365,7 @@ int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem) (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) #ifndef FREESCALE_LTC_TFM +#ifdef WOLFSSL_SP_INT_NEGATIVE /* Calculate the remainder of dividing a by m: r = a mod m. * * @param [in] a SP integer to reduce. @@ -8355,31 +8373,14 @@ int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem) * @param [out] r SP integer to store result in. * * @return MP_OKAY on success. - * @return MP_VAL when a, m or r is NULL or m is 0. + * @return MP_MEM when dynamic memory allocation fails. */ -int sp_mod(const sp_int* a, const sp_int* m, sp_int* r) +static int _sp_mod(const sp_int* a, const sp_int* m, sp_int* r) { int err = MP_OKAY; -#ifdef WOLFSSL_SP_INT_NEGATIVE /* Remainder will start as a. */ DECL_SP_INT(t, (a == NULL) ? 1 : a->used + 1); -#endif /* WOLFSSL_SP_INT_NEGATIVE */ - /* Validate parameters. */ - if ((a == NULL) || (m == NULL) || (r == NULL)) { - err = MP_VAL; - } - /* Ensure a isn't too big a number to operate on. */ - else if (a->used >= SP_INT_DIGITS) { - err = MP_VAL; - } - -#ifndef WOLFSSL_SP_INT_NEGATIVE - if (err == MP_OKAY) { - /* Use divide to calculate remainder and don't get quotient. */ - err = sp_div(a, m, NULL, r); - } -#else /* In case remainder is modulus - allocate temporary. */ ALLOC_SP_INT(t, a->used + 1, err, NULL); if (err == MP_OKAY) { @@ -8396,8 +8397,50 @@ int sp_mod(const sp_int* a, const sp_int* m, sp_int* r) err = sp_copy(t, r); } } - FREE_SP_INT(t, NULL); + + return err; +} +#endif + +/* Calculate the remainder of dividing a by m: r = a mod m. + * + * @param [in] a SP integer to reduce. + * @param [in] m SP integer that is the modulus. + * @param [out] r SP integer to store result in. + * + * @return MP_OKAY on success. + * @return MP_VAL when a, m or r is NULL or m is 0. + * @return MP_MEM when dynamic memory allocation fails. + */ +int sp_mod(const sp_int* a, const sp_int* m, sp_int* r) +{ + int err = MP_OKAY; + + /* Validate parameters. */ + if ((a == NULL) || (m == NULL) || (r == NULL)) { + err = MP_VAL; + } + /* Ensure a isn't too big a number to operate on. */ + else if (a->used >= SP_INT_DIGITS) { + err = MP_VAL; + } + +#ifndef WOLFSSL_SP_INT_NEGATIVE + if (err == MP_OKAY) { + /* Use divide to calculate remainder and don't get quotient. */ + err = sp_div(a, m, NULL, r); + } +#else + if ((err == MP_OKAY) && (r != m)) { + err = sp_div(a, m, NULL, r); + if ((!sp_iszero(r)) && (r->sign != m->sign)) { + err = sp_add(r, m, r); + } + } + else if (err == MP_OKAY) { + err = _sp_mod(a, m, r); + } #endif /* WOLFSSL_SP_INT_NEGATIVE */ return err; @@ -8438,14 +8481,14 @@ static int _sp_mul_nxn(const sp_int* a, const sp_int* b, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) - sp_int_digit t[a->used * 2]; + !defined(WOLFSSL_SP_NO_DYN_STACK) + sp_int_digit t[a->used]; #else - sp_int_digit t[SP_INT_DIGITS]; + sp_int_digit t[SP_INT_DIGITS / 2]; #endif #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * (a->used * 2), NULL, + t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * a->used, NULL, DYNAMIC_TYPE_BIGINT); if (t == NULL) { err = MP_MEM; @@ -8480,14 +8523,14 @@ static int _sp_mul_nxn(const sp_int* a, const sp_int* b, sp_int* r) for (; i < a->used; i++, dp--) { SP_ASM_MUL_ADD(l, h, o, a->dp[i], dp[0]); } - t[k] = l; + r->dp[k] = l; l = h; h = o; o = 0; } - t[k] = l; + r->dp[k] = l; + XMEMCPY(r->dp, t, a->used * sizeof(sp_int_digit)); r->used = k + 1; - XMEMCPY(r->dp, t, r->used * sizeof(sp_int_digit)); sp_clamp(r); } @@ -8517,7 +8560,7 @@ static int _sp_mul(const sp_int* a, const sp_int* b, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used + b->used]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -8595,7 +8638,7 @@ static int _sp_mul(const sp_int* a, const sp_int* b, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used + b->used]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -8664,7 +8707,7 @@ static int _sp_mul(const sp_int* a, const sp_int* b, sp_int* r) #ifndef WOLFSSL_SP_SMALL #if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC) -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256) #ifndef SQR_MUL_ASM /* Multiply a by b and store in r: r = a * b * @@ -8852,7 +8895,7 @@ static int _sp_mul_4(const sp_int* a, const sp_int* b, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM /* Multiply a by b and store in r: r = a * b * @@ -8955,7 +8998,7 @@ static int _sp_mul_6(const sp_int* a, const sp_int* b, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256) #ifdef SQR_MUL_ASM /* Multiply a by b and store in r: r = a * b * @@ -9102,7 +9145,7 @@ static int _sp_mul_8(const sp_int* a, const sp_int* b, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 32 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM /* Multiply a by b and store in r: r = a * b * @@ -11307,13 +11350,13 @@ int sp_mul(const sp_int* a, const sp_int* b, sp_int* r) else #ifndef WOLFSSL_SP_SMALL #if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC) -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256) if ((a->used == 4) && (b->used == 4)) { err = _sp_mul_4(a, b, r); } else #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM if ((a->used == 6) && (b->used == 6)) { err = _sp_mul_6(a, b, r); @@ -11321,7 +11364,7 @@ int sp_mul(const sp_int* a, const sp_int* b, sp_int* r) else #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256) #ifdef SQR_MUL_ASM if ((a->used == 8) && (b->used == 8)) { err = _sp_mul_8(a, b, r); @@ -11329,7 +11372,7 @@ int sp_mul(const sp_int* a, const sp_int* b, sp_int* r) else #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 32 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM if ((a->used == 12) && (b->used == 12)) { err = _sp_mul_12(a, b, r); @@ -11415,6 +11458,32 @@ int sp_mul(const sp_int* a, const sp_int* b, sp_int* r) #if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \ defined(WOLFCRYPT_HAVE_ECCSI) || \ (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) || defined(OPENSSL_ALL) +static int _sp_mulmod(const sp_int* a, const sp_int* b, const sp_int* m, + sp_int* r) +{ + int err = MP_OKAY; + + /* Create temporary for multiplication result. */ + DECL_SP_INT(t, a->used + b->used); + ALLOC_SP_INT(t, a->used + b->used, err, NULL); + if (err == MP_OKAY) { + err = sp_init_size(t, a->used + b->used); + } + + /* Multiply and reduce. */ + if (err == MP_OKAY) { + err = sp_mul(a, b, t); + } + if (err == MP_OKAY) { + err = sp_mod(t, m, r); + } + + /* Dispose of an allocated SP int. */ + FREE_SP_INT(t, NULL); + + return err; +} + /* Multiply a by b mod m and store in r: r = (a * b) mod m * * @param [in] a SP integer to multiply. @@ -11459,23 +11528,7 @@ int sp_mulmod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r) } } else if (err == MP_OKAY) { - /* Create temporary for multiplication result. */ - DECL_SP_INT(t, a->used + b->used); - ALLOC_SP_INT(t, a->used + b->used, err, NULL); - if (err == MP_OKAY) { - err = sp_init_size(t, a->used + b->used); - } - - /* Multiply and reduce. */ - if (err == MP_OKAY) { - err = sp_mul(a, b, t); - } - if (err == MP_OKAY) { - err = sp_mod(t, m, r); - } - - /* Dispose of an allocated SP int. */ - FREE_SP_INT(t, NULL); + _sp_mulmod(a, b, m, r); } #if 0 @@ -11581,7 +11634,8 @@ static int _sp_invmod_bin(const sp_int* a, const sp_int* m, sp_int* u, return err; } -#if !defined(WOLFSSL_SP_SMALL) && (!defined(NO_RSA) || !defined(NO_DH)) +#if !defined(WOLFSSL_SP_LOW_MEM) && !defined(WOLFSSL_SP_SMALL) && \ + (!defined(NO_RSA) || !defined(NO_DH)) /* Calculates the multiplicative inverse in the field. r*a = x*m + 1 * Extended Euclidean Algorithm. NOT constant time. * @@ -11614,20 +11668,17 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, sp_int* y, sp_int* b, sp_int* c, sp_int* inv) { int err = MP_OKAY; - sp_int* d = NULL; - sp_int* r = NULL; sp_int* s; #ifndef WOLFSSL_SP_INT_NEGATIVE int bneg = 0; int cneg = 0; int neg; #endif - DECL_SP_INT_ARRAY(t, m->used + 1, 2); + DECL_SP_INT(d, m->used + 1); - ALLOC_SP_INT_ARRAY(t, m->used + 1, 2, err, NULL); + ALLOC_SP_INT(d, m->used + 1, err, NULL); if (err == MP_OKAY) { - d = t[0]; - r = t[1]; + mp_init(d); /* 1. x = m, y = a, b = 1, c = 0 */ _sp_copy(a, y); @@ -11639,7 +11690,7 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, /* 2. while x > 1 */ while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) { /* 2.1. d = x / y, r = x mod y */ - err = sp_div(x, y, d, r); + err = sp_div(x, y, d, x); if (err == MP_OKAY) { /* 2.2. c -= d * b */ if (sp_isone(d)) { @@ -11655,7 +11706,7 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, } } /* 2.3. x = y, y = r */ - s = x; x = y; y = r; r = s; + s = y; y = x; x = s; /* 2.4. s = b, b = c, c = s */ s = b; b = c; c = s; } @@ -11676,7 +11727,7 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, /* 2. while x > 1 */ while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) { /* 2.1. d = x / y, r = x mod y */ - err = sp_div(x, y, d, r); + err = sp_div(x, y, d, x); if (err == MP_OKAY) { if (sp_isone(d)) { /* c -= 1 * b */ @@ -11715,7 +11766,7 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, } } /* 2.3. x = y, y = r */ - s = x; x = y; y = r; r = s; + s = y; y = x; x = s; /* 2.4. s = b, b = c, c = s */ s = b; b = c; c = s; neg = bneg; bneg = cneg; cneg = neg; @@ -11736,7 +11787,7 @@ static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x, } #endif - FREE_SP_INT_ARRAY(t, NULL); + FREE_SP_INT(d, NULL); return err; } #endif @@ -11810,7 +11861,8 @@ static int _sp_invmod(const sp_int* a, const sp_int* m, sp_int* r) if (err == MP_OKAY) { /* Calculate inverse. */ - #if !defined(WOLFSSL_SP_SMALL) && (!defined(NO_RSA) || !defined(NO_DH)) + #if !defined(WOLFSSL_SP_LOW_MEM) && !defined(WOLFSSL_SP_SMALL) && \ + (!defined(NO_RSA) || !defined(NO_DH)) if (sp_count_bits(mm) >= 1024) { err = _sp_invmod_div(ma, mm, u, v, b, c, c); } @@ -11975,8 +12027,13 @@ int sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r, int s = 0; sp_int* t = NULL; sp_int* e = NULL; +#ifndef WOLFSSL_SP_NO_MALLOC + DECL_DYN_SP_INT_ARRAY(pre, (m == NULL) ? 1 : m->used * 2 + 1, + CT_INV_MOD_PRE_CNT + 2); +#else DECL_SP_INT_ARRAY(pre, (m == NULL) ? 1 : m->used * 2 + 1, CT_INV_MOD_PRE_CNT + 2); +#endif /* Validate parameters. */ if ((a == NULL) || (m == NULL) || (r == NULL)) { @@ -11989,7 +12046,12 @@ int sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r, err = MP_VAL; } +#ifndef WOLFSSL_SP_NO_MALLOC + ALLOC_DYN_SP_INT_ARRAY(pre, m->used * 2 + 1, CT_INV_MOD_PRE_CNT + 2, err, + NULL); +#else ALLOC_SP_INT_ARRAY(pre, m->used * 2 + 1, CT_INV_MOD_PRE_CNT + 2, err, NULL); +#endif if (err == MP_OKAY) { t = pre[CT_INV_MOD_PRE_CNT + 0]; e = pre[CT_INV_MOD_PRE_CNT + 1]; @@ -12118,7 +12180,11 @@ int sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r, } } +#ifndef WOLFSSL_SP_NO_MALLOC + FREE_DYN_SP_INT_ARRAY(pre, NULL); +#else FREE_SP_INT_ARRAY(pre, NULL); +#endif return err; } @@ -13084,13 +13150,6 @@ int sp_exptmod(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) #if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) #if defined(WOLFSSL_SP_FAST_NCT_EXPTMOD) || !defined(WOLFSSL_SP_SMALL) -/* Always allocate large array of sp_ints unless defined WOLFSSL_SP_NO_MALLOC */ -#ifdef SP_ALLOC -#define SP_ALLOC_PREDEFINED -#else -#define SP_ALLOC -#endif - /* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * Creates a window of precalculated exponents with base in Montgomery form. * Sliding window and is NOT constant time. @@ -13141,7 +13200,11 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* bm = NULL; sp_int_digit mask; /* Maximum winBits is 6 and preCnt is (1 << (winBits - 1)). */ +#ifndef WOLFSSL_SP_NO_MALLOC + DECL_DYN_SP_INT_ARRAY(t, m->used * 2 + 1, (1 << 5) + 2); +#else DECL_SP_INT_ARRAY(t, m->used * 2 + 1, (1 << 5) + 2); +#endif bits = sp_count_bits(e); @@ -13175,7 +13238,11 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, * - temporary result * - Montgomery form of base */ +#ifndef WOLFSSL_SP_NO_MALLOC + ALLOC_DYN_SP_INT_ARRAY(t, m->used * 2 + 1, preCnt + 2, err, NULL); +#else ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, preCnt + 2, err, NULL); +#endif if (err == MP_OKAY) { /* Set variables to use allocate memory. */ tr = t[preCnt + 0]; @@ -13393,15 +13460,14 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, err = sp_copy(tr, r); } +#ifndef WOLFSSL_SP_NO_MALLOC + FREE_DYN_SP_INT_ARRAY(t, NULL); +#else FREE_SP_INT_ARRAY(t, NULL); +#endif return err; } -#ifndef SP_ALLOC_PREDEFINED -#undef SP_ALLOC -#undef SP_ALLOC_PREDEFINED -#endif - #else /* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * Non-constant time implementation. @@ -13796,14 +13862,15 @@ static int _sp_sqr(const sp_int* a, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) - sp_int_digit t[a->used * 2]; + !defined(WOLFSSL_SP_NO_DYN_STACK) + sp_int_digit t[((a->used + 1) / 2) * 2 + 1]; #else - sp_int_digit t[SP_INT_DIGITS]; + sp_int_digit t[(SP_INT_DIGITS + 1) / 2]; #endif #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * (a->used * 2), NULL, + t = (sp_int_digit*)XMALLOC( + sizeof(sp_int_digit) * (((a->used + 1) / 2) * 2 + 1), NULL, DYNAMIC_TYPE_BIGINT); if (t == NULL) { err = MP_MEM; @@ -13816,13 +13883,14 @@ static int _sp_sqr(const sp_int* a, sp_int* r) h = 0; l = 0; SP_ASM_SQR(h, l, a->dp[0]); - t[0] = h; - t[1] = l; + r->dp[0] = h; + r->dp[1] = l; } else if (err == MP_OKAY) { sp_int_digit l; sp_int_digit h; sp_int_digit o; + sp_int_digit* p = t; h = 0; l = 0; @@ -13858,7 +13926,7 @@ static int _sp_sqr(const sp_int* a, sp_int* r) for (; (i < a->used); i++, j--) { SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]); } - t[k * 2 - 1] = l; + p[k * 2 - 1] = l; l = h; h = o; o = 0; @@ -13869,17 +13937,19 @@ static int _sp_sqr(const sp_int* a, sp_int* r) for (; (i < a->used); i++, j--) { SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]); } - t[k * 2] = l; + p[k * 2] = l; l = h; h = o; o = 0; + + p = r->dp; } - t[k * 2 - 1] = l; + r->dp[k * 2 - 1] = l; + XMEMCPY(r->dp, t, (((a->used + 1) / 2) * 2 + 1) * sizeof(sp_int_digit)); } if (err == MP_OKAY) { r->used = a->used * 2; - XMEMCPY(r->dp, t, r->used * sizeof(sp_int_digit)); sp_clamp(r); } @@ -13908,7 +13978,7 @@ static int _sp_sqr(const sp_int* a, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) + !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used * 2]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -13996,7 +14066,7 @@ static int _sp_sqr(const sp_int* a, sp_int* r) #ifndef WOLFSSL_SP_SMALL #if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC) -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256) #ifndef SQR_MUL_ASM /* Square a and store in r. r = a * a * @@ -14164,7 +14234,7 @@ static int _sp_sqr_4(const sp_int* a, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM /* Square a and store in r. r = a * a * @@ -14259,7 +14329,7 @@ static int _sp_sqr_6(const sp_int* a, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256) #ifdef SQR_MUL_ASM /* Square a and store in r. r = a * a * @@ -14389,7 +14459,7 @@ static int _sp_sqr_8(const sp_int* a, sp_int* r) } #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 32 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM /* Square a and store in r. r = a * a * @@ -16106,13 +16176,13 @@ int sp_sqr(const sp_int* a, sp_int* r) else #ifndef WOLFSSL_SP_SMALL #if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC) -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256) if (a->used == 4) { err = _sp_sqr_4(a, r); } else #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 64 +#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM if (a->used == 6) { err = _sp_sqr_6(a, r); @@ -16120,7 +16190,7 @@ int sp_sqr(const sp_int* a, sp_int* r) else #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 64 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256) #ifdef SQR_MUL_ASM if (a->used == 8) { err = _sp_sqr_8(a, r); @@ -16128,7 +16198,7 @@ int sp_sqr(const sp_int* a, sp_int* r) else #endif /* SQR_MUL_ASM */ #endif /* SP_WORD_SIZE == 32 */ -#if SP_WORD_SIZE == 32 +#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384) #ifdef SQR_MUL_ASM if (a->used == 12) { err = _sp_sqr_12(a, r); @@ -18577,5 +18647,12 @@ void sp_memzero_check(sp_int* sp) } #endif /* WOLFSSL_CHECK_MEM_ZERO */ +#if (!defined(WOLFSSL_SMALL_STACK) && !defined(SP_ALLOC)) || \ + defined(WOLFSSL_SP_NO_MALLOC) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(WOLFSSL_SP_NO_DYN_STACK) +#pragma GCC diagnostic pop +#endif +#endif #endif /* WOLFSSL_SP_MATH || WOLFSSL_SP_MATH_ALL */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index f3865f95f..442588712 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1235,9 +1235,11 @@ enum { #endif #define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8) +#ifndef NO_DH #if WOLFSSL_MAX_DHKEY_BITS < WOLFSSL_MIN_DHKEY_BITS #error "WOLFSSL_MAX_DHKEY_BITS has to be greater than WOLFSSL_MIN_DHKEY_BITS" #endif +#endif /* NO_DH */ #ifndef MAX_PSK_ID_LEN /* max psk identity/hint supported */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 7ba03c0b7..fb43f9748 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -689,10 +689,17 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); (! ((HAVE_FIPS_VERSION == 5) && (HAVE_FIPS_VERSION_MINOR == 0))))) WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen); #endif - #endif + #endif /* !HAVE_USER_RSA */ WOLFSSL_API int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header); WOLFSSL_API int wc_RsaKeyToPublicDer_ex(RsaKey* key, byte* output, word32 inLen, int with_header); + + /* For FIPS v1/v2 and selftest rsa.h is replaced. */ + #if defined(HAVE_SELFTEST) || (defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 5))) + WOLFSSL_API int wc_RsaPrivateKeyValidate(const byte* input, + word32* inOutIdx, int* keySz, word32 inSz); + #endif #endif #ifndef NO_DSA diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 712b91256..8a51b0772 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -189,6 +189,26 @@ typedef int mp_err; BITS_PER_DIGIT*2) */ #define MP_WARRAY ((mp_word)1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) +/* No point in dynamically allocating mp_int when it is very small. + * The dp field will grow and shrink dynamically. + */ +/* Declare a statically allocated mp_int. */ +#define DECL_MP_INT_SIZE(name, bits) \ + mp_int name[1] +/* Declare statically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + mp_int name[1] +/* Zero out mp_int of minimal size. */ +#define NEW_MP_INT_SIZE(name, bits, heap, type) \ + XMEMSET(name, 0, sizeof(mp_int)) +/* Dispose of static mp_int. */ +#define FREE_MP_INT_SIZE(name, heap, type) +/* Initialize an mp_int. */ +#define INIT_MP_INT_SIZE(name, bits) \ + mp_init(name) +/* Type to cast to when using size marcos. */ +#define MP_INT_SIZE mp_int + #ifdef HAVE_WOLF_BIGINT /* raw big integer */ typedef struct WC_BIGINT { @@ -237,6 +257,8 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define mp_isword(a, w) \ ((((a)->used == 1) && ((a)->dp[0] == (w))) || (((w) == 0) && ((a)->used == 0)) \ ? MP_YES : MP_NO) +/* Number of bits used based on used field only. */ +#define mp_bitsused(a) ((a)->used * DIGIT_BIT) /* number of primes */ #ifdef MP_8BIT diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 455ec0162..6d31aab55 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -352,6 +352,11 @@ WOLFSSL_API int wc_RsaEncryptSize(const RsaKey* key); /* to avoid asn duplicate symbols @wc_fips */ WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz); +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) +WOLFSSL_API int wc_RsaPrivateKeyValidate(const byte* input, word32* inOutIdx, + int* keySz, word32 inSz); +#endif WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz); WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 77f44b816..e824a8baf 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1939,6 +1939,9 @@ extern void uITRON4_free(void *p) ; #undef WOLFSSL_SP_INT_DIGIT_ALIGN #define WOLFSSL_SP_INT_DIGIT_ALIGN #endif +#ifdef __APPLE__ + #define WOLFSSL_SP_NO_DYN_STACK +#endif #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */ diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index fce3feb4a..c21224f2c 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -658,18 +658,21 @@ typedef struct sp_ecc_ctx { #define sp_setneg(a) ((a)->sign = MP_NEG) #endif +/* Number of bits used based on used field only. */ +#define sp_bitsused(a) ((a)->used * SP_WORD_SIZE) + /* Updates the used count to exclude leading zeros. * * Assumes a is not NULL. * * @param [in] a SP integer to update. */ -#define sp_clamp(a) \ - do { \ - int ii; \ - for (ii = (a)->used - 1; ii >= 0 && (a)->dp[ii] == 0; ii--) { \ - } \ - (a)->used = ii + 1; \ +#define sp_clamp(a) \ + do { \ + int ii; \ + for (ii = (a)->used - 1; ii >= 0 && (a)->dp[ii] == 0; ii--) { \ + } \ + (a)->used = ii + 1; \ } while (0) /* Check the compiled and linked math implementation are the same. @@ -681,16 +684,6 @@ typedef struct sp_ecc_ctx { #define CheckFastMathSettings() (SP_WORD_SIZE == CheckRunTimeFastMath()) -/* The number of bytes to a sp_int with 'cnt' digits. - * Must have at least one digit. - */ -#define MP_INT_SIZEOF(cnt) \ - (sizeof(sp_int) - (SP_INT_DIGITS - (((cnt) == 0) ? 1 : (cnt))) * \ - sizeof(sp_int_digit)) -/* The address of the next sp_int after one with 'cnt' digits. */ -#define MP_INT_NEXT(t, cnt) \ - (sp_int*)(((byte*)(t)) + MP_INT_SIZEOF(cnt)) - /** * A result of NO. * e.g. Is prime? NO. @@ -747,6 +740,86 @@ typedef struct sp_ecc_ctx { /* Mask of all used bits in word/digit. */ #define MP_MASK SP_MASK +#ifdef MP_LOW_MEM +/* Use algorithms that use less memory. */ +#define WOLFSSL_SP_LOW_MEM +#endif + + +/* The number of bytes to a sp_int with 'cnt' digits. + * Must have at least one digit. + */ +#define MP_INT_SIZEOF(cnt) \ + (sizeof(sp_int) - (SP_INT_DIGITS - (((cnt) == 0) ? 1 : (cnt))) * \ + sizeof(sp_int_digit)) +/* The address of the next sp_int after one with 'cnt' digits. */ +#define MP_INT_NEXT(t, cnt) \ + (sp_int*)(((byte*)(t)) + MP_INT_SIZEOF(cnt)) + + +/* Calculate the number of words required to support a number of bits. */ +#define MP_BITS_CNT(bits) \ + (((bits + SP_WORD_SIZE - 1) / SP_WORD_SIZE) * 2 + 1) + +#ifdef WOLFSSL_SMALL_STACK +/* + * Dynamic memory allocation of mp_int. + */ +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + sp_int* name = NULL +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE(name, bits) \ + sp_int* name = NULL +/* Allocate an mp_int of minimal size and zero out. */ +#define NEW_MP_INT_SIZE(name, bits, heap, type) \ +do { \ + name = (mp_int*)XMALLOC(MP_INT_SIZEOF(MP_BITS_CNT(bits)), heap, type); \ + if (name != NULL) { \ + XMEMSET(name, 0, MP_INT_SIZEOF(MP_BITS_CNT(bits))); \ + } \ +} \ +while (0) +/* Dispose of dynamically allocated mp_int. */ +#define FREE_MP_INT_SIZE(name, heap, type) \ + XFREE(name, heap, type) +/* Type to cast to when using size marcos. */ +#define MP_INT_SIZE sp_int +/* Must check mp_int pointer for NULL. */ +#define MP_INT_SIZE_CHECK_NULL +#else +/* + * Static allocation of mp_int. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(WOLFSSL_SP_NO_DYN_STACK) +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + unsigned char name##d[MP_INT_SIZEOF(MP_BITS_CNT(bits))]; \ + sp_int* name = (sp_int*)name##d +#else +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + unsigned char name##d[MP_INT_SIZEOF(MP_BITS_CNT(max))]; \ + sp_int* name = (sp_int*)name##d +#endif +/* Declare a statically allocated mp_int. */ +#define DECL_MP_INT_SIZE(name, bits) \ + unsigned char name##d[MP_INT_SIZEOF(MP_BITS_CNT(bits))]; \ + sp_int* name = (sp_int*)name##d +/* Zero out mp_int of minimal size. */ +#define NEW_MP_INT_SIZE(name, bits, heap, type) \ + XMEMSET(name, 0, MP_INT_SIZEOF(MP_BITS_CNT(bits))) +/* Dispose of static mp_int. */ +#define FREE_MP_INT_SIZE(name, heap, type) +/* Type to force compiler to not complain about size. */ +#define MP_INT_SIZE sp_int_minimal +#endif + +/* Initialize an mp_int to a specific size. */ +#define INIT_MP_INT_SIZE(name, bits) \ + mp_init_size(name, MP_BITS_CNT(bits)) + #ifdef HAVE_WOLF_BIGINT /* Raw big integer as a big-endian byte array. @@ -992,6 +1065,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp); #define mp_abs sp_abs #define mp_isneg sp_isneg #define mp_setneg sp_setneg +#define mp_bitsused sp_bitsused #define mp_clamp sp_clamp /* One to one mappings. */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 8c55535d1..94912a3c9 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -317,6 +317,55 @@ #define FP_YES 1 /* yes response */ #define FP_NO 0 /* no response */ + +#ifdef WOLFSSL_SMALL_STACK +/* + * Dynamic memory allocation of mp_int. + */ +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE(name, bits) \ + mp_int* name = NULL +/* Declare a dynamically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + mp_int* name = NULL +/* Allocate an mp_int of minimal size and zero out. */ +#define NEW_MP_INT_SIZE(name, bits, heap, type) \ +do { \ + name = (mp_int*)XMALLOC(sizeof(mp_int), heap, type); \ + if (name != NULL) { \ + XMEMSET(name, 0, sizeof(mp_int)); \ + } \ +} \ +while (0) +/* Dispose of dynamically allocated mp_int. */ +#define FREE_MP_INT_SIZE(name, heap, type) \ + XFREE(name, heap, type) +/* Must check for mp_int pointer for NULL. */ +#define MP_INT_SIZE_CHECK_NULL +#else +/* + * Static allocation of mp_int. + */ +/* Declare a statically allocated mp_int. */ +#define DECL_MP_INT_SIZE(name, bits) \ + mp_int name[1] +/* Declare a statically allocated mp_int. */ +#define DECL_MP_INT_SIZE_DYN(name, bits, max) \ + mp_int name[1] +/* Zero out mp_int of minimal size. */ +#define NEW_MP_INT_SIZE(name, bits, heap, type) \ + XMEMSET(name, 0, sizeof(mp_int)) +/* Dispose of static mp_int. */ +#define FREE_MP_INT_SIZE(name, heap, type) +#endif + +/* Initialize an mp_int. */ +#define INIT_MP_INT_SIZE(name, bits) \ + mp_init(name) +/* Type to cast to when using size marcos. */ +#define MP_INT_SIZE mp_int + + #ifdef HAVE_WOLF_BIGINT /* raw big integer */ typedef struct WC_BIGINT { @@ -448,6 +497,8 @@ MP_API void fp_free(fp_int* a); #define fp_isword(a, w) \ (((((a)->used == 1) && ((a)->dp[0] == (w))) || \ (((w) == 0) && ((a)->used == 0))) ? FP_YES : FP_NO) +/* Number of bits used based on used field only. */ +#define fp_bitsused(a) ((a)->used * DIGIT_BIT) /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); @@ -740,6 +791,7 @@ int fp_sqr_comba64(fp_int *a, fp_int *b); #define mp_isneg(a) fp_isneg(a) #define mp_setneg(a) fp_setneg(a) #define mp_isword(a, w) fp_isword(a, w) +#define mp_bitsused(a) fp_bitsused(a) #define MP_RADIX_BIN 2 #define MP_RADIX_OCT 8