diff --git a/src/ssl.c b/src/ssl.c index 2813d3b24..bbb0be506 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 9875f5d32..2f16c6265 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 */ @@ -31177,14 +31269,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 9448bc789..f90ebc67c 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1995,6 +1995,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