diff --git a/configure.ac b/configure.ac index 89bba24e6..e898696e2 100644 --- a/configure.ac +++ b/configure.ac @@ -2257,12 +2257,12 @@ fi # ECC encrypt AC_ARG_ENABLE([eccencrypt], - [AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled)])], + [AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled). yes = SEC1 standard, iso18033 = ISO 18033 standard, old = original wolfSSL algorithm])], [ ENABLED_ECC_ENCRYPT=$enableval ], [ ENABLED_ECC_ENCRYPT=no ] ) -if test "$ENABLED_ECC_ENCRYPT" = "yes" +if test "$ENABLED_ECC_ENCRYPT" != "no" then if test "$ENABLED_ECC" = "no" then @@ -2273,6 +2273,14 @@ then AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.]) fi AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT" + if test "$ENABLED_ECC_ENCRYPT" = "old" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_OLD" + fi + if test "$ENABLED_ECC_ENCRYPT" = "iso18033" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_ISO18033" + fi fi # Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption (ECCSI) diff --git a/tests/api.c b/tests/api.c index 7c78694c5..9b611035a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -23021,11 +23021,15 @@ static int test_wc_ecc_encryptDecrypt (void) #if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) \ && !defined(WC_NO_RNG) - ecc_key srvKey, cliKey; + ecc_key srvKey, cliKey, tmpKey; WC_RNG rng; const char* msg = "EccBlock Size 16"; word32 msgSz = (word32)XSTRLEN(msg); +#ifdef WOLFSSL_ECIES_OLD byte out[XSTRLEN(msg) + WC_SHA256_DIGEST_SIZE]; +#else + byte out[KEY20 * 2 + 1 + XSTRLEN(msg) + WC_SHA256_DIGEST_SIZE]; +#endif word32 outSz = (word32)sizeof(out); byte plain[XSTRLEN(msg) + 1]; word32 plainSz = (word32)sizeof(plain); @@ -23050,6 +23054,9 @@ static int test_wc_ecc_encryptDecrypt (void) if (ret == 0) { ret = wc_ecc_make_key(&rng, keySz, &srvKey); } + if (ret == 0) { + ret = wc_ecc_init(&tmpKey); + } } #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ @@ -23098,27 +23105,38 @@ static int test_wc_ecc_encryptDecrypt (void) printf(resultFmt, ret == 0 ? passed : failed); printf(testingFmt, "wc_ecc_decrypt()"); +#ifdef WOLFSSL_ECIES_OLD if (ret == 0) { - ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, plain, + tmpKey.dp = cliKey.dp; + ret = wc_ecc_copy_point(&cliKey.pubkey, &tmpKey.pubkey); + } +#endif + + if (ret == 0) { + ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz, plain, &plainSz, NULL); } if (ret == 0) { - ret = wc_ecc_decrypt(NULL, &cliKey, out, outSz, plain, + ret = wc_ecc_decrypt(NULL, &tmpKey, out, outSz, plain, &plainSz, NULL); + #ifdef WOLFSSL_ECIES_OLD + /* NULL parameter allowed in new implementations - public key comes from + * the message. */ if (ret == BAD_FUNC_ARG) { ret = wc_ecc_decrypt(&srvKey, NULL, out, outSz, plain, &plainSz, NULL); } + #endif if (ret == BAD_FUNC_ARG) { - ret = wc_ecc_decrypt(&srvKey, &cliKey, NULL, outSz, plain, + ret = wc_ecc_decrypt(&srvKey, &tmpKey, NULL, outSz, plain, &plainSz, NULL); } if (ret == BAD_FUNC_ARG) { - ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, NULL, + ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz, NULL, &plainSz, NULL); } if (ret == BAD_FUNC_ARG) { - ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, + ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz, plain, NULL, NULL); } if (ret == BAD_FUNC_ARG) { @@ -23137,6 +23155,7 @@ static int test_wc_ecc_encryptDecrypt (void) if (wc_FreeRng(&rng) && ret == 0) { ret = WOLFSSL_FATAL_ERROR; } + wc_ecc_free(&tmpKey); wc_ecc_free(&cliKey); wc_ecc_free(&srvKey); diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index e96369bfc..dead59c8a 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9148,8 +9148,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, } /* Import x, y and optional private (d) as unsigned binary */ -int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, - byte* d, int curve_id) +int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy, + const byte* d, int curve_id) { return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy, (const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN); @@ -9195,6 +9195,20 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, } #endif /* HAVE_ECC_KEY_IMPORT */ +#if defined(HAVE_ECC_ENCRYPT) && !defined(WOLFSSL_ECIES_OLD) +/* public key size in octets */ +static int ecc_public_key_size(ecc_key* key, word32* sz) +{ + if (key == NULL || key->dp == NULL) + return BAD_FUNC_ARG; + + /* 'Uncompressed' | x | y */ + *sz = 1 + 2 * key->dp->size; + + return 0; +} +#endif + /* key size in octets */ int wc_ecc_size(ecc_key* key) { @@ -11170,7 +11184,6 @@ void wc_ecc_ctx_free(ecEncCtx* ctx) } } - static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, int* keysLen, word32* digestSz, word32* blockSz) { @@ -11195,7 +11208,11 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, } else return BAD_FUNC_ARG; +#ifdef WOLFSSL_ECIES_OLD *keysLen = *encKeySz + *ivSz + *digestSz; +#else + *keysLen = *encKeySz + *digestSz; +#endif return 0; } @@ -11210,16 +11227,29 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, { int ret = 0; word32 blockSz; +#ifndef WOLFSSL_ECIES_OLD + byte iv[ECC_MAX_IV_SIZE]; + word32 pubKeySz; +#endif word32 digestSz; ecEncCtx localCtx; #ifdef WOLFSSL_SMALL_STACK byte* sharedSecret; byte* keys; #else +#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033) byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ +#else + byte sharedSecret[ECC_MAXSIZE * 3 + 1]; /* Public key too */ +#endif byte keys[ECC_BUFSIZE]; /* max size */ #endif +#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033) word32 sharedSz = ECC_MAXSIZE; +#else + /* 'Uncompressed' byte | public key x | public key y | secret */ + word32 sharedSz = 1 + ECC_MAXSIZE * 3; +#endif int keysLen; int encKeySz; int ivSz; @@ -11242,6 +11272,10 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) return ret; +#ifndef WOLFSSL_ECIES_OLD + pubKeySz = 1 + wc_ecc_size(privKey) * 2; +#endif + if (ctx->protocol == REQ_RESP_SERVER) { offset = keysLen; keysLen *= 2; @@ -11264,35 +11298,66 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if ( (msgSz%blockSz) != 0) return BAD_PADDING_E; +#ifdef WOLFSSL_ECIES_OLD if (*outSz < (msgSz + digestSz)) return BUFFER_E; +#else + if (*outSz < (pubKeySz + msgSz + digestSz)) + return BUFFER_E; +#endif #ifdef ECC_TIMING_RESISTANT if (ctx->rng != NULL && privKey->rng == NULL) privKey->rng = ctx->rng; #endif +#ifndef WOLFSSL_ECIES_OLD + if (privKey->type == ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_make_pub_ex(privKey, NULL, privKey->rng); + if (ret != 0) + return ret; + } + ret = wc_ecc_export_x963(privKey, out, &pubKeySz); + if (ret != 0) + return ret; + out += pubKeySz; +#endif + #ifdef WOLFSSL_SMALL_STACK - sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + sharedSecret = (byte*)XMALLOC(sharedSz, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); if (sharedSecret == NULL) return MEMORY_E; - keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + keys = (byte*)XMALLOC(ECC_BUFSIZE, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); if (keys == NULL) { - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); return MEMORY_E; } #endif +#ifdef WOLFSSL_ECIES_ISO18033 + XMEMCPY(sharedSecret, out - pubKeySz, pubKeySz); + sharedSz -= pubKeySz; +#endif + do { #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); if (ret != 0) break; #endif + #ifndef WOLFSSL_ECIES_ISO18033 ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + #else + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret + pubKeySz, + &sharedSz); + #endif } while (ret == WC_PENDING_E); if (ret == 0) { + #ifdef WOLFSSL_ECIES_ISO18033 + /* KDF data is encoded public key and secret. */ + sharedSz += pubKeySz; + #endif switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, @@ -11307,15 +11372,22 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } if (ret == 0) { +#ifdef WOLFSSL_ECIES_OLD encKey = keys + offset; encIv = encKey + encKeySz; macKey = encKey + encKeySz + ivSz; +#else + XMEMSET(iv, 0, ivSz); + encKey = keys + offset; + encIv = iv; + macKey = encKey + encKeySz; +#endif switch (ctx->encAlgo) { case ecAES_128_CBC: { #ifdef WOLFSSL_SMALL_STACK - Aes *aes = (Aes *)XMALLOC(sizeof *aes, NULL, + Aes *aes = (Aes *)XMALLOC(sizeof *aes, ctx->heap, DYNAMIC_TYPE_AES); if (aes == NULL) { ret = MEMORY_E; @@ -11338,7 +11410,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, wc_AesFree(aes); } #ifdef WOLFSSL_SMALL_STACK - XFREE(aes, NULL, DYNAMIC_TYPE_AES); + XFREE(aes, ctx->heap, DYNAMIC_TYPE_AES); #endif if (ret != 0) break; @@ -11356,7 +11428,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecHMAC_SHA256: { #ifdef WOLFSSL_SMALL_STACK - Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, NULL, + Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, ctx->heap, DYNAMIC_TYPE_HMAC); if (hmac == NULL) { ret = MEMORY_E; @@ -11377,7 +11449,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, wc_HmacFree(hmac); } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC); + XFREE(hmac, ctx->heap, DYNAMIC_TYPE_HMAC); #endif } break; @@ -11388,12 +11460,17 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } } - if (ret == 0) + if (ret == 0) { +#ifdef WOLFSSL_ECIES_OLD *outSz = msgSz + digestSz; +#else + *outSz = pubKeySz + msgSz + digestSz; +#endif + } #ifdef WOLFSSL_SMALL_STACK - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); - XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); #endif return ret; @@ -11408,16 +11485,33 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, { int ret = 0; word32 blockSz; +#ifndef WOLFSSL_ECIES_OLD + byte iv[ECC_MAX_IV_SIZE]; + word32 pubKeySz; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* peerKey = NULL; +#else + ecc_key peerKey[1]; +#endif +#endif word32 digestSz; ecEncCtx localCtx; #ifdef WOLFSSL_SMALL_STACK byte* sharedSecret; byte* keys; #else +#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033) byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ +#else + byte sharedSecret[ECC_MAXSIZE * 3 + 1]; /* Public key too */ +#endif byte keys[ECC_BUFSIZE]; /* max size */ #endif +#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033) word32 sharedSz = ECC_MAXSIZE; +#else + word32 sharedSz = ECC_MAXSIZE * 3 + 1; +#endif int keysLen; int encKeySz; int ivSz; @@ -11426,9 +11520,13 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, byte* encIv; byte* macKey; - if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL || - outSz == NULL) + + if (privKey == NULL || msg == NULL || out == NULL || outSz == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ECIES_OLD + if (pubKey == NULL) + return BAD_FUNC_ARG; +#endif if (ctx == NULL) { /* use defaults */ ecc_ctx_init(&localCtx, 0, NULL); @@ -11440,6 +11538,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) return ret; +#ifndef WOLFSSL_ECIES_OLD + ret = ecc_public_key_size(privKey, &pubKeySz); + if (ret != 0) + return ret; +#endif + if (ctx->protocol == REQ_RESP_CLIENT) { offset = keysLen; keysLen *= 2; @@ -11459,11 +11563,21 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (keysLen > ECC_BUFSIZE) /* keys size */ return BUFFER_E; +#ifdef WOLFSSL_ECIES_OLD if ( ((msgSz-digestSz) % blockSz) != 0) return BAD_PADDING_E; if (*outSz < (msgSz - digestSz)) return BUFFER_E; +#else + if ( ((msgSz-digestSz-pubKeySz) % blockSz) != 0) + return BAD_PADDING_E; + + if (msgSz < pubKeySz + blockSz + digestSz) + return BAD_FUNC_ARG; + if (*outSz < (msgSz - digestSz - pubKeySz)) + return BUFFER_E; +#endif #ifdef ECC_TIMING_RESISTANT if (ctx->rng != NULL && privKey->rng == NULL) @@ -11471,26 +11585,76 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #endif #ifdef WOLFSSL_SMALL_STACK - sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); - if (sharedSecret == NULL) + sharedSecret = (byte*)XMALLOC(sharedSz, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); + if (sharedSecret == NULL) { + #ifndef WOLFSSL_ECIES_OLD + if (pubKey == peerKey) + wc_ecc_free(peerKey); + #endif return MEMORY_E; + } - keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + keys = (byte*)XMALLOC(ECC_BUFSIZE, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); if (keys == NULL) { - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); + #ifndef WOLFSSL_ECIES_OLD + if (pubKey == peerKey) + wc_ecc_free(peerKey); + #endif return MEMORY_E; } #endif - do { - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); - if (ret != 0) - break; - #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - } while (ret == WC_PENDING_E); +#ifndef WOLFSSL_ECIES_OLD + if (pubKey == NULL) { +#ifdef WOLFSSL_SMALL_STACK + peerKey = (ecc_key*)XMALLOC(sizeof(*peerKey), ctx->heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (peerKey == NULL) + ret = MEMORY_E; +#endif + pubKey = peerKey; + } if (ret == 0) { + ret = wc_ecc_init_ex(pubKey, privKey->heap, INVALID_DEVID); + } + if (ret == 0) { + ret = wc_ecc_import_x963_ex(msg, pubKeySz, pubKey, privKey->dp->id); + } + if (ret == 0) { + /* Point is not MACed. */ + msg += pubKeySz; + msgSz -= pubKeySz; + } +#endif + + if (ret == 0) { + #ifdef WOLFSSL_ECIES_ISO18033 + XMEMCPY(sharedSecret, msg - pubKeySz, pubKeySz); + sharedSz -= pubKeySz; + #endif + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + ret = wc_AsyncWait(ret, &privKey->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + #ifndef WOLFSSL_ECIES_ISO18033 + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, + &sharedSz); + #else + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret + + pubKeySz, &sharedSz); + #endif + } while (ret == WC_PENDING_E); + } + if (ret == 0) { + #ifdef WOLFSSL_ECIES_ISO18033 + /* KDF data is encoded public key and secret. */ + sharedSz += pubKeySz; + #endif switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, @@ -11505,16 +11669,24 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } if (ret == 0) { +#ifdef WOLFSSL_ECIES_OLD encKey = keys + offset; encIv = encKey + encKeySz; macKey = encKey + encKeySz + ivSz; +#else + XMEMSET(iv, 0, ivSz); + encKey = keys + offset; + encIv = iv; + macKey = encKey + encKeySz; +#endif switch (ctx->macAlgo) { case ecHMAC_SHA256: { byte verify[WC_SHA256_DIGEST_SIZE]; #ifdef WOLFSSL_SMALL_STACK - Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, NULL, DYNAMIC_TYPE_HMAC); + Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, ctx->heap, + DYNAMIC_TYPE_HMAC); if (hmac == NULL) { ret = MEMORY_E; break; @@ -11539,7 +11711,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, wc_HmacFree(hmac); } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC); + XFREE(hmac, ctx->heap, DYNAMIC_TYPE_HMAC); #endif break; } @@ -11556,7 +11728,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecAES_128_CBC: { #ifdef WOLFSSL_SMALL_STACK - Aes *aes = (Aes *)XMALLOC(sizeof *aes, NULL, + Aes *aes = (Aes *)XMALLOC(sizeof *aes, ctx->heap, DYNAMIC_TYPE_AES); if (aes == NULL) { ret = MEMORY_E; @@ -11580,7 +11752,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, wc_AesFree(aes); } #ifdef WOLFSSL_SMALL_STACK - XFREE(aes, NULL, DYNAMIC_TYPE_AES); + XFREE(aes, ctx->heap, DYNAMIC_TYPE_AES); #endif if (ret != 0) break; @@ -11596,9 +11768,18 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret == 0) *outSz = msgSz - digestSz; +#ifndef WOLFSSL_ECIES_OLD + if (pubKey == peerKey) + wc_ecc_free(peerKey); +#endif #ifdef WOLFSSL_SMALL_STACK - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); - XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#ifndef WOLFSSL_ECIES_OLD + if (peerKey != NULL) { + XFREE(peerKey, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); + } +#endif + XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER); #endif return ret; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 741b6bf0b..38375bdce 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -23891,19 +23891,228 @@ done: #if defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) +#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 +static int ecc_encrypt_kat(WC_RNG *rng) +{ + int ret = 0; +#ifdef WOLFSSL_ECIES_OLD +#ifdef WOLFSSL_SMALL_STACK + ecc_key* userA = NULL; +#else + ecc_key userA[1]; +#endif + int userAInit = 0; +#endif +#ifdef WOLFSSL_SMALL_STACK + ecc_key* userB = NULL; +#else + ecc_key userB[1]; +#endif + int userBInit = 0; + ecc_key* tmpKey; + byte plain[48]; + word32 plainSz = sizeof(plain); + + WOLFSSL_SMALL_STACK_STATIC const byte privKey[] = { + 0x04, 0x80, 0xef, 0x1d, 0xbe, 0x02, 0x0c, 0x20, + 0x5b, 0xab, 0x80, 0x35, 0x5b, 0x2a, 0x0f, 0x6d, + 0xd3, 0xb0, 0x7f, 0x7e, 0x7f, 0x86, 0x8a, 0x49, + 0xee, 0xb4, 0xaa, 0x09, 0x2d, 0x1e, 0x1d, 0x02 + }; +#ifdef WOLFSSL_ECIES_OLD + WOLFSSL_SMALL_STACK_STATIC const byte pubKey[] = { + 0x04, + /* X */ + 0x50, 0xf2, 0x93, 0xa2, 0x48, 0xa9, 0xc0, 0x5a, + 0x9a, 0xa7, 0x70, 0x34, 0xb7, 0x7f, 0x4c, 0x3a, + 0xad, 0xfc, 0xd8, 0xb6, 0x76, 0x0a, 0xe3, 0xc1, + 0x87, 0x17, 0x07, 0x2d, 0x8d, 0xa3, 0x63, 0xa0, + /* X */ + 0xc1, 0x27, 0xb2, 0x97, 0x9b, 0x84, 0xe7, 0xcd, + 0x20, 0x65, 0x8d, 0x2b, 0x6a, 0x93, 0x75, 0xaa, + 0x8b, 0xe1, 0x3a, 0x7b, 0x24, 0x1a, 0xbe, 0xe8, + 0x36, 0xd2, 0xe6, 0x34, 0x8a, 0x7a, 0xb3, 0x28 + }; +#endif + WOLFSSL_SMALL_STACK_STATIC const byte enc_msg[] = { +#ifdef WOLFSSL_ECIES_OLD + 0x42, 0x70, 0xbf, 0xf9, 0xf4, 0x7e, 0x4b, 0x9b, + 0xb5, 0x4c, 0xcc, 0xc5, 0x94, 0xa7, 0xef, 0xaa, + 0xc3, 0x7c, 0x85, 0xa6, 0x51, 0x6e, 0xd3, 0xfa, + 0x56, 0xc9, 0x10, 0x4d, 0x14, 0x32, 0x61, 0xb8, + 0xbb, 0x66, 0x7a, 0xb5, 0xbc, 0x95, 0xf8, 0xca, + 0xd1, 0x2a, 0x19, 0x51, 0x44, 0xd8, 0x0e, 0x57, + 0x34, 0xed, 0x45, 0x89, 0x2e, 0x57, 0xbe, 0xd5, + 0x06, 0x22, 0xd7, 0x13, 0x0a, 0x0e, 0x40, 0x36, + 0x0d, 0x05, 0x0d, 0xb6, 0xae, 0x61, 0x37, 0x18, + 0x83, 0x90, 0x0a, 0x27, 0x95, 0x41, 0x8c, 0x45 +#elif defined(WOLFSSL_ECIES_ISO18033) + 0x04, 0x50, 0xf2, 0x93, 0xa2, 0x48, 0xa9, 0xc0, + 0x5a, 0x9a, 0xa7, 0x70, 0x34, 0xb7, 0x7f, 0x4c, + 0x3a, 0xad, 0xfc, 0xd8, 0xb6, 0x76, 0x0a, 0xe3, + 0xc1, 0x87, 0x17, 0x07, 0x2d, 0x8d, 0xa3, 0x63, + 0xa0, 0xc1, 0x27, 0xb2, 0x97, 0x9b, 0x84, 0xe7, + 0xcd, 0x20, 0x65, 0x8d, 0x2b, 0x6a, 0x93, 0x75, + 0xaa, 0x8b, 0xe1, 0x3a, 0x7b, 0x24, 0x1a, 0xbe, + 0xe8, 0x36, 0xd2, 0xe6, 0x34, 0x8a, 0x7a, 0xb3, + 0x28, 0xbb, 0x9f, 0xa8, 0x2d, 0xe1, 0xf1, 0x67, + 0x45, 0x02, 0x19, 0xdc, 0xc8, 0x24, 0x8b, 0x20, + 0x02, 0xa0, 0x8f, 0x95, 0x12, 0x55, 0x51, 0xf8, + 0x03, 0xc4, 0x54, 0x13, 0x98, 0x2d, 0xf0, 0x31, + 0x51, 0x80, 0x45, 0x24, 0xcb, 0x8b, 0x48, 0xa6, + 0x8b, 0x8e, 0x97, 0x9c, 0x56, 0x4d, 0x70, 0x00, + 0x53, 0xd3, 0x47, 0x00, 0x5a, 0x23, 0x8c, 0xf9, + 0xfd, 0xd2, 0x33, 0x2c, 0x43, 0x6e, 0x9e, 0xb2, + 0xf4, 0x95, 0xd4, 0xcf, 0x30, 0xd6, 0xa2, 0xc5, + 0x35, 0x96, 0x6a, 0xd4, 0x36, 0x15, 0xa9, 0xbd, + 0x7f +#else + 0x04, 0x50, 0xf2, 0x93, 0xa2, 0x48, 0xa9, 0xc0, + 0x5a, 0x9a, 0xa7, 0x70, 0x34, 0xb7, 0x7f, 0x4c, + 0x3a, 0xad, 0xfc, 0xd8, 0xb6, 0x76, 0x0a, 0xe3, + 0xc1, 0x87, 0x17, 0x07, 0x2d, 0x8d, 0xa3, 0x63, + 0xa0, 0xc1, 0x27, 0xb2, 0x97, 0x9b, 0x84, 0xe7, + 0xcd, 0x20, 0x65, 0x8d, 0x2b, 0x6a, 0x93, 0x75, + 0xaa, 0x8b, 0xe1, 0x3a, 0x7b, 0x24, 0x1a, 0xbe, + 0xe8, 0x36, 0xd2, 0xe6, 0x34, 0x8a, 0x7a, 0xb3, + 0x28, 0xe5, 0x17, 0xaf, 0x0d, 0x65, 0x4d, 0x3d, + 0x50, 0x96, 0x05, 0xc9, 0x63, 0x2c, 0xef, 0x1c, + 0x1f, 0x78, 0xc9, 0x90, 0x7a, 0x14, 0x00, 0xfc, + 0x44, 0x71, 0x6d, 0x57, 0x8c, 0xdf, 0x23, 0xca, + 0x65, 0xcf, 0x93, 0x06, 0xb6, 0x9a, 0xf4, 0x61, + 0xbd, 0x44, 0x1a, 0xeb, 0x52, 0x68, 0x0f, 0xd1, + 0xde, 0xc7, 0x3f, 0x6f, 0xce, 0xbe, 0x49, 0x61, + 0x48, 0x01, 0x77, 0x41, 0xd0, 0xd8, 0x5b, 0x48, + 0xca, 0x4e, 0x47, 0x3e, 0x47, 0xbf, 0x1d, 0x28, + 0x4c, 0x18, 0x1a, 0xfb, 0x96, 0x95, 0xda, 0xde, + 0x55 +#endif + }; + WOLFSSL_SMALL_STACK_STATIC const byte msg[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f + }; + +#ifdef WOLFSSL_SMALL_STACK + userB = (ecc_key *)XMALLOC(sizeof(*userB), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (userB == NULL) { + ret = -10451; + } +#ifdef WOLFSSL_ECIES_OLD + if (ret == 0) { + userA = (ecc_key *)XMALLOC(sizeof(*userA), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (userA == NULL) { + ret = -10450; + } + } +#endif +#endif + + if (ret == 0) { + ret = wc_ecc_init_ex(userB, HEAP_HINT, devId); + if (ret != 0) + ret = -10453; + } + if (ret == 0) { + userBInit = 1; +#ifdef WOLFSSL_ECIES_OLD + ret = wc_ecc_init_ex(userA, HEAP_HINT, devId); + if (ret != 0) + ret = -10452; + } + if (ret == 0) { + userAInit = 1; + tmpKey = userA; +#else + tmpKey = NULL; +#endif + } + + + if (ret == 0) { + ret = wc_ecc_import_private_key_ex(privKey, sizeof(privKey), NULL, 0, + userB, ECC_SECP256R1); + if (ret != 0) + ret = -10454; + } + +#ifdef WOLFSSL_ECIES_OLD + if (ret == 0) { + ret = wc_ecc_import_x963_ex(pubKey, sizeof(pubKey), userA, + ECC_SECP256R1); + if (ret != 0) + ret = -10455; + } +#endif + +#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ + !defined(HAVE_SELFTEST) + if (ret == 0) { + ret = wc_ecc_set_rng(userB, rng); + if (ret != 0) { + ret = -10456; + } + } +#endif + + if (ret == 0) { + ret = wc_ecc_decrypt(userB, tmpKey, enc_msg, sizeof(enc_msg), plain, + &plainSz, NULL); + if (ret != 0) + ret = -10457; + } + if (ret == 0) { + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -10458; + } + } + + if (userBInit) + wc_ecc_free(userB); +#ifdef WOLFSSL_ECIES_OLD + if (userAInit) + wc_ecc_free(userA); +#endif +#ifdef WOLFSSL_SMALL_STACK + if (userB != NULL) { + XFREE(userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#ifdef WOLFSSL_ECIES_OLD + if (userA != NULL) { + XFREE(userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif +#endif + + return ret; +} +#endif + WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) { WC_RNG rng; int ret = 0; #ifdef WOLFSSL_SMALL_STACK ecc_key *userA = (ecc_key *)XMALLOC(sizeof *userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER), - *userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + *userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER), + *tmpKey = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #else - ecc_key userA[1], userB[1]; + ecc_key userA[1], userB[1], tmpKey[1]; #endif byte msg[48]; byte plain[48]; +#ifdef WOLFSSL_ECIES_OLD byte out[80]; +#else + byte out[1 + ECC_KEYGEN_SIZE * 2 + 80]; +#endif word32 outSz = sizeof(out); word32 plainSz = sizeof(plain); int i; @@ -23914,7 +24123,11 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) const byte* tmpSalt; byte msg2[48]; byte plain2[48]; +#ifdef WOLFSSL_ECIES_OLD byte out2[80]; +#else + byte out2[1 + ECC_KEYGEN_SIZE * 2 + 80]; +#endif word32 outSz2 = sizeof(out2); word32 plainSz2 = sizeof(plain2); @@ -23939,6 +24152,9 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) if (ret != 0) goto done; ret = wc_ecc_init_ex(userB, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(tmpKey, HEAP_HINT, devId); if (ret != 0) goto done; @@ -23981,8 +24197,16 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) ret = -10405; goto done; } +#ifdef WOLFSSL_ECIES_OLD + tmpKey->dp = userA->dp; + ret = wc_ecc_copy_point(&userA->pubkey, &tmpKey->pubkey); + if (ret != 0) { + ret = -10413; goto done; + } +#endif + /* decrypt msg from A */ - ret = wc_ecc_decrypt(userB, userA, out, outSz, plain, &plainSz, NULL); + ret = wc_ecc_decrypt(userB, tmpKey, out, outSz, plain, &plainSz, NULL); if (ret != 0) { ret = -10406; goto done; } @@ -23991,6 +24215,17 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) ret = -10407; goto done; } +#ifndef WOLFSSL_ECIES_OLD + /* A decrypts msg (response) from B */ + ret = wc_ecc_decrypt(userB, NULL, out, outSz, plain2, &plainSz2, NULL); + if (ret != 0) + goto done; + + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -10415; goto done; + } +#endif + /* let's verify message exchange works, A is client, B is server */ cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); @@ -24032,9 +24267,12 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) if (ret != 0) goto done; +#ifndef WOLFSSL_ECIES_OLD + wc_ecc_free(tmpKey); +#endif /* B decrypts msg (request) from A */ plainSz = sizeof(plain); - ret = wc_ecc_decrypt(userB, userA, out, outSz, plain, &plainSz, srvCtx); + ret = wc_ecc_decrypt(userB, tmpKey, out, outSz, plain, &plainSz, srvCtx); if (ret != 0) goto done; @@ -24052,8 +24290,18 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) if (ret != 0) goto done; +#ifdef WOLFSSL_ECIES_OLD + tmpKey->dp = userB->dp; + ret = wc_ecc_copy_point(&userB->pubkey, &tmpKey->pubkey); + if (ret != 0) { + ret = -10414; goto done; + } +#else + wc_ecc_free(tmpKey); +#endif + /* A decrypts msg (response) from B */ - ret = wc_ecc_decrypt(userA, userB, out2, outSz2, plain2, &plainSz2, + ret = wc_ecc_decrypt(userA, tmpKey, out2, outSz2, plain2, &plainSz2, cliCtx); if (ret != 0) goto done; @@ -24062,6 +24310,10 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) ret = -10412; goto done; } +#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 + ret = ecc_encrypt_kat(&rng); +#endif + done: /* cleanup */ @@ -24077,7 +24329,12 @@ done: wc_ecc_free(userB); XFREE(userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } + if (tmpKey != NULL) { + wc_ecc_free(tmpKey); + XFREE(tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } #else + wc_ecc_free(tmpKey); wc_ecc_free(userB); wc_ecc_free(userA); #endif @@ -24098,9 +24355,11 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) #ifdef WOLFSSL_SMALL_STACK ecc_key *cliKey = (ecc_key *)XMALLOC(sizeof *cliKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ecc_key *servKey = (ecc_key *)XMALLOC(sizeof *servKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + ecc_key *tmpKey = (ecc_key *)XMALLOC(sizeof *tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #else ecc_key cliKey[1]; ecc_key servKey[1]; + ecc_key tmpKey[1]; #endif WC_RNG rng; word32 idx = 0; @@ -24114,7 +24373,7 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) word32 x; #ifdef WOLFSSL_SMALL_STACK - if ((cliKey == NULL) || (servKey == NULL)) + if ((cliKey == NULL) || (servKey == NULL) || (tmpKey == NULL)) ERROR_OUT(MEMORY_E, done); #endif @@ -24122,6 +24381,9 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) if (ret != 0) ERROR_OUT(-10420, done); ret = wc_ecc_init_ex(servKey, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(-10421, done); + ret = wc_ecc_init_ex(tmpKey, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(-10421, done); @@ -24157,6 +24419,10 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) if (ret != 0) { ERROR_OUT(-10425, done); } + ret = wc_ecc_set_rng(servKey, &rng); + if (ret != 0) { + ERROR_OUT(-10425, done); + } #endif #endif /* !WC_NO_RNG */ @@ -24169,8 +24435,16 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) if (ret < 0) ERROR_OUT(-10426, done); + #ifdef WOLFSSL_ECIES_OLD + tmpKey->dp = cliKey->dp; + ret = wc_ecc_copy_point(&cliKey->pubkey, &tmpKey->pubkey); + if (ret != 0) { + ret = -10414; goto done; + } + #endif + y = sizeof(plain); - ret = wc_ecc_decrypt(cliKey, servKey, out, x, plain, &y, NULL); + ret = wc_ecc_decrypt(servKey, tmpKey, out, x, plain, &y, NULL); if (ret < 0) ERROR_OUT(-10427, done); @@ -24232,9 +24506,14 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) wc_ecc_free(servKey); XFREE(servKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } + if (tmpKey != NULL) { + wc_ecc_free(tmpKey); + XFREE(tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } #else wc_ecc_free(cliKey); wc_ecc_free(servKey); + wc_ecc_free(tmpKey); #endif wc_FreeRng(&rng); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index a0de8df6b..18c3a759a 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -722,8 +722,8 @@ WOLFSSL_API int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id); WOLFSSL_API -int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, - byte* d, int curve_id); +int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy, + const byte* d, int curve_id); #endif /* HAVE_ECC_KEY_IMPORT */ #ifdef HAVE_ECC_KEY_EXPORT @@ -803,6 +803,7 @@ enum { KEY_SIZE_256 = 32, IV_SIZE_64 = 8, IV_SIZE_128 = 16, + ECC_MAX_IV_SIZE = 16, EXCHANGE_SALT_SZ = 16, EXCHANGE_INFO_SZ = 23 };