diff --git a/.github/workflows/win-csharp-test.yml b/.github/workflows/win-csharp-test.yml new file mode 100644 index 0000000000..4ba24f9e93 --- /dev/null +++ b/.github/workflows/win-csharp-test.yml @@ -0,0 +1,57 @@ +name: Windows CSharp Build Test + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + + runs-on: windows-latest + + # This should be a safe limit for the tests to run. + timeout-minutes: 6 + + env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: wolfssl\wrapper\CSharp\wolfSSL_CSharp.sln + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: Debug + BUILD_PLATFORM: x64 + + steps: + - name: Pull wolfssl + uses: actions/checkout@master + with: + repository: wolfssl/wolfssl + path: wolfssl + + - name: Create FIPS stub files (autogen) + working-directory: wolfssl + run: | + echo $null >> wolfcrypt\src\fips.c + echo $null >> wolfcrypt\src\fips_test.c + echo $null >> wolfcrypt\src\wolfcrypt_first.c + echo $null >> wolfcrypt\src\wolfcrypt_last.c + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} + + - name: Run wolfCrypt test + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl\wrapper\CSharp\Debug\x64\ + run: ./wolfCrypt-test.exe + + - name: Run wolfSSL client/server example + working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl\wrapper\CSharp\Debug\x64\ + run: ./wolfSSL-TLS-Server.exe && sleep 1 & ./wolfSSL-TLS-Client.exe diff --git a/mcapi/crypto.h b/mcapi/crypto.h index dd95c1ca93..f11184916a 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -173,9 +173,9 @@ enum { typedef struct CRYPT_AES_CTX { /* big enough to hold internal, but check on init */ #ifdef WOLF_PRIVATE_KEY_ID - int holder[110]; + int holder[114]; #else - int holder[92]; + int holder[96]; #endif } CRYPT_AES_CTX; diff --git a/src/pk.c b/src/pk.c index e99ef80a06..1711b8c1eb 100644 --- a/src/pk.c +++ b/src/pk.c @@ -354,7 +354,7 @@ int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, int ret = 0; int paddingSz = 0; word32 idx; - word32 cipherInfoSz; + word32 cipherInfoSz = 0; #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -3300,7 +3300,7 @@ static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits, #endif int initTmpRng = 0; WC_RNG* rng = NULL; - long en; + long en = 0; #endif (void)cb; diff --git a/src/ssl.c b/src/ssl.c index 264f2c04ec..73c413ba06 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -16119,11 +16119,14 @@ long wolfSSL_set_options(WOLFSSL* ssl, long op) else { /* Only preserve overlapping suites */ Suites tmpSuites; - word16 in, out, haveECDSAsig = 0; - word16 haveStaticECC = ssl->options.haveStaticECC; + word16 in, out; + word16 haveECDSAsig, haveStaticECC; #ifdef NO_RSA haveECDSAsig = 1; haveStaticECC = 1; +#else + haveECDSAsig = 0; + haveStaticECC = ssl->options.haveStaticECC; #endif XMEMSET(&tmpSuites, 0, sizeof(Suites)); /* Get all possible ciphers and sigalgs for the version. Following @@ -21928,9 +21931,9 @@ int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names, #endif /* HAVE_SUPPORTED_CURVES */ } - if (ssl) + if (ssl != NULL) ssl->disabledCurves = disabled; - else + else if (ctx != NULL) ctx->disabledCurves = disabled; ret = WOLFSSL_SUCCESS; diff --git a/tests/api.c b/tests/api.c index 0e8ae3a811..09f3742dd5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27659,7 +27659,7 @@ static int test_wc_EccPrivateKeyToDer(void) byte output[ONEK_BUF]; ecc_key eccKey; WC_RNG rng; - word32 inLen; + word32 inLen = 0; word32 outLen = 0; int ret; @@ -27675,12 +27675,13 @@ static int test_wc_EccPrivateKeyToDer(void) #endif ExpectIntEQ(ret, 0); - inLen = (word32)sizeof(output); /* Bad Cases */ ExpectIntEQ(wc_EccPrivateKeyToDer(NULL, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_EccPrivateKeyToDer(NULL, output, inLen), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); - ExpectIntEQ(wc_EccPrivateKeyToDer(&eccKey, NULL, inLen), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); + inLen = wc_EccPrivateKeyToDer(&eccKey, NULL, 0); + ExpectIntGT(inLen, 0); ExpectIntEQ(wc_EccPrivateKeyToDer(&eccKey, output, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Good Case */ ExpectIntGT(outLen = (word32)wc_EccPrivateKeyToDer(&eccKey, output, inLen), 0); @@ -51708,7 +51709,7 @@ static int test_wolfSSL_ASN1_INTEGER(void) ASN1_INTEGER_free(a); a = NULL; - p = longDer; + p = invalidLenDer; ExpectNull(d2i_ASN1_INTEGER(NULL, &p, sizeof(invalidLenDer))); p = longDer; diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 4c9a8d1811..0e4fbe607b 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -10530,6 +10530,7 @@ int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, if (ret == 0) ret = wc_AesGcmEncrypt_ex(aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, authIn, authInSz); + aes->isAllocated = 0; wc_AesFree(aes); } ForceZero(aes, sizeof *aes); @@ -10571,6 +10572,8 @@ int wc_GmacVerify(const byte* key, word32 keySz, if (ret == 0) ret = wc_AesGcmDecrypt(aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, authIn, authInSz); + + aes->isAllocated = 0; wc_AesFree(aes); } ForceZero(aes, sizeof *aes); @@ -11287,6 +11290,20 @@ int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, #endif /* HAVE_AESCCM */ +Aes* wc_AesNew(void* heap, int devId) +{ + Aes* aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_AES); + if (aes != NULL) { + if (wc_AesInit(aes, heap, devId) != 0) { + XFREE(aes, heap, DYNAMIC_TYPE_AES); + aes = NULL; + } + else { + aes->isAllocated = 1; + } + } + return aes; +} /* Initialize Aes for use with async hardware */ int wc_AesInit(Aes* aes, void* heap, int devId) @@ -11296,6 +11313,7 @@ int wc_AesInit(Aes* aes, void* heap, int devId) if (aes == NULL) return BAD_FUNC_ARG; + aes->isAllocated = 0; aes->heap = heap; aes->rounds = 0; @@ -11421,8 +11439,13 @@ int wc_AesInit_Label(Aes* aes, const char* label, void* heap, int devId) /* Free Aes from use with async hardware */ void wc_AesFree(Aes* aes) { - if (aes == NULL) + unsigned int isAllocated; + + if (aes == NULL) { return; + } + + isAllocated = aes->isAllocated; #ifdef WC_DEBUG_CIPHER_LIFECYCLE (void)wc_debug_CipherLifecycleFree(&aes->CipherLifecycleTag, aes->heap, 1); @@ -11490,6 +11513,11 @@ void wc_AesFree(Aes* aes) #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Check(aes, sizeof(Aes)); #endif + + if (isAllocated) { + XFREE(aes, aes->heap, DYNAMIC_TYPE_AES); + } + } int wc_AesGetKeySize(Aes* aes, word32* keySize) @@ -14023,6 +14051,7 @@ static WARN_UNUSED_RESULT int AesSivCipher( } } + aes->isAllocated = 0; wc_AesFree(aes); #ifdef WOLFSSL_SMALL_STACK XFREE(aes, NULL, DYNAMIC_TYPE_AES); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bea4c89d0e..3868f7c732 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -22604,7 +22604,7 @@ static int DecodeCertReq(DecodedCert* cert, int* criticalExt) { DECL_ASNGETDATA(dataASN, certReqASN_Length); int ret = 0; - byte version; + byte version = 0; word32 idx; CALLOC_ASNGETDATA(dataASN, certReqASN_Length, ret, cert->heap); @@ -23497,7 +23497,7 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz, const unsigned char** pubKey, word32* pubKeySz) { int ret = 0; - int l; + int l = 0; word32 o = 0; int i; static DecodeInstr ops[] = { @@ -27761,7 +27761,7 @@ static int SetCertificatePolicies(byte *output, byte oid[MAX_OID_SZ]; word32 oidSz; word32 sz = 0; - int piSz; + int piSz = 0; if ((input == NULL) || (nb_certpol > MAX_CERTPOL_NB)) { ret = BAD_FUNC_ARG; @@ -30294,8 +30294,8 @@ int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, return (int)(idx + seqSz); #else DECL_ASNSETDATA(dataASN, sigASN_Length); - word32 seqSz; - int sz; + word32 seqSz = 0; + int sz = 0; int ret = 0; CALLOC_ASNSETDATA(dataASN, sigASN_Length, ret, NULL); @@ -34876,6 +34876,7 @@ int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, /* Write a Private ecc key, including public to DER format, * length on success else < 0 */ +/* Note: use wc_EccKeyDerSize to get length only */ WOLFSSL_ABI int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) { @@ -34887,10 +34888,7 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) int wc_EccKeyDerSize(ecc_key* key, int pub) { word32 sz = 0; - int ret; - - ret = wc_BuildEccKeyDer(key, NULL, &sz, pub, 1); - + int ret = wc_BuildEccKeyDer(key, NULL, &sz, pub, 1); if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } @@ -34901,7 +34899,11 @@ int wc_EccKeyDerSize(ecc_key* key, int pub) * length on success else < 0 */ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) { - return wc_BuildEccKeyDer(key, output, &inLen, 0, 1); + int ret = wc_BuildEccKeyDer(key, output, &inLen, 0, 1); + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { + return (int)inLen; + } + return ret; } #ifdef HAVE_PKCS8 @@ -35443,7 +35445,7 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0, sz; #else DECL_ASNSETDATA(dataASN, edKeyASN_Length); - int sz; + int sz = 0; #endif /* validate parameters */ diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index e24034222f..304fa3b95f 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -655,6 +655,22 @@ int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, #endif /* HAVE_CURVE25519_KEY_IMPORT */ +curve25519_key* wc_curve25519_new(void* heap, int devId) +{ + curve25519_key* key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), heap, + DYNAMIC_TYPE_CURVE25519); + if (key != NULL) { + if (wc_curve25519_init_ex(key, heap, devId) != 0) { + XFREE(key, heap, DYNAMIC_TYPE_CURVE25519); + key = NULL; + } + else { + key->isAllocated = 1; + } + } + return key; +} + int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId) { if (key == NULL) @@ -691,9 +707,15 @@ int wc_curve25519_init(curve25519_key* key) /* Clean the memory of a key */ void wc_curve25519_free(curve25519_key* key) { + int isAllocated = 0; + void* heap; + if (key == NULL) return; + isAllocated = key->isAllocated; + heap = key->heap; + #ifdef WOLFSSL_SE050 se050_curve25519_free_key(key); #endif @@ -703,9 +725,15 @@ void wc_curve25519_free(curve25519_key* key) XMEMSET(&key->p, 0, sizeof(key->p)); key->pubSet = 0; key->privSet = 0; + #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Check(key, sizeof(curve25519_key)); #endif + + if (isAllocated) { + XFREE(key, heap, DYNAMIC_TYPE_CURVE25519); + (void)heap; + } } /* get key size */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index ee031a6aa9..65af05cbfc 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4103,7 +4103,7 @@ static int wc_ecc_new_point_ex(ecc_point** point, void* heap) #ifndef WOLFSSL_NO_MALLOC XFREE(p, heap, DYNAMIC_TYPE_ECC); #endif - return err; + p = NULL; } #else p->x = (mp_int*)&p->xyz[0]; @@ -13908,16 +13908,26 @@ int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 sz) if (ctx == NULL || (salt == NULL && sz != 0)) return BAD_FUNC_ARG; - ctx->kdfSalt = salt; - ctx->kdfSaltSz = sz; + /* truncate salt if exceeds max */ + if (sz > EXCHANGE_SALT_SZ) + sz = EXCHANGE_SALT_SZ; + /* using a custom kdf salt, so borrow clientSalt/serverSalt for it, + * since wc_ecc_ctx_set_peer_salt will set kdf and mac salts */ if (ctx->protocol == REQ_RESP_CLIENT) { ctx->cliSt = ecCLI_SALT_SET; + ctx->kdfSalt = ctx->clientSalt; } else if (ctx->protocol == REQ_RESP_SERVER) { ctx->srvSt = ecSRV_SALT_SET; + ctx->kdfSalt = ctx->serverSalt; } + if (salt != NULL) { + XMEMCPY((byte*)ctx->kdfSalt, salt, sz); + } + ctx->kdfSaltSz = sz; + return 0; } @@ -14764,8 +14774,9 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret == 0) ret = wc_HmacFinal(hmac, verify); if ((ret == 0) && (XMEMCMP(verify, msg + msgSz - digestSz, - digestSz) != 0)) { - ret = -1; + digestSz) != 0)) { + ret = HASH_TYPE_E; + WOLFSSL_MSG("ECC Decrypt HMAC Check failed!"); } wc_HmacFree(hmac); diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 86f594dd79..363ecc4aae 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -968,6 +968,21 @@ int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, } #endif /* HAVE_ED25519_VERIFY */ +ed25519_key* wc_ed25519_new(void* heap, int devId) +{ + ed25519_key* key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, + DYNAMIC_TYPE_ED25519); + if (key != NULL) { + if (wc_ed25519_init_ex(key, heap, devId) != 0) { + XFREE(key, heap, DYNAMIC_TYPE_ED25519); + key = NULL; + } + else { + key->isAllocated = 1; + } + } + return key; +} /* initialize information and memory for key */ int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId) @@ -1008,9 +1023,15 @@ int wc_ed25519_init(ed25519_key* key) /* clear memory of key */ void wc_ed25519_free(ed25519_key* key) { + int isAllocated = 0; + void* heap; + if (key == NULL) return; + isAllocated = key->isAllocated; + heap = key->heap; + #ifdef WOLFSSL_ED25519_PERSISTENT_SHA ed25519_hash_free(key, &key->sha); #endif @@ -1023,6 +1044,11 @@ void wc_ed25519_free(ed25519_key* key) #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Check(key, sizeof(ed25519_key)); #endif + + if (isAllocated) { + XFREE(key, heap, DYNAMIC_TYPE_ED25519); + (void)heap; + } } diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index db3a047998..d5988341d7 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -686,6 +686,22 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, NULL, INVALID_DEVID); } +wc_HashAlg* wc_HashNew(enum wc_HashType type, void* heap, int devId) +{ + wc_HashAlg* hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap, + DYNAMIC_TYPE_HASHES); + if (hash != NULL) { + if (wc_HashInit_ex(hash, type, heap, devId) != 0) { + XFREE(hash, heap, DYNAMIC_TYPE_HASHES); + hash = NULL; + } + else { + hash->isAllocated = 1; + } + } + return hash; +} + int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap, int devId) { @@ -1008,43 +1024,53 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) { int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ + int isAllocated = 0; + void* heap = NULL; if (hash == NULL) return BAD_FUNC_ARG; + isAllocated = hash->isAllocated; + switch (type) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 + heap = hash->md5.heap; wc_Md5Free(&hash->md5); ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA + heap = hash->sha.heap; wc_ShaFree(&hash->sha); ret = 0; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 + heap = hash->sha224.heap; wc_Sha224Free(&hash->sha224); ret = 0; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 + heap = hash->sha256.heap; wc_Sha256Free(&hash->sha256); ret = 0; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 + heap = hash->sha384.heap; wc_Sha384Free(&hash->sha384); ret = 0; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 + heap = hash->sha512.heap; wc_Sha512Free(&hash->sha512); ret = 0; #endif @@ -1071,6 +1097,7 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) #endif case WC_HASH_TYPE_SHA3_224: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + heap = hash->sha3.heap; wc_Sha3_224_Free(&hash->sha3); ret = 0; #endif @@ -1096,6 +1123,7 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) #ifdef WOLFSSL_SM3 case WC_HASH_TYPE_SM3: + heap = hash->sm3.heap; wc_Sm3Free(&hash->sm3); ret = 0; break; @@ -1118,6 +1146,9 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) ret = BAD_FUNC_ARG; }; + if (isAllocated && heap) + XFREE(hash, heap, DYNAMIC_TYPE_HASHES); + return ret; } diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 1cb01bb476..29295716b5 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -154,9 +154,24 @@ static void wc_RsaCleanup(RsaKey* key) #endif } +RsaKey* wc_NewRsaKey(void* heap, int devId) +{ + RsaKey* key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); + if (key != NULL) { + if (wc_InitRsaKey_ex(key, heap, devId) != 0) { + XFREE(key, heap, DYNAMIC_TYPE_RSA); + key = NULL; + } + else { + key->isAllocated = 1; + } + } + return key; +} + int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) { - int ret = 0; + int ret = 0; if (key == NULL) { return BAD_FUNC_ARG; @@ -527,11 +542,16 @@ int wc_RsaGetKeyId(RsaKey* key, word32* keyId) int wc_FreeRsaKey(RsaKey* key) { int ret = 0; + int isAllocated = 0; + void* heap; if (key == NULL) { return BAD_FUNC_ARG; } + isAllocated = key->isAllocated; + heap = key->heap; + wc_RsaCleanup(key); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) @@ -595,6 +615,11 @@ int wc_FreeRsaKey(RsaKey* key) wc_fspsm_RsaKeyFree(key); #endif + if (isAllocated) { + XFREE(key, heap, DYNAMIC_TYPE_RSA); + (void)heap; + } + return ret; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ca8094ea13..7d32190818 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1953,7 +1953,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ else TEST_PASS("AES-SIV test passed!\n"); #endif -#endif +#endif /* !NO_AES */ #if defined(WOLFSSL_AES_EAX) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST) @@ -5873,7 +5873,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sm3_test(void) #ifndef NO_HASH_WRAPPER WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) { - wc_HashAlg hash; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + wc_HashAlg *hash = NULL; +#else + wc_HashAlg hash[1]; +#endif int ret, exp_ret; int i, j; int digestSz; @@ -5931,6 +5935,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) WOLFSSL_ENTER("hash_test"); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + hash = wc_HashNew(WC_HASH_TYPE_SHA256, HEAP_HINT, devId); + if (hash == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } + hash->isAllocated = 0; /* free manually */ +#else + XMEMSET(hash, 0, sizeof(wc_HashAlg)); +#endif + /* Parameter Validation testing. */ ret = wc_HashInit(NULL, WC_HASH_TYPE_SHA256); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) @@ -5938,7 +5953,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); - ret = wc_HashUpdate(&hash, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + ret = wc_HashUpdate(hash, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, data, sizeof(data)); @@ -5947,7 +5962,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, NULL); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); - ret = wc_HashFinal(&hash, WC_HASH_TYPE_SHA256, NULL); + ret = wc_HashFinal(hash, WC_HASH_TYPE_SHA256, NULL); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, out); @@ -5956,16 +5971,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) /* Try invalid hash algorithms. */ for (i = 0; i < (int)(sizeof(typesBad)/sizeof(*typesBad)); i++) { - ret = wc_HashInit(&hash, typesBad[i]); + ret = wc_HashInit(hash, typesBad[i]); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_I(i); - ret = wc_HashUpdate(&hash, typesBad[i], data, sizeof(data)); + ret = wc_HashUpdate(hash, typesBad[i], data, sizeof(data)); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_I(i); - ret = wc_HashFinal(&hash, typesBad[i], out); + ret = wc_HashFinal(hash, typesBad[i], out); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_I(i); - wc_HashFree(&hash, typesBad[i]); + wc_HashFree(hash, typesBad[i]); } /* Try valid hash algorithms. */ @@ -5976,16 +5991,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) exp_ret = HASH_TYPE_E; j++; } - ret = wc_HashInit(&hash, typesGood[i]); + ret = wc_HashInit(hash, typesGood[i]); if (ret != exp_ret) return WC_TEST_RET_ENC_I(i); - ret = wc_HashUpdate(&hash, typesGood[i], data, sizeof(data)); + ret = wc_HashUpdate(hash, typesGood[i], data, sizeof(data)); if (ret != exp_ret) return WC_TEST_RET_ENC_I(i); - ret = wc_HashFinal(&hash, typesGood[i], out); + ret = wc_HashFinal(hash, typesGood[i], out); if (ret != exp_ret) return WC_TEST_RET_ENC_I(i); - wc_HashFree(&hash, typesGood[i]); + wc_HashFree(hash, typesGood[i]); digestSz = wc_HashGetDigestSize(typesGood[i]); if (exp_ret < 0 && digestSz != exp_ret) @@ -6206,6 +6221,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hash_test(void) return WC_TEST_RET_ENC_EC(ret); #endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + hash->isAllocated = 1; /* free manually */ + (void)wc_HashFree(hash, WC_HASH_TYPE_NONE); +#endif + return 0; } #endif /* !NO_HASH_WRAPPER */ @@ -9168,18 +9188,28 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, WOLFSSL_ENTER("aesofb_test"); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(-1, out); -#ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(-1, out); -#endif -#endif - - XMEMSET(enc, 0, sizeof *enc); + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); #ifdef HAVE_AES_DECRYPT - XMEMSET(dec, 0, sizeof *dec); + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif + ret = wc_AesInit(enc, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + #ifdef HAVE_AES_DECRYPT + ret = wc_AesInit(dec, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ #ifdef WOLFSSL_AES_128 /* 128 key size test */ @@ -9192,16 +9222,6 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, } #endif - ret = wc_AesInit(enc, HEAP_HINT, INVALID_DEVID); - if (ret != 0) - ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - - #ifdef HAVE_AES_DECRYPT - ret = wc_AesInit(dec, HEAP_HINT, INVALID_DEVID); - if (ret != 0) - ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - #endif - ret = wc_AesSetKey(enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -9423,19 +9443,12 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif /* HAVE_AES_DECRYPT */ - out: + out: wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT wc_AesFree(dec); -#endif -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); -#ifdef HAVE_AES_DECRYPT - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif -#endif - + #endif #endif /* WOLFSSL_AES_256 */ return ret; @@ -9453,17 +9466,15 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE * 4]; - #ifdef HAVE_AES_DECRYPT -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) +#ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) Aes *dec = NULL; -#else + #else Aes dec[1]; -#endif - int dec_inited = 0; - byte plain [AES_BLOCK_SIZE * 4]; #endif + byte plain [AES_BLOCK_SIZE * 4]; +#endif wc_test_ret_t ret = 0; WOLFSSL_SMALL_STACK_STATIC const byte iv[] = { @@ -9569,26 +9580,28 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #endif /* WOLFSSL_AES_256 */ #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + #ifdef HAVE_AES_DECRYPT + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif -#endif - + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - enc_inited = 1; -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - dec_inited = 1; -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ #ifdef WOLFSSL_AES_128 /* 128 key tests */ @@ -9753,18 +9766,9 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, out: - if (enc_inited) - wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT - if (dec_inited) - wc_AesFree(dec); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); + wc_AesFree(enc); #ifdef HAVE_AES_DECRYPT - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif + wc_AesFree(dec); #endif return ret; @@ -9778,7 +9782,6 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE]; #ifdef HAVE_AES_DECRYPT #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -9786,7 +9789,6 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #else Aes dec[1]; #endif - int dec_inited = 0; byte plain [AES_BLOCK_SIZE]; #endif wc_test_ret_t ret = 0; @@ -9867,26 +9869,28 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #endif /* WOLFSSL_AES_256 */ #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); #ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); #endif -#endif - +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - enc_inited = 1; -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - dec_inited = 1; -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ #ifdef WOLFSSL_AES_128 /* 128 key tests */ @@ -10016,19 +10020,10 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, out: - if (enc_inited) wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT - if (dec_inited) + #ifdef HAVE_AES_DECRYPT wc_AesFree(dec); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); -#ifdef HAVE_AES_DECRYPT - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif -#endif + #endif return ret; } @@ -10040,7 +10035,6 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE]; #ifdef HAVE_AES_DECRYPT #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -10048,7 +10042,6 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #else Aes dec[1]; #endif - int dec_inited = 0; byte plain [AES_BLOCK_SIZE]; #endif wc_test_ret_t ret = 0; @@ -10126,26 +10119,28 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, #endif #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + #ifdef HAVE_AES_DECRYPT + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif -#endif - + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - enc_inited = 1; -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - dec_inited = 1; -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ #ifdef WOLFSSL_AES_128 /* 128 key tests */ @@ -10229,26 +10224,16 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, out: - if (enc_inited) - wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT - if (dec_inited) - wc_AesFree(dec); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); -#ifdef HAVE_AES_DECRYPT - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif -#endif + wc_AesFree(enc); + #ifdef HAVE_AES_DECRYPT + wc_AesFree(dec); + #endif return ret; } #endif /* !HAVE_SELFTEST && !HAVE_FIPS */ #endif /* WOLFSSL_AES_CFB */ - static wc_test_ret_t aes_key_size_test(void) { wc_test_ret_t ret; @@ -12709,19 +12694,17 @@ static wc_test_ret_t aesecb_test(void) wc_test_ret_t ret = 0; #if defined(WOLFSSL_AES_256) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - Aes *enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES); + Aes *enc = NULL; #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE * 4]; #ifdef HAVE_AES_DECRYPT #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - Aes *dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES); + Aes *dec = NULL; #else Aes dec[1]; #endif - int dec_inited = 0; byte plain[AES_BLOCK_SIZE * 4]; #endif /* HAVE_AES_DECRYPT */ @@ -12746,16 +12729,27 @@ static wc_test_ret_t aesecb_test(void) 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 }; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); + #ifdef HAVE_AES_DECRYPT + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + XMEMSET(dec, 0, sizeof(Aes)); ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - enc_inited = 1; - #if defined(HAVE_AES_DECRYPT) + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - dec_inited = 1; #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ XMEMSET(cipher, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(enc, niKey, sizeof(niKey), cipher, AES_ENCRYPTION); @@ -12846,28 +12840,10 @@ static wc_test_ret_t aesecb_test(void) #endif /* HAVE_AES_DECRYPT */ } - out: -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (enc) { - if (enc_inited) - wc_AesFree(enc); - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#ifdef HAVE_AES_DECRYPT - if (dec) { - if (dec_inited) - wc_AesFree(dec); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#endif -#else - if (enc_inited) + out: + wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT - if (dec_inited) wc_AesFree(dec); -#endif -#endif #endif /* WOLFSSL_AES_256 */ @@ -13648,19 +13624,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) { #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_DIRECT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - Aes *enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES); + Aes *enc = NULL; #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE * 4]; #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - Aes *dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES); + Aes *dec = NULL; #else Aes dec[1]; #endif - int dec_inited = 0; byte plain [AES_BLOCK_SIZE * 4]; #endif /* HAVE_AES_DECRYPT || WOLFSSL_AES_COUNTER */ #endif /* HAVE_AES_CBC || WOLFSSL_AES_COUNTER || WOLFSSL_AES_DIRECT */ @@ -13692,25 +13666,32 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \ defined(WOLFSSL_AES_DIRECT) + enc = wc_AesNew(HEAP_HINT, devId); if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); #endif #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) + dec = wc_AesNew(HEAP_HINT, devId); if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); #endif -#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ - +#else +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_DIRECT) + XMEMSET(enc, 0, sizeof(Aes)); + #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - enc_inited = 1; +#endif #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - dec_inited = 1; #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ #ifdef HAVE_AES_ECB ret = aes_ecb_test(enc, dec, cipher, plain); @@ -14111,31 +14092,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) out: #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_DIRECT) -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (enc) { - if (enc_inited) - wc_AesFree(enc); - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#else - if (enc_inited) - wc_AesFree(enc); + wc_AesFree(enc); #endif - (void)cipher; #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (dec) { - if (dec_inited) - wc_AesFree(dec); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#else - if (dec_inited) - wc_AesFree(dec); + wc_AesFree(dec); #endif - (void)plain; -#endif /* HAVE_AES_DECRYPT || WOLFSSL_AES_COUNTER */ -#endif /* HAVE_AES_CBC || WOLFSSL_AES_COUNTER || WOLFSSL_AES_DIRECT */ return ret; } @@ -14209,7 +14170,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void) #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE]; #ifdef HAVE_AES_DECRYPT #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -14219,9 +14179,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void) #endif byte plain[AES_BLOCK_SIZE]; #endif -#ifdef HAVE_AES_DECRYPT - int dec_inited = 0; -#endif /* Test vectors from NIST Special Publication 800-38A, 2001 Edition * Appendix F.2.3 */ @@ -14249,24 +14206,28 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void) WOLFSSL_ENTER("aes192_test"); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + #ifdef HAVE_AES_DECRYPT + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif -#endif - + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - enc_inited = 1; -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - dec_inited = 1; -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ ret = wc_AesSetKey(enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); if (ret != 0) @@ -14302,26 +14263,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void) #endif out: -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (enc) { - if (enc_inited) - wc_AesFree(enc); - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#ifdef HAVE_AES_DECRYPT - if (dec) { - if (dec_inited) - wc_AesFree(dec); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#endif -#else /* !WOLFSSL_SMALL_STACK || WOLFSSL_NO_MALLOC */ - if (enc_inited) - wc_AesFree(enc); + + wc_AesFree(enc); #ifdef HAVE_AES_DECRYPT - if (dec_inited) - wc_AesFree(dec); -#endif + wc_AesFree(dec); #endif #endif /* HAVE_AES_CBC */ @@ -14338,7 +14283,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) #else Aes enc[1]; #endif - int enc_inited = 0; byte cipher[AES_BLOCK_SIZE]; #ifdef HAVE_AES_DECRYPT #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -14346,7 +14290,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) #else Aes dec[1]; #endif - int dec_inited = 0; byte plain[AES_BLOCK_SIZE]; #endif #endif /* HAVE_AES_CBC */ @@ -14385,24 +14328,28 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) WOLFSSL_ENTER("aes256_test"); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#ifdef HAVE_AES_DECRYPT - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) + #ifdef HAVE_AES_DECRYPT + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif -#endif - + #endif +#else + XMEMSET(enc, 0, sizeof(Aes)); + #ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(Aes)); + #endif ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - enc_inited = 1; -#ifdef HAVE_AES_DECRYPT + #ifdef HAVE_AES_DECRYPT ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - dec_inited = 1; -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ ret = wc_AesSetKey(enc, key, (word32)keySz, iv, AES_ENCRYPTION); if (ret != 0) @@ -14516,27 +14463,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) out: -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (enc) { - if (enc_inited) - wc_AesFree(enc); - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - } + wc_AesFree(enc); #ifdef HAVE_AES_DECRYPT - if (dec) { - if (dec_inited) - wc_AesFree(dec); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); - } + wc_AesFree(dec); #endif -#else /* !WOLFSSL_SMALL_STACK || WOLFSSL_NO_MALLOC */ - if (enc_inited) - wc_AesFree(enc); -#ifdef HAVE_AES_DECRYPT - if (dec_inited) - wc_AesFree(dec); -#endif /* HAVE_AES_DECRYPT */ -#endif /* !WOLFSSL_SMALL_STACK || WOLFSSL_NO_MALLOC */ #endif /* HAVE_AES_CBC */ return ret; @@ -14552,7 +14482,6 @@ static wc_test_ret_t aesgcm_default_test_helper(byte* key, int keySz, byte* iv, byte* aad, int aadSz, byte* tag, int tagSz) { wc_test_ret_t ret; - int enc_inited = 0, dec_inited = 0; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) Aes *enc = NULL; Aes *dec = NULL; @@ -14565,27 +14494,27 @@ static wc_test_ret_t aesgcm_default_test_helper(byte* key, int keySz, byte* iv, byte resultP[AES_BLOCK_SIZE * 3]; byte resultC[AES_BLOCK_SIZE * 3]; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif - XMEMSET(resultT, 0, sizeof(resultT)); XMEMSET(resultC, 0, sizeof(resultC)); XMEMSET(resultP, 0, sizeof(resultP)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); +#else + XMEMSET(enc, 0, sizeof(Aes)); + XMEMSET(dec, 0, sizeof(Aes)); ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - enc_inited = 1; ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - else - dec_inited = 1; +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ ret = wc_AesGcmSetKey(enc, key, (word32)keySz); if (ret != 0) @@ -14663,23 +14592,8 @@ static wc_test_ret_t aesgcm_default_test_helper(byte* key, int keySz, byte* iv, out: -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if (enc) { - if (enc_inited) - wc_AesFree(enc); - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - } - if (dec) { - if (dec_inited) - wc_AesFree(dec); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); - } -#else /* !WOLFSSL_SMALL_STACK || WOLFSSL_NO_MALLOC */ - if (enc_inited) - wc_AesFree(enc); - if (dec_inited) - wc_AesFree(dec); -#endif + wc_AesFree(enc); + wc_AesFree(dec); return ret; } @@ -15007,23 +14921,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesgcm_test(void) #endif WOLFSSL_ENTER("aesgcm_test"); -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); - if ((dec = (Aes *)XMALLOC(sizeof *dec, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); -#endif - XMEMSET(resultT, 0, sizeof(resultT)); XMEMSET(resultC, 0, sizeof(resultC)); XMEMSET(resultP, 0, sizeof(resultP)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); + dec = wc_AesNew(HEAP_HINT, devId); + if (dec == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); +#else ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); ret = wc_AesInit(dec, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); +#endif #ifdef WOLFSSL_AES_256 ret = wc_AesGcmSetKey(enc, k1, (word32)k1Sz); @@ -15597,9 +15513,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesgcm_test(void) #endif /* WOLFSSL_AES_256 */ #endif /* !WOLFSSL_AFALG_XILINX_AES && !WOLFSSL_XILINX_CRYPT */ - wc_AesFree(enc); - wc_AesFree(dec); - ret = 0; out: @@ -15611,11 +15524,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesgcm_test(void) XFREE(large_outdec, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); - XFREE(dec, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif + wc_AesFree(enc); + wc_AesFree(dec); return ret; } @@ -15945,19 +15855,20 @@ static wc_test_ret_t aesccm_128_test(void) byte tl2[sizeof(tl)]; byte t_empty2[sizeof(t_empty)]; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((enc = (Aes *)XMALLOC(sizeof *enc, HEAP_HINT, DYNAMIC_TYPE_AES)) == NULL) - return WC_TEST_RET_ENC_ERRNO; -#endif - - XMEMSET(enc, 0, sizeof *enc); /* clear context */ XMEMSET(t2, 0, sizeof(t2)); XMEMSET(c2, 0, sizeof(c2)); XMEMSET(p2, 0, sizeof(p2)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + enc = wc_AesNew(HEAP_HINT, devId); + if (enc == NULL) + return WC_TEST_RET_ENC_ERRNO; +#else + XMEMSET(enc, 0, sizeof(Aes)); ret = wc_AesInit(enc, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); +#endif /* WOLFSSL_SMALL_STACK && !WOLFSSL_NO_MALLOC */ ret = wc_AesCcmSetKey(enc, k, sizeof(k)); if (ret != 0) @@ -15994,7 +15905,6 @@ static wc_test_ret_t aesccm_128_test(void) if (XMEMCMP(p2, c2, sizeof(p2))) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif - wc_AesFree(enc); XMEMSET(enc, 0, sizeof(Aes)); /* clear context */ XMEMSET(t2, 0, sizeof(t2)); @@ -16123,14 +16033,11 @@ static wc_test_ret_t aesccm_128_test(void) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); #endif - wc_AesFree(enc); - ret = 0; out: -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - XFREE(enc, HEAP_HINT, DYNAMIC_TYPE_AES); -#endif + + wc_AesFree(enc); return ret; } @@ -16517,8 +16424,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aeskeywrap_test(void) } #endif /* HAVE_AES_KEYWRAP */ +#endif /* !NO_AES */ -#endif /* NO_AES */ #ifdef HAVE_ARIA void printOutput(const char *strName, unsigned char *data, unsigned int dataSz) @@ -21439,14 +21346,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) byte* tmp = NULL; byte* der = NULL; - RsaKey *key = (RsaKey *)XMALLOC(sizeof *key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + RsaKey *key = NULL; #else RsaKey key[1]; byte tmp[FOURK_BUF]; #endif #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - RsaKey *keypub = (RsaKey *)XMALLOC(sizeof *keypub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + RsaKey *keypub = NULL; #else RsaKey keypub[1]; #endif @@ -21489,6 +21396,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) WC_ALLOC_VAR(in, byte, TEST_STRING_SZ, HEAP_HINT); WC_ALLOC_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); WC_ALLOC_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT); + WOLFSSL_ENTER("rsa_test"); #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC @@ -21499,9 +21407,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) XMEMCPY(in, inStr, inLen); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + key = wc_NewRsaKey(HEAP_HINT, devId); if (key == NULL) ERROR_OUT(MEMORY_E, exit_rsa); #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) + keypub = wc_NewRsaKey(HEAP_HINT, devId); if (keypub == NULL) ERROR_OUT(MEMORY_E, exit_rsa); #endif @@ -21513,9 +21423,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) /* initialize stack structures */ XMEMSET(&rng, 0, sizeof(rng)); - XMEMSET(key, 0, sizeof *key); + /* memset also clears isAllocated bit, so free must be called manually */ + XMEMSET(key, 0, sizeof(RsaKey)); #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) - XMEMSET(keypub, 0, sizeof *keypub); + XMEMSET(keypub, 0, sizeof(RsaKey)); #endif #if !defined(NO_ASN) @@ -22069,12 +21980,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) if (key != NULL) { wc_FreeRsaKey(key); - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_RSA); } #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) if (keypub != NULL) { wc_FreeRsaKey(keypub); - XFREE(keypub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keypub, HEAP_HINT, DYNAMIC_TYPE_RSA); } #endif #ifdef WOLFSSL_TEST_CERT @@ -24542,8 +24453,8 @@ static wc_test_ret_t openssl_aes_test(void) return 0; } +#endif /* !NO_AES && !WOLFCRYPT_ONLY */ -#endif /* !defined(NO_AES) && !defined(WOLFCRYPT_ONLY) */ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) { @@ -25757,7 +25668,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) #endif } #endif /* WOLFSSL_AES_128 && HAVE_AES_CBC */ -#endif /* ifndef NO_AES */ +#endif /* !NO_AES && !WOLFCRYPT_ONLY */ return 0; } @@ -33589,6 +33500,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void) (defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_256)) #if ((! defined(HAVE_FIPS)) || FIPS_VERSION_GE(5,3)) +/* maximum encrypted message: + * msgSz (14) + pad (2) + pubKeySz(1+66*2) + ivSz(16) + digestSz(32) = 197 */ +#define MAX_ECIES_TEST_SZ 200 static wc_test_ret_t ecc_ctx_kdf_salt_test(WC_RNG* rng, ecc_key* a, ecc_key* b) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -33596,9 +33510,9 @@ static wc_test_ret_t ecc_ctx_kdf_salt_test(WC_RNG* rng, ecc_key* a, ecc_key* b) byte* encrypted; byte* decrypted; #else - byte plaintext[128]; - byte encrypted[128]; - byte decrypted[128]; + byte plaintext[MAX_ECIES_TEST_SZ]; + byte encrypted[MAX_ECIES_TEST_SZ]; + byte decrypted[MAX_ECIES_TEST_SZ]; #endif ecEncCtx* aCtx = NULL; ecEncCtx* bCtx = NULL; @@ -33607,13 +33521,13 @@ static wc_test_ret_t ecc_ctx_kdf_salt_test(WC_RNG* rng, ecc_key* a, ecc_key* b) wc_test_ret_t ret = 0; static const char message[] = "Hello wolfSSL!"; word32 plaintextLen; - word32 encryptLen = 128; - word32 decryptLen = 128; + word32 encryptLen = MAX_ECIES_TEST_SZ; + word32 decryptLen = MAX_ECIES_TEST_SZ; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - plaintext = XMALLOC(128, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - encrypted = XMALLOC(128, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - decrypted = XMALLOC(128, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + plaintext = XMALLOC(MAX_ECIES_TEST_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + encrypted = XMALLOC(MAX_ECIES_TEST_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + decrypted = XMALLOC(MAX_ECIES_TEST_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif wc_ecc_free(a); @@ -33662,7 +33576,7 @@ static wc_test_ret_t ecc_ctx_kdf_salt_test(WC_RNG* rng, ecc_key* a, ecc_key* b) ret = 10473; } - XMEMSET(plaintext, 0, 128); + XMEMSET(plaintext, 0, MAX_ECIES_TEST_SZ); XSTRLCPY((char *)plaintext, message, sizeof plaintext); plaintextLen = (((word32)XSTRLEN(message) + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; @@ -34917,7 +34831,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) byte exportBuf[32]; #endif word32 x = 0; - curve25519_key userA, userB, pubKey; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + curve25519_key *userA = NULL, *userB = NULL, *pubKey = NULL; +#else + curve25519_key userA[1], userB[1], pubKey[1]; +#endif #if defined(HAVE_CURVE25519_SHARED_SECRET) && \ defined(HAVE_CURVE25519_KEY_IMPORT) @@ -34977,29 +34895,39 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - wc_curve25519_init_ex(&userA, HEAP_HINT, devId); - wc_curve25519_init_ex(&userB, HEAP_HINT, devId); - wc_curve25519_init_ex(&pubKey, HEAP_HINT, devId); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + userA = wc_curve25519_new(HEAP_HINT, devId); + userB = wc_curve25519_new(HEAP_HINT, devId); + pubKey = wc_curve25519_new(HEAP_HINT, devId); + if (userA == NULL || userB == NULL || pubKey == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } +#else + wc_curve25519_init_ex(userA, HEAP_HINT, devId); + wc_curve25519_init_ex(userB, HEAP_HINT, devId); + wc_curve25519_init_ex(pubKey, HEAP_HINT, devId); +#endif /* make curve25519 keys */ - ret = wc_curve25519_make_key(&rng, 32, &userA); + ret = wc_curve25519_make_key(&rng, 32, userA); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = wc_curve25519_make_key(&rng, 32, &userB); + ret = wc_curve25519_make_key(&rng, 32, userB); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); #ifdef HAVE_CURVE25519_SHARED_SECRET /* find shared secret key */ x = sizeof(sharedA); - if ((ret = wc_curve25519_shared_secret(&userA, &userB, sharedA, &x)) != 0) { + if ((ret = wc_curve25519_shared_secret(userA, userB, sharedA, &x)) != 0) { printf("wc_curve25519_shared_secret 1 failed\n"); return WC_TEST_RET_ENC_EC(ret); } y = sizeof(sharedB); - if ((ret = wc_curve25519_shared_secret(&userB, &userA, sharedB, &y)) != 0) { + if ((ret = wc_curve25519_shared_secret(userB, userA, sharedB, &y)) != 0) { printf("wc_curve25519_shared_secret 2 failed\n"); return WC_TEST_RET_ENC_EC(ret); } @@ -35015,12 +34943,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) #ifdef HAVE_CURVE25519_KEY_EXPORT /* export a public key and import it for another user */ x = sizeof(exportBuf); - ret = wc_curve25519_export_public(&userA, exportBuf, &x); + ret = wc_curve25519_export_public(userA, exportBuf, &x); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); #ifdef HAVE_CURVE25519_KEY_IMPORT - ret = wc_curve25519_import_public(exportBuf, x, &pubKey); + ret = wc_curve25519_import_public(exportBuf, x, pubKey); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); #endif @@ -35031,7 +34959,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) /* test shared key after importing a public key */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); - if (wc_curve25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0) { + if (wc_curve25519_shared_secret(userB, pubKey, sharedB, &y) != 0) { return WC_TEST_RET_ENC_NC; } @@ -35040,19 +34968,19 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) /* import RFC test vectors and compare shared key */ ret = wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), - &userA); + userA); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); ret = wc_curve25519_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), - &userB); + userB); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); /* test against known test vector */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); - ret = wc_curve25519_shared_secret(&userA, &userB, sharedB, &y); + ret = wc_curve25519_shared_secret(userA, userB, sharedB, &y); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -35062,7 +34990,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) /* test swapping roles of keys and generating same shared key */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); - ret = wc_curve25519_shared_secret(&userB, &userA, sharedB, &y); + ret = wc_curve25519_shared_secret(userB, userA, sharedB, &y); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -35071,24 +34999,32 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) /* test with 1 generated key and 1 from known test vector */ ret = wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), - &userA); + userA); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - wc_curve25519_free(&userB); - wc_curve25519_init_ex(&userB, HEAP_HINT, devId); + wc_curve25519_free(userB); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + userB = wc_curve25519_new(HEAP_HINT, devId); + if (userB == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } +#else + wc_curve25519_init_ex(userB, HEAP_HINT, devId); +#endif - ret = wc_curve25519_make_key(&rng, 32, &userB); + ret = wc_curve25519_make_key(&rng, 32, userB); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); x = sizeof(sharedA); - ret = wc_curve25519_shared_secret(&userA, &userB, sharedA, &x); + ret = wc_curve25519_shared_secret(userA, userB, sharedA, &x); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); y = sizeof(sharedB); - ret = wc_curve25519_shared_secret(&userB, &userA, sharedB, &y); + ret = wc_curve25519_shared_secret(userB, userA, sharedB, &y); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -35115,9 +35051,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) #endif /* clean up keys when done */ - wc_curve25519_free(&pubKey); - wc_curve25519_free(&userB); - wc_curve25519_free(&userA); + wc_curve25519_free(pubKey); + wc_curve25519_free(userB); + wc_curve25519_free(userA); wc_FreeRng(&rng); @@ -35640,8 +35576,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ word32 keySz, sigSz; - ed25519_key key; - ed25519_key key2; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + ed25519_key* key = NULL; + ed25519_key* key2 = NULL; +#else + ed25519_key key[1]; + ed25519_key key2[1]; +#endif + #if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \ defined(HAVE_ED25519_KEY_IMPORT) @@ -36022,8 +35965,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) #endif /* NO_ASN */ #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ #if !defined(NO_ASN) && defined(HAVE_ED25519_SIGN) - ed25519_key key3; + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + ed25519_key* key3 = NULL; + #else + ed25519_key key3[1]; + #endif #endif + WOLFSSL_ENTER("ed25519_test"); /* create ed25519 keys */ @@ -36035,19 +35983,36 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - wc_ed25519_init_ex(&key, HEAP_HINT, devId); - wc_ed25519_init_ex(&key2, HEAP_HINT, devId); -#if !defined(NO_ASN) && defined(HAVE_ED25519_SIGN) - wc_ed25519_init_ex(&key3, HEAP_HINT, devId); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + key = wc_ed25519_new(HEAP_HINT, devId); + key2 = wc_ed25519_new(HEAP_HINT, devId); + if (key == NULL || key2 == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } + #if !defined(NO_ASN) && defined(HAVE_ED25519_SIGN) + key3 = wc_ed25519_new(HEAP_HINT, devId); + if (key3 == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } + #endif +#else + wc_ed25519_init_ex(key, HEAP_HINT, devId); + wc_ed25519_init_ex(key2, HEAP_HINT, devId); + #if !defined(NO_ASN) && defined(HAVE_ED25519_SIGN) + wc_ed25519_init_ex(key3, HEAP_HINT, devId); + #endif #endif + #ifdef HAVE_ED25519_MAKE_KEY - wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); - wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key2); + wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, key); + wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, key2); #endif /* helper functions for signature and key size */ - keySz = (word32)wc_ed25519_size(&key); - sigSz = (word32)wc_ed25519_sig_size(&key); + keySz = (word32)wc_ed25519_size(key); + sigSz = (word32)wc_ed25519_sig_size(key); #if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) &&\ defined(HAVE_ED25519_KEY_IMPORT) @@ -36056,10 +36021,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) XMEMSET(out, 0, sizeof(out)); if (wc_ed25519_import_private_key(sKeys[i], ED25519_KEY_SIZE, pKeys[i], - pKeySz[i], &key) != 0) + pKeySz[i], key) != 0) return WC_TEST_RET_ENC_I(i); - if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) != 0) + if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, key) != 0) return WC_TEST_RET_ENC_I(i); if (XMEMCMP(out, sigs[i], 64)) @@ -36068,55 +36033,55 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) #if defined(HAVE_ED25519_VERIFY) /* test verify on good msg */ if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, - &key) != 0 || verify != 1) + key) != 0 || verify != 1) return WC_TEST_RET_ENC_I(i); #ifdef WOLFSSL_ED25519_STREAMING_VERIFY /* test verify on good msg using streaming interface directly */ if (wc_ed25519_verify_msg_init(out, outlen, - &key, (byte)Ed25519, NULL, 0) != 0) + key, (byte)Ed25519, NULL, 0) != 0) return WC_TEST_RET_ENC_I(i); for (j = 0; j < msgSz[i]; j += i) { - if (wc_ed25519_verify_msg_update(msgs[i] + j, MIN(i, msgSz[i] - j), &key) != 0) + if (wc_ed25519_verify_msg_update(msgs[i] + j, MIN(i, msgSz[i] - j), key) != 0) return WC_TEST_RET_ENC_I(i); } if (wc_ed25519_verify_msg_final(out, outlen, &verify, - &key) != 0 || verify != 1) + key) != 0 || verify != 1) return WC_TEST_RET_ENC_I(i); #endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ /* test verify on bad msg */ out[outlen-1] = out[outlen-1] + 1; if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, - &key) == 0 || verify == 1) + key) == 0 || verify == 1) return WC_TEST_RET_ENC_I(i); #endif /* HAVE_ED25519_VERIFY */ /* test api for import/exporting keys */ exportPSz = sizeof(exportPKey); exportSSz = sizeof(exportSKey); - if (wc_ed25519_export_public(&key, exportPKey, &exportPSz) != 0) + if (wc_ed25519_export_public(key, exportPKey, &exportPSz) != 0) return WC_TEST_RET_ENC_I(i); - if (wc_ed25519_import_public_ex(exportPKey, exportPSz, &key2, 1) != 0) + if (wc_ed25519_import_public_ex(exportPKey, exportPSz, key2, 1) != 0) return WC_TEST_RET_ENC_I(i); - if (wc_ed25519_export_private_only(&key, exportSKey, &exportSSz) != 0) + if (wc_ed25519_export_private_only(key, exportSKey, &exportSSz) != 0) return WC_TEST_RET_ENC_I(i); if (wc_ed25519_import_private_key(exportSKey, exportSSz, - exportPKey, exportPSz, &key2) != 0) + exportPKey, exportPSz, key2) != 0) return WC_TEST_RET_ENC_I(i); /* clear "out" buffer and test sign with imported keys */ outlen = sizeof(out); XMEMSET(out, 0, sizeof(out)); - if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key2) != 0) + if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, key2) != 0) return WC_TEST_RET_ENC_I(i); #if defined(HAVE_ED25519_VERIFY) if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, - &key2) != 0 || verify != 1) + key2) != 0 || verify != 1) return WC_TEST_RET_ENC_I(i); if (XMEMCMP(out, sigs[i], 64)) @@ -36172,27 +36137,27 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) }; ret = wc_ed25519_import_private_key(sKeys[0], ED25519_KEY_SIZE, - pKeys[0], pKeySz[0], &key); + pKeys[0], pKeySz[0], key); if (ret != 0) return ret; ret = wc_ed25519_verify_msg(rareEd1, sizeof(rareEd1), msgs[0], msgSz[0], - &verify, &key); + &verify, key); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return ret; ret = wc_ed25519_verify_msg(rareEd2, sizeof(rareEd2), msgs[0], msgSz[0], - &verify, &key); + &verify, key); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return ret; ret = wc_ed25519_verify_msg(rareEd3, sizeof(rareEd3), msgs[0], msgSz[0], - &verify, &key); + &verify, key); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return ret; ret = wc_ed25519_verify_msg(rareEd4, sizeof(rareEd4), msgs[0], msgSz[0], - &verify, &key); + &verify, key); if (ret != WC_NO_ERR_TRACE(SIG_VERIFY_E)) return ret; } @@ -36208,33 +36173,33 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) #ifndef NO_ASN /* Try ASN.1 encoded private-only key and public key. */ idx = 0; - ret = wc_Ed25519PrivateKeyDecode(privateEd25519, &idx, &key3, + ret = wc_Ed25519PrivateKeyDecode(privateEd25519, &idx, key3, sizeof(privateEd25519)); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); idx = 0; - if (wc_Ed25519PrivateKeyDecode(badPrivateEd25519, &idx, &key3, + if (wc_Ed25519PrivateKeyDecode(badPrivateEd25519, &idx, key3, sizeof(badPrivateEd25519)) == 0) return WC_TEST_RET_ENC_NC; - ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3); + ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, key3); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); /* try with a buffer size that is too large */ idx = 0; - if (wc_Ed25519PublicKeyDecode(badPublicEd25519, &idx, &key3, + if (wc_Ed25519PublicKeyDecode(badPublicEd25519, &idx, key3, sizeof(badPublicEd25519)) == 0) return WC_TEST_RET_ENC_NC; idx = 0; - ret = wc_Ed25519PublicKeyDecode(publicEd25519, &idx, &key3, + ret = wc_Ed25519PublicKeyDecode(publicEd25519, &idx, key3, sizeof(publicEd25519)); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3); + ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, key3); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -36243,35 +36208,43 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) #if defined(HAVE_ED25519_VERIFY) /* test verify on good msg */ - ret = wc_ed25519_verify_msg(out, outlen, msgs[0], msgSz[0], &verify, &key3); + ret = wc_ed25519_verify_msg(out, outlen, msgs[0], msgSz[0], &verify, key3); if (ret != 0 || verify != 1) return WC_TEST_RET_ENC_EC(ret); #endif /* HAVE_ED25519_VERIFY */ - wc_ed25519_free(&key3); - wc_ed25519_init(&key3); + wc_ed25519_free(key3); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + key3 = wc_ed25519_new(HEAP_HINT, devId); + if (key3 == NULL) { + ret = MEMORY_E; + return WC_TEST_RET_ENC_EC(ret); + } +#else + wc_ed25519_init_ex(key3, HEAP_HINT, devId); +#endif idx = 0; - ret = wc_Ed25519PrivateKeyDecode(privPubEd25519, &idx, &key3, + ret = wc_Ed25519PrivateKeyDecode(privPubEd25519, &idx, key3, sizeof(privPubEd25519)); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3); + ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, key3); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); if (XMEMCMP(out, sigs[0], 64)) return WC_TEST_RET_ENC_NC; - wc_ed25519_free(&key3); + wc_ed25519_free(key3); #endif /* NO_ASN */ #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ /* clean up keys when done */ - wc_ed25519_free(&key); - wc_ed25519_free(&key2); + wc_ed25519_free(key); + wc_ed25519_free(key2); #if defined(HAVE_HASHDRBG) || defined(NO_RC4) wc_FreeRng(&rng); @@ -48879,7 +48852,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cmac_test(void) return ret; } -#endif /* NO_AES && WOLFSSL_CMAC */ +#endif /* !NO_AES && WOLFSSL_CMAC */ #if defined(WOLFSSL_SIPHASH) @@ -50137,7 +50110,7 @@ static wc_test_ret_t pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, byte optionalUkm[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; -#endif /* NO_AES */ +#endif /* !NO_AES */ #if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) && \ !defined(NO_SHA) @@ -50770,7 +50743,7 @@ static wc_test_ret_t pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCer WOLFSSL_SMALL_STACK_STATIC const byte optionalUkm[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; -#endif /* NO_AES */ +#endif /* !NO_AES */ #if !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) /* encryption key for kekri recipient types */ @@ -50869,12 +50842,12 @@ static wc_test_ret_t pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCer NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_IANDS.der"); #endif - #else /* NO_AES || !HAVE_AESGCM */ + #else (void)rsaCert; (void)rsaCertSz; (void)rsaPrivKey; (void)rsaPrivKeySz; - #endif /* NO_AES || !HAVE_AESGCM */ + #endif /* !NO_AES && !HAVE_AESGCM */ #endif /* key agreement key encryption technique*/ @@ -50956,7 +50929,7 @@ static wc_test_ret_t pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCer 0, 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der"); #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ - #endif /* NO_AES */ + #endif /* !NO_AES && HAVE_AESGCM */ #endif /* kekri (KEKRecipientInfo) recipient types */ diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index cf08ec3a5c..b52817d224 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -392,6 +392,7 @@ struct Aes { byte nonceSet:1; byte ctrSet:1; #endif + byte isAllocated:1; /* flag indicates if structure was allocated */ #ifdef WC_DEBUG_CIPHER_LIFECYCLE void *CipherLifecycleTag; /* used for dummy allocation and initialization, * trackable by sanitizers. @@ -725,6 +726,7 @@ WOLFSSL_API int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, WOLFSSL_API int wc_AesInit_Label(Aes* aes, const char* label, void* heap, int devId); #endif +WOLFSSL_API Aes* wc_AesNew(void* heap, int devId); WOLFSSL_API void wc_AesFree(Aes* aes); #ifdef WOLFSSL_AES_SIV diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index 4d6d90da45..2d4d85173f 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -90,7 +90,7 @@ struct curve25519_key { void* devCtx; int devId; #endif - + void *heap; #ifdef WOLFSSL_SE050 word32 keyId; byte keyIdSet; @@ -99,6 +99,8 @@ struct curve25519_key { /* bit fields */ byte pubSet:1; byte privSet:1; + + unsigned int isAllocated:1; /* flag indicates if structure was allocated */ }; enum { @@ -131,6 +133,8 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, curve25519_key* public_key, byte* out, word32* outlen, int endian); +WOLFSSL_API +curve25519_key* wc_curve25519_new(void* heap, int devId); WOLFSSL_API int wc_curve25519_init(curve25519_key* key); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index ff3b26cb0c..b8b483ce2e 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -106,8 +106,10 @@ struct ed25519_key { void *heap; #ifdef WOLFSSL_ED25519_PERSISTENT_SHA wc_Sha512 sha; - int sha_clean_flag; + unsigned int sha_clean_flag : 1; #endif + /* flag indicates if structure was allocated */ + unsigned int isAllocated : 1; }; #ifndef WC_ED25519KEY_TYPE_DEFINED @@ -175,7 +177,8 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, #endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ #endif /* HAVE_ED25519_VERIFY */ - +WOLFSSL_API +ed25519_key* wc_ed25519_new(void* heap, int devId); WOLFSSL_API int wc_ed25519_init(ed25519_key* key); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index 1d12da87ae..c8ede51fec 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -97,7 +97,7 @@ struct ed448_key { void *heap; #ifdef WOLFSSL_ED448_PERSISTENT_SHA wc_Shake sha; - int sha_clean_flag; + unsigned int sha_clean_flag : 1; #endif }; diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 2f7de32d0d..5c1a6d661a 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -119,6 +119,7 @@ typedef union { #ifdef WOLFSSL_SM3 wc_Sm3 sm3; #endif + unsigned int isAllocated:1; /* flag indicates if structure was allocated */ } wc_HashAlg; #endif /* !NO_HASH_WRAPPER */ @@ -175,6 +176,8 @@ WOLFSSL_API int wc_Hash_ex(enum wc_HashType hash_type, byte* hash, word32 hash_len, void* heap, int devId); /* generic hash operation wrappers */ +WOLFSSL_API wc_HashAlg* wc_HashNew(enum wc_HashType type, void* heap, + int devId); WOLFSSL_API int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap, int devId); WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index c5d211e67a..4cff68a43c 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -269,6 +269,7 @@ struct RsaKey { #if defined(WOLFSSL_RENESAS_FSPSM) FSPSM_RSA_CTX ctx; #endif + unsigned int isAllocated:1; /* flag indicates if structure was allocated */ }; #ifndef WC_RSAKEY_TYPE_DEFINED @@ -292,6 +293,7 @@ struct RsaPadding { typedef struct RsaPadding RsaPadding; #endif +WOLFSSL_API RsaKey* wc_NewRsaKey(void* heap, int devId); WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); diff --git a/wrapper/CSharp/README.md b/wrapper/CSharp/README.md index 21310463ae..537e6cc9b4 100644 --- a/wrapper/CSharp/README.md +++ b/wrapper/CSharp/README.md @@ -2,7 +2,9 @@ This directory contains the CSharp wrapper for the wolfSSL TLS layer with examples. -* `wolfSSL_CSharp`: wolfSSL TLS layer wrappers (library) +* `wolfSSL_CSharp`: wolfSSL TLS layer wrappers (library). +* `wolfCrypt-Test`: wolfCrypt layer wrapper testing. +* `user_settings.h`: wolfCrypt wrapper user settings. Examples: * `wolfSSL-DTLS-PSK-Server` @@ -20,6 +22,12 @@ A Visual Studio solution `wolfSSL_CSharp.sln` is provided. This will allow you to build the wrapper library and examples. It includes the wolfSSL Visual Studio project directly. +To successfully run and build the solution on Windows Visual Studio you will +need to open a new solution `wolfSSL_CSharp.sln` located in `wrapper\CSharp\wolfSSL_CSharp.sln`. + +Select the CPU type, configuration, and target file. +select `Build` and either `Rebuild Solution` or `Build Solution`. + ## Linux (Ubuntu) using mono Prerequisites for linux: @@ -34,35 +42,40 @@ apt-get install mono-complete ``` ./autogen.sh -./configure --enable-wolftpm +./configure --enable-keygen --enable-eccencrypt --enable-ed25519 --enable-curve25519 --enable-aesgcm make make check sudo make install ``` -### Build and run the wrapper +### Build and run the wolfCrypt test wrapper + +From the `wrapper/CSharp` directory (`cd wrapper/CSharp`): -From the wolfssl root directory: +Compile wolfCrypt test: ``` -cd wrapper/CSharp +mcs wolfCrypt-Test/wolfCrypt-Test.cs wolfSSL_CSharp/wolfCrypt.cs -OUT:wolfcrypttest.exe +mono wolfcrypttest.exe ``` +### Build and run the wolfSSL client/server test + +From the `wrapper/CSharp` directory (`cd wrapper/CSharp`): + Compile server: ``` -mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs \ -wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs -OUT:server.exe +mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs -OUT:server.exe ``` Compile client: ``` -mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs \ -wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs -OUT:client.exe +mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs -OUT:client.exe ``` -### Run the example +#### Run the example In one terminal instance run the server: @@ -76,7 +89,7 @@ And in another terminal instance run the client: mono client.exe ``` -### Enabling SNI +#### Enabling SNI To enable SNI, just pass the `-S` argument with the specified hostname to the client: diff --git a/wrapper/CSharp/include.am b/wrapper/CSharp/include.am index c1a11c8c00..ecd70d015e 100644 --- a/wrapper/CSharp/include.am +++ b/wrapper/CSharp/include.am @@ -26,10 +26,13 @@ EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo. EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp.sln +EXTRA_DIST+= wrapper/CSharp/user_settings.h +EXTRA_DIST+= wrapper/CSharp/wolfssl.vcxproj EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/X509.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/App.config @@ -40,3 +43,7 @@ EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Client/App.config EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Client/Properties/AssemblyInfo.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.cs EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.csproj +EXTRA_DIST+= wrapper/CSharp/wolfCrypt-Test/App.config +EXTRA_DIST+= wrapper/CSharp/wolfCrypt-Test/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs +EXTRA_DIST+= wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.csproj diff --git a/wrapper/CSharp/user_settings.h b/wrapper/CSharp/user_settings.h new file mode 100644 index 0000000000..b9d2ff738d --- /dev/null +++ b/wrapper/CSharp/user_settings.h @@ -0,0 +1,136 @@ +/* user_settings.h + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* These are the build settings used by the Visual Studio CSharp wrapper */ + +#ifndef _WIN_CSHARP_USER_SETTINGS_H_ +#define _WIN_CSHARP_USER_SETTINGS_H_ + +/* Features */ +#define NO_OLD_TLS +#define WOLFSSL_TLS13 +#define WOLFSSL_DTLS +#define WOLFSSL_DTLS13 +#define WOLFSSL_SEND_HRR_COOKIE +#define WOLFSSL_DTLS_CID +#define HAVE_EXTENDED_MASTER +#define HAVE_SECURE_RENEGOTIATION +#define HAVE_SUPPORTED_CURVES +#define HAVE_TLS_EXTENSIONS +#define WOLFSSL_CERT_EXT +#define WOLFSSL_CERT_REQ +#define WOLFSSL_CERT_GEN +#define HAVE_ENCRYPT_THEN_MAC +#define HAVE_ECC_ENCRYPT +#define WOLFSSL_PUBLIC_MP +#define NO_MULTIBYTE_PRINT +#define WOLFSSL_KEY_GEN /* RSA key gen */ +#define WOLFSSL_ASN_TEMPLATE /* default */ +#define WOLFSSL_SHA3 + +#if 0 + #define OPENSSL_EXTRA +#endif + +#define HAVE_CRL +#if 0 + /* start thread that can monitor CRL directory */ + #define HAVE_CRL_MONITOR +#endif + +/* Algorithms */ +#define HAVE_ED25519 +#define HAVE_CURVE25519 + +#define HAVE_AESGCM +#define WOLFSSL_AESGCM_STREAM +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 + +#define HAVE_HKDF + +#undef NO_DH +#define HAVE_PUBLIC_FFDHE +#define HAVE_FFDHE_2048 +#define HAVE_FFDHE_4096 + +#undef NO_RSA +#define WC_RSA_PSS +#define WOLFSSL_PSS_LONG_SALT +#define WC_RSA_BLINDING + +#define HAVE_ECC +#define ECC_SHAMIR +#define ECC_TIMING_RESISTANT +#define HAVE_COMP_KEY + +/* Disable features */ +#define NO_PSK + +/* Disable Algorithms */ +#define NO_DES3 +#define NO_DSA +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_SHA + +/* Math */ + +/* Single Precision Support for RSA/DH 1024/2048/3072 and + * ECC P-256/P-384 */ +#define WOLFSSL_HAVE_SP_ECC +#define WOLFSSL_HAVE_SP_DH +#define WOLFSSL_HAVE_SP_RSA + +/* Optional Performance Speedups */ +#if 0 + #ifdef _WIN64 + /* Assembly speedups for SP math */ + #define WOLFSSL_SP_X86_64_ASM + + /* Support for RDSEED instruction */ + #define HAVE_INTEL_RDSEED + + /* AESNI on x64 */ + #define WOLFSSL_AESNI + + /* Intel ASM */ + #define USE_INTEL_SPEEDUP + #define WOLFSSL_X86_64_BUILD + + /* Old versions of MASM compiler do not recognize newer + * instructions. */ + #if 0 + #define NO_AVX2_SUPPORT + #define NO_MOVBE_SUPPORT + #endif + #endif +#endif + +/* Debug logging */ +#if 1 + #define DEBUG_WOLFSSL +#else + /* #define NO_ERROR_STRINGS */ +#endif + +#endif /* !_WIN_CSHARP_USER_SETTINGS_H_ */ diff --git a/wrapper/CSharp/wolfCrypt-Test/App.config b/wrapper/CSharp/wolfCrypt-Test/App.config new file mode 100644 index 0000000000..4bfa005618 --- /dev/null +++ b/wrapper/CSharp/wolfCrypt-Test/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/wrapper/CSharp/wolfCrypt-Test/Properties/AssemblyInfo.cs b/wrapper/CSharp/wolfCrypt-Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..ed34d06a03 --- /dev/null +++ b/wrapper/CSharp/wolfCrypt-Test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfCrypt-Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfCrypt-Test")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a4f4a244-1306-47f4-a168-31f78d7362fa")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs new file mode 100644 index 0000000000..2dd2e7f774 --- /dev/null +++ b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs @@ -0,0 +1,920 @@ +/* wolfCrypt-Test.cs + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Tests for the wolfCrypt C# wrapper */ + +using System; +using System.Linq; +using System.Text; +using System.Security.Cryptography; +using wolfSSL.CSharp; +using System.Runtime.InteropServices; +using static wolfSSL.CSharp.wolfcrypt; + +public class wolfCrypt_Test_CSharp +{ + private static void random_test() + { + int ret, i, zeroCount = 0; + Byte[] data = new Byte[128]; + + Console.WriteLine("Starting RNG test"); + + /* Random Test */ + ret = wolfcrypt.Random(data, data.Length); + if (ret == 0) + { + /* Check for 0's */ + for (i = 0; i < (int)data.Length; i++) + { + if (data[i] == 0) + { + zeroCount++; + } + } + if (zeroCount == data.Length) + { + Console.WriteLine("RNG zero check error"); + } + else + { + Console.WriteLine("RNG Test Passed"); + } + } + else + { + Console.WriteLine("RNG Error" + wolfcrypt.GetError(ret)); + } + } /* END random_test */ + + private static void ecc_test(string hashAlgorithm, int keySize) + { + int ret; + IntPtr rng = IntPtr.Zero; + IntPtr PrivKey = IntPtr.Zero; + IntPtr PubKey = IntPtr.Zero; + IntPtr key = IntPtr.Zero; + + Console.WriteLine("\nStarting ECC" + (keySize*8) + " test for " + hashAlgorithm + "..."); + + /* Create a new RNG context */ + rng = wolfcrypt.RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("RNG initialization failed."); + } + + /* Generate ECC Key Pair */ + Console.WriteLine("Testing ECC Key Generation..."); + key = wolfcrypt.EccMakeKey(keySize, rng); + if (key == IntPtr.Zero) + { + throw new Exception("EccMakeKey failed"); + } + Console.WriteLine("ECC Key Generation test passed."); + + /* Export and Import Key */ + Console.WriteLine("Testing ECC Key Export and Import..."); + byte[] privateKeyDer; + ret = wolfcrypt.EccExportPrivateKeyToDer(key, out privateKeyDer); + if (ret < 0) { + throw new Exception("ExportPrivateKeyToDer failed"); + } + byte[] publicKeyDer; + ret = wolfcrypt.EccExportPublicKeyToDer(key, out publicKeyDer, true); + if (ret < 0) { + throw new Exception("ExportPublicKeyToDer failed"); + } + PrivKey = wolfcrypt.EccImportKey(privateKeyDer); + if (PrivKey == IntPtr.Zero) + { + throw new Exception("EccImportKey Private failed"); + } + + PubKey = wolfcrypt.EccImportPublicKeyFromDer(publicKeyDer); + if (PubKey == IntPtr.Zero) + { + throw new Exception("ImportPublicKeyFromDer Public failed"); + } + Console.WriteLine("ECC Key Export and Import test passed."); + + /* Generate hash based on selected algorithm */ + byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); + byte[] hash; + + switch (hashAlgorithm.ToUpper()) + { + case "SHA256": + using (SHA256 sha256 = SHA256.Create()) + { + hash = sha256.ComputeHash(dataToHash); + } + break; + + case "SHA384": + using (SHA384 sha384 = SHA384.Create()) + { + hash = sha384.ComputeHash(dataToHash); + } + break; + + case "SHA512": + using (SHA512 sha512 = SHA512.Create()) + { + hash = sha512.ComputeHash(dataToHash); + } + break; + + default: + throw new Exception("Unsupported hash algorithm"); + } + Console.WriteLine($"{hashAlgorithm} hash generated."); + + /* Sign Data */ + Console.WriteLine("Testing ECC Signature Creation..."); + byte[] signature = new byte[wolfcrypt.ECC_MAX_SIG_SIZE]; + int signLength = wolfcrypt.EccSign(PrivKey, hash, signature); + if (signLength <= 0) + { + throw new Exception("EccSign failed"); + } + + byte[] actualSignature = new byte[signLength]; + Array.Copy(signature, 0, actualSignature, 0, signLength); + + Console.WriteLine($"ECC Signature Creation test passed. Signature Length: {signLength}"); + + /* Verify Signature */ + Console.WriteLine("Testing ECC Signature Verification..."); + int verifyResult = wolfcrypt.EccVerify(PubKey, actualSignature, hash); + if (verifyResult != 0) + { + throw new Exception("EccVerify failed"); + } + Console.WriteLine("ECC Signature Verification test passed."); + + /* Cleanup */ + if (key != IntPtr.Zero) wolfcrypt.EccFreeKey(key); + if (PubKey != IntPtr.Zero) wolfcrypt.EccFreeKey(PubKey); + if (PrivKey != IntPtr.Zero) wolfcrypt.EccFreeKey(PrivKey); + if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); + } /* END ecc_test */ + + private static void ecies_test(int keySize) + { + /* maximum encrypted message: + * msgSz (14) + pad (2) + pubKeySz(1+66*2) + ivSz(16) + digestSz(32) = 197 */ + int bufferSize = wolfcrypt.MAX_ECIES_TEST_SZ; + const string message = "Hello wolfSSL!"; + byte[] salt = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + IntPtr a = IntPtr.Zero; + IntPtr b = IntPtr.Zero; + IntPtr aCtx = IntPtr.Zero; + IntPtr bCtx = IntPtr.Zero; + IntPtr rng = IntPtr.Zero; + IntPtr heap = IntPtr.Zero; + + byte[] plaintext = new byte[bufferSize]; + byte[] encrypted = new byte[bufferSize]; + byte[] decrypted = new byte[bufferSize]; + + try + { + Console.WriteLine($"\nStarting ECIES test for {keySize} byte key size..."); + + /* Create a new RNG context */ + rng = wolfcrypt.RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("RNG initialization failed."); + } + + /* Initialize keys */ + a = wolfcrypt.EccMakeKey(keySize, rng); + b = wolfcrypt.EccMakeKey(keySize, rng); + if (a == IntPtr.Zero || b == IntPtr.Zero) + { + throw new Exception("Key generation failed."); + } + Console.WriteLine("ECC key generation passed."); + + /* Create ECIES contexts for encryption and decryption */ + aCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_CLIENT, rng, heap); + bCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_SERVER, rng, heap); + if (aCtx == IntPtr.Zero || bCtx == IntPtr.Zero) + { + throw new Exception("Context creation failed."); + } + Console.WriteLine("ECC context creation passed."); + + /* Set KDF salt */ + if (wolfcrypt.EciesSetKdfSalt(aCtx, salt) != 0 || + wolfcrypt.EciesSetKdfSalt(bCtx, salt) != 0) + { + throw new Exception("Failed to set KDF salt."); + } + Console.WriteLine("KDF salt setup passed."); + + /* Prepare plaintext */ + Array.Clear(plaintext, 0, plaintext.Length); + Array.Copy(Encoding.ASCII.GetBytes(message), plaintext, message.Length); + /* Pad to block size */ + int plaintextLen = ((message.Length + (wolfcrypt.AES_BLOCK_SIZE - 1)) / + wolfcrypt.AES_BLOCK_SIZE) * wolfcrypt.AES_BLOCK_SIZE; + + /* Encrypt message */ + int ret = wolfcrypt.EciesEncrypt(a, b, plaintext, (uint)plaintextLen, encrypted, aCtx); + if (ret < 0) + { + throw new Exception("Encryption failed."); + } + + int encryptedLen = ret; + Console.WriteLine("ECC encryption passed."); + + /* Decrypt message */ + ret = wolfcrypt.EciesDecrypt(b, a, encrypted, (uint)encryptedLen, decrypted, bCtx); + if (ret < 0) + { + throw new Exception("Decryption failed."); + } + + int decryptedLen = ret; + Console.WriteLine("ECC decryption passed."); + + /* Compare decrypted text to original plaintext */ + if (decryptedLen != plaintextLen || !wolfcrypt.ByteArrayVerify(plaintext, decrypted)) + { + throw new Exception("Decrypted text does not match original plaintext."); + } + Console.WriteLine("Decrypted text matches original plaintext."); + } + finally + { + /* Cleanup key and context */ + if (a != IntPtr.Zero) wolfcrypt.EccFreeKey(a); + if (b != IntPtr.Zero) wolfcrypt.EccFreeKey(b); + if (aCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(aCtx); + if (bCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(bCtx); + if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); + } + } /* END ecies_test */ + + private static void ecdhe_test(int keySize) + { + int ret; + IntPtr rng = IntPtr.Zero; + IntPtr keyA = IntPtr.Zero; + IntPtr keyB = IntPtr.Zero; + IntPtr publicKeyA = IntPtr.Zero; + IntPtr publicKeyB = IntPtr.Zero; + byte[] derKey; + + Console.WriteLine("\nStarting ECDHE shared secret test for " + keySize + " key size..."); + + /* Create RNG */ + Console.WriteLine("Generating RNG..."); + rng = RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("Failed to generate RNG."); + } + Console.WriteLine("RNG generation test passed."); + + /* Generate Key Pair A */ + Console.WriteLine("Generating Key Pair A..."); + keyA = wolfcrypt.EccMakeKey(keySize, rng); + if (keyA == IntPtr.Zero) + { + throw new Exception("Failed to generate key pair A."); + } + + /* Generate Key Pair B */ + Console.WriteLine("Generating Key Pair B..."); + keyB = wolfcrypt.EccMakeKey(keySize, rng); + if (keyB == IntPtr.Zero) + { + throw new Exception("Failed to generate key pair B."); + } + Console.WriteLine("ECC Key generation test passed."); + + /* Export Public Key B to DER format */ + Console.WriteLine("Exporting Public Key B to DER format..."); + ret = wolfcrypt.EccExportPublicKeyToDer(keyB, out derKey, true); + if (ret < 0 || derKey == null) + { + throw new Exception("EccExportPublicKeyToDer failed"); + } + + /* Decode Public Key B from DER format */ + Console.WriteLine("Decoding Public Key B from DER format..."); + publicKeyB = wolfcrypt.EccImportPublicKeyFromDer(derKey); + if (publicKeyB == IntPtr.Zero) + { + throw new Exception("Failed to decode public key B from DER format."); + } + Console.WriteLine("ECC Export and Import test passed."); + + /* Compute Shared Secret using Private Key A and Public Key B */ + Console.WriteLine("Computing Shared Secret using Private Key A and Public Key B..."); + byte[] sharedSecretA = new byte[keySize]; + int retA = wolfcrypt.EcdheSharedSecret(keyA, publicKeyB, sharedSecretA, rng); + if (retA != 0) + { + throw new Exception("Failed to compute shared secret A. Error code: " + retA); + } + Console.WriteLine("ECC shared secret created using private Key A."); + + /* Export Public Key A to DER format */ + Console.WriteLine("Exporting Public Key A to DER format..."); + ret = wolfcrypt.EccExportPublicKeyToDer(keyA, out derKey, true); + if (ret < 0 || derKey == null) + { + throw new Exception("EccExportPublicKeyToDer failed"); + } + + /* Decode Public Key A from DER format */ + Console.WriteLine("Decoding Public Key A from DER format..."); + publicKeyA = wolfcrypt.EccImportPublicKeyFromDer(derKey); + if (publicKeyA == IntPtr.Zero) + { + throw new Exception("Failed to decode public key A from DER format."); + } + + /* Compute Shared Secret using Private Key B and Public Key A */ + Console.WriteLine("Computing Shared Secret using Private Key B and Public Key A..."); + byte[] sharedSecretB = new byte[keySize]; + int retB = wolfcrypt.EcdheSharedSecret(keyB, publicKeyA, sharedSecretB, rng); + if (retB != 0) + { + throw new Exception("Failed to compute shared secret B. Error code: " + retB); + } + Console.WriteLine("ECC shared secret created using private Key B."); + + /* Compare Shared Secrets */ + Console.WriteLine("Comparing Shared Secrets..."); + if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB)) + { + throw new Exception("Shared secrets do not match."); + } + else + { + Console.WriteLine("ECC shared secret match."); + } + + /* Cleanup */ + if (keyA != IntPtr.Zero) wolfcrypt.EccFreeKey(keyA); + if (keyB != IntPtr.Zero) wolfcrypt.EccFreeKey(keyB); + if (publicKeyA != IntPtr.Zero) wolfcrypt.EccFreeKey(publicKeyA); + if (publicKeyB != IntPtr.Zero) wolfcrypt.EccFreeKey(publicKeyB); + if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); + } /* END ecdhe_test */ + + private static void rsa_test(string hashAlgorithm, int keySize) + { + IntPtr key = IntPtr.Zero; + IntPtr heap = IntPtr.Zero; + int devId = wolfcrypt.INVALID_DEVID; + + Console.WriteLine("\nStarting RSA" + keySize + " test for " + hashAlgorithm + "..."); + + /* Generate RSA Key Pair */ + Console.WriteLine("Testing RSA Key Generation..."); + key = wolfcrypt.RsaMakeKey(heap, devId, keySize); + if (key == IntPtr.Zero) + { + throw new Exception("RsaMakeKey failed"); + } + Console.WriteLine("RSA Key Generation test passed."); + + /* Generate hash based on selected algorithm */ + byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); + byte[] hash; + + switch (hashAlgorithm.ToUpper()) + { + case "SHA256": + using (SHA256 sha256 = SHA256.Create()) + { + hash = sha256.ComputeHash(dataToHash); + } + break; + + case "SHA384": + using (SHA384 sha384 = SHA384.Create()) + { + hash = sha384.ComputeHash(dataToHash); + } + break; + + case "SHA512": + using (SHA512 sha512 = SHA512.Create()) + { + hash = sha512.ComputeHash(dataToHash); + } + break; + + default: + throw new Exception("Unsupported hash algorithm"); + } + Console.WriteLine($"{hashAlgorithm} hash generated."); + + /* Sign Data */ + Console.WriteLine("Testing RSA Signature Creation..."); + byte[] signature = new byte[keySize / 8]; + int signLength = wolfcrypt.RsaSignSSL(key, hash, signature); + if (signLength <= 0) + { + throw new Exception("RsaSignSSL failed"); + } + + byte[] actualSignature = new byte[signLength]; + Array.Copy(signature, 0, actualSignature, 0, signLength); + + Console.WriteLine($"RSA Signature Creation test passed. Signature Length: {signLength}"); + + /* Verify Signature */ + Console.WriteLine("Testing RSA Signature Verification..."); + int verifyResult = wolfcrypt.RsaVerifySSL(key, actualSignature, hash); + if (verifyResult != 0) + { + throw new Exception("RsaVerifySSL failed"); + } + Console.WriteLine("RSA Signature Verification test passed."); + + /* Cleanup */ + if (key != IntPtr.Zero) wolfcrypt.RsaFreeKey(key); + } /* END rsa_test */ + + private static void ed25519_test() + { + int ret; + IntPtr key = IntPtr.Zero; + byte[] privKey; + byte[] pubKey; + + Console.WriteLine("\nStarting ED25519 tests..."); + + IntPtr heap = IntPtr.Zero; + int devId = wolfcrypt.INVALID_DEVID; + + /* Generate ED25519 Key Pair */ + Console.WriteLine("Testing ED25519 Key Generation..."); + key = wolfcrypt.Ed25519MakeKey(heap, devId); + if (key == IntPtr.Zero) + { + throw new Exception("Ed25519MakeKey failed"); + } + Console.WriteLine("ED25519 Key Generation test passed."); + + /* Export and Import Key */ + Console.WriteLine("Testing ED25519 Key Export and Import..."); + /* Export Private */ + ret = wolfcrypt.Ed25519ExportKeyToDer(key, out privKey); + if (ret < 0 || privKey == null) + { + throw new Exception("Ed25519ExportKeyToDer failed"); + } + /* Export Public */ + ret = wolfcrypt.Ed25519ExportPublicKeyToDer(key, out pubKey, true); + if (ret < 0 || pubKey == null) + { + throw new Exception("Ed25519ExportKeyToDer failed"); + } + /* Import Private */ + IntPtr importedPrivKey = wolfcrypt.Ed25519PrivateKeyDecode(privKey); + if (importedPrivKey == IntPtr.Zero) + { + throw new Exception("Ed25519PrivateKeyDecode failed"); + } + /* Import Public */ + IntPtr importedPubKey = wolfcrypt.Ed25519PublicKeyDecode(pubKey); + if (importedPubKey == IntPtr.Zero) + { + throw new Exception("Ed25519PublicKeyDecode failed"); + } + Console.WriteLine("ED25519 Key Export and Import test passed."); + + /* Generate a hash */ + byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); + + /* Sign Data */ + Console.WriteLine("Testing ED25519 Signature Creation..."); + byte[] signature; + + ret = wolfcrypt.Ed25519SignMsg(dataToHash, out signature, key); + if (ret != 0) + { + throw new Exception("Ed25519SignMsg failed"); + } + Console.WriteLine($"ED25519 Signature Creation test passed. Signature Length: {signature.Length}"); + + /* Verify Signature */ + Console.WriteLine("Testing ED25519 Signature Verification..."); + ret = wolfcrypt.Ed25519VerifyMsg(signature, dataToHash, key); + if (ret != 0) + { + throw new Exception("Ed25519VerifyMsg failed"); + } + Console.WriteLine("ED25519 Signature Verification test passed."); + + /* Cleanup */ + if (key != IntPtr.Zero) wolfcrypt.Ed25519FreeKey(key); + } /* END ed25519_test */ + + private static void curve25519_test() + { + int ret; + IntPtr keyA = IntPtr.Zero; + IntPtr keyB = IntPtr.Zero; + IntPtr publicKeyA = IntPtr.Zero; + IntPtr publicKeyB = IntPtr.Zero; + byte[] derKey; + + Console.WriteLine("\nStarting Curve25519 shared secret test..."); + + /* Generate Key Pair A */ + Console.WriteLine("Generating Key Pair A..."); + keyA = wolfcrypt.Curve25519MakeKey(IntPtr.Zero, 0); + if (keyA == IntPtr.Zero) + { + throw new Exception("Failed to generate key pair A."); + } + + /* Generate Key Pair B */ + Console.WriteLine("Generating Key Pair B..."); + keyB = wolfcrypt.Curve25519MakeKey(IntPtr.Zero, 0); + if (keyB == IntPtr.Zero) + { + throw new Exception("Failed to generate key pair B."); + } + Console.WriteLine("Curve25519 Key generation test passed."); + + /* Export Public Key B to DER format */ + Console.WriteLine("Exporting Public Key B to DER format..."); + ret = wolfcrypt.Curve25519ExportPublicKeyToDer(keyB, out derKey, true); + if (ret < 0 || derKey == null) + { + throw new Exception("Curve25519ExportPublicKeyToDer failed"); + } + + /* Decode Public Key B from DER format */ + Console.WriteLine("Decoding Public Key B from DER format..."); + publicKeyB = wolfcrypt.Curve25519PublicKeyDecode(derKey); + if (publicKeyB == IntPtr.Zero) + { + throw new Exception("Failed to decode public key B from DER format."); + } + Console.WriteLine("Curve25519 Export and Import test passed."); + + /* Compute Shared Secret using Private Key A and Public Key B */ + Console.WriteLine("Computing Shared Secret using Private Key A and Public Key B..."); + byte[] sharedSecretA = new byte[wolfcrypt.ED25519_KEY_SIZE]; + int retA = wolfcrypt.Curve25519SharedSecret(keyA, publicKeyB, sharedSecretA); + if (retA != 0) + { + throw new Exception("Failed to compute shared secret A. Error code: " + retA); + } + Console.WriteLine("Curve25519 shared secret created using private Key A."); + + /* Export Public Key A to DER format */ + Console.WriteLine("Exporting Public Key A to DER format..."); + ret = wolfcrypt.Curve25519ExportPublicKeyToDer(keyA, out derKey, true); + if (ret < 0 || derKey == null) + { + throw new Exception("Curve25519ExportPublicKeyToDer failed"); + } + + /* Decode Public Key A from DER format */ + Console.WriteLine("Decoding Public Key A from DER format..."); + publicKeyA = wolfcrypt.Curve25519PublicKeyDecode(derKey); + if (publicKeyA == IntPtr.Zero) + { + throw new Exception("Failed to decode public key A from DER format."); + } + + /* Compute Shared Secret using Private Key B and Public Key A */ + Console.WriteLine("Computing Shared Secret using Private Key B and Public Key A..."); + byte[] sharedSecretB = new byte[wolfcrypt.ED25519_KEY_SIZE]; + int retB = wolfcrypt.Curve25519SharedSecret(keyB, publicKeyA, sharedSecretB); + if (retB != 0) + { + throw new Exception("Failed to compute shared secret B. Error code: " + retB); + } + Console.WriteLine("Curve25519 shared secret created using private Key B."); + + /* Compare Shared Secrets */ + Console.WriteLine("Comparing Shared Secrets..."); + if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB)) + { + throw new Exception("Shared secrets do not match."); + } + else + { + Console.WriteLine("Curve25519 shared secret match."); + } + + /* Cleanup */ + if (keyA != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(keyA); + if (keyB != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(keyB); + if (publicKeyA != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(publicKeyA); + if (publicKeyB != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(publicKeyB); + } /* END curve25519_test */ + + private static void aes_gcm_test() + { + IntPtr aes = IntPtr.Zero; + byte[] key; + byte[] iv; + byte[] plaintext; + byte[] ciphertext; + byte[] addAuth; + byte[] authTag; + byte[] decrypted; + int ret; + + try + { + Console.WriteLine("\nStarting AES-GCM tests..."); + + IntPtr heap = IntPtr.Zero; + int devId = wolfcrypt.INVALID_DEVID; + + /* Initialize AES-GCM Context */ + Console.WriteLine("Testing AES-GCM Initialization..."); + + /* + * This is from the Test Case 16 from the document Galois/ + * Counter Mode of Operation (GCM) by McGrew and + * Viega. + */ + + key = new byte[32] + { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 + }; + + iv = new byte[12] + { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 + }; + + plaintext = new byte[] + { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 + }; + + + ciphertext = new byte[] + { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 + }; + + addAuth = new byte[] + { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 + }; + + authTag = new byte[16]; + + aes = wolfcrypt.AesNew(heap, devId); + if (aes == IntPtr.Zero) + { + throw new Exception($"AesNew failed with error code {aes}"); + } + Console.WriteLine("AesNew test passed."); + + /* Set AES-GCM Key */ + Console.WriteLine("Testing AES-GCM Key Setting..."); + uint len = (uint)key.Length; + ret = wolfcrypt.AesGcmSetKey(aes, key); + if (ret != 0) + { + throw new Exception($"AesGcmSetKey failed with error code {ret}"); + } + Console.WriteLine("AES-GCM Key Setting test passed."); + + /* Encryption */ + Console.WriteLine("Testing AES-GCM Encryption..."); + ret = wolfcrypt.AesGcmEncrypt(aes, iv, plaintext, ciphertext, authTag, addAuth); + if (ret != 0) + { + throw new Exception($"AesGcmEncrypt failed with error code {ret}"); + } + Console.WriteLine($"AES-GCM Encryption test passed. Ciphertext Length: {ciphertext.Length}"); + + /* Decryption */ + Console.WriteLine("Testing AES-GCM Decryption..."); + decrypted = new byte[plaintext.Length]; + + ret = wolfcrypt.AesGcmDecrypt(aes, iv, ciphertext, decrypted, authTag, addAuth); + if (ret != 0) + { + throw new Exception($"AesGcmDecrypt failed with error code {ret}"); + } + + /* Verify Decryption */ + if (!plaintext.SequenceEqual(decrypted)) + { + throw new Exception("Decryption failed: decrypted data does not match original plaintext."); + } + Console.WriteLine("AES-GCM Decryption test passed."); + + } + catch (Exception ex) + { + Console.WriteLine($"AES-GCM test failed: {ex.Message}"); + } + finally + { + /* Cleanup */ + if (aes != IntPtr.Zero) + { + wolfcrypt.AesGcmFree(aes); + } + } + } /* END aes_gcm_test */ + + private static void hash_test(uint hashType) + { + IntPtr hash = IntPtr.Zero; + IntPtr heap = IntPtr.Zero; + int devId = wolfcrypt.INVALID_DEVID; + + /* Get the enum name */ + string hashTypeName = Enum.GetName(typeof(wolfcrypt.hashType), hashType); + + Console.WriteLine($"\nStarting hash test for {hashTypeName}..."); + + /* Allocate new hash context */ + Console.WriteLine("Testing hash context allocation..."); + hash = wolfcrypt.HashNew(hashType, heap, devId); + if (hash == IntPtr.Zero) + { + Console.WriteLine($"HashNew failed for {hashTypeName}"); + return; + } + Console.WriteLine("Hash context allocation test passed."); + + /* Initialize the hash context with the specified hash type */ + Console.WriteLine("Testing hash initialization..."); + int initResult = wolfcrypt.InitHash(hash, hashType); + if (initResult != 0) + { + Console.WriteLine($"InitHash failed for {hashTypeName}"); + wolfcrypt.HashFree(hash, hashType); + return; + } + Console.WriteLine("Hash initialization test passed."); + + /* Update the hash with data */ + byte[] dataToHash = Encoding.UTF8.GetBytes("This is some data to hash"); + Console.WriteLine("Testing hash update..."); + int updateResult = wolfcrypt.HashUpdate(hash, hashType, dataToHash); + if (updateResult != 0) + { + Console.WriteLine($"HashUpdate failed for {hashTypeName}"); + wolfcrypt.HashFree(hash, hashType); + return; + } + Console.WriteLine("Hash update test passed."); + + /* Finalize the hash and get the result */ + Console.WriteLine("Testing hash finalization..."); + byte[] hashOutput; + int finalResult = wolfcrypt.HashFinal(hash, hashType, out hashOutput); + if (finalResult != 0) + { + Console.WriteLine($"HashFinal failed for {hashType}"); + wolfcrypt.HashFree(hash, hashType); + return; + } + Console.WriteLine($"Hash finalization test passed for {hashTypeName}. Hash Length: {hashOutput.Length}"); + + /* Output the hash result */ + Console.WriteLine($"Hash Output ({hashTypeName}): {BitConverter.ToString(hashOutput).Replace("-", "")}"); + + /* Cleanup */ + Console.WriteLine("Testing hash cleanup..."); + int freeResult = wolfcrypt.HashFree(hash, hashType); + if (freeResult != 0) + { + Console.WriteLine($"HashFree failed for {hashTypeName}"); + } + else + { + Console.WriteLine("Hash cleanup test passed."); + } + } /* END hash_test */ + + public static void standard_log(int lvl, StringBuilder msg) + { + Console.WriteLine(msg); + } + + public static void Main(string[] args) + { + try + { + Console.WriteLine("Starting Cryptographic Tests...\n"); + + wolfcrypt.Init(); + + /* setup logging to stdout */ + wolfcrypt.SetLogging(standard_log); + + random_test(); + + Console.WriteLine("\nStarting ECC tests"); + + ecc_test("SHA256", 32); /* Uses SHA-256 (32 byte hash) */ + ecc_test("SHA384", 32); /* Uses SHA-384 (32 byte hash) */ + ecc_test("SHA512", 32); /* Uses SHA-512 (32 byte hash) */ + + Console.WriteLine("\nStarting ECIES tests"); + + ecies_test(32); /* ECIES test (32 byte key size) */ + ecies_test(48); /* ECIES test (48 byte key size) */ + ecies_test(66); /* ECIES test (66 byte key size) */ + + Console.WriteLine("\nStarting ECDHE tests"); + + ecdhe_test(32); /* ECDHE shared secret test (32 byte key size) */ + ecdhe_test(48); /* ECDHE shared secret test (48 byte key size) */ + ecdhe_test(66); /* ECDHE shared secret test (66 byte key size) */ + + Console.WriteLine("\nStarting RSA tests"); + + rsa_test("SHA256", 2048); /* Uses SHA-256 (2048 bit hash) */ + rsa_test("SHA384", 2048); /* Uses SHA-384 (2048 bit hash) */ + rsa_test("SHA512", 2048); /* Uses SHA-512 (2048 bit hash) */ + + Console.WriteLine("\nStarting ED25519 test"); + + ed25519_test(); /* ED25519 test */ + + Console.WriteLine("\nStarting curve25519 test"); + + curve25519_test(); /* curve25519 shared secret test */ + + Console.WriteLine("\nStarting AES-GCM test"); + + aes_gcm_test(); /* AES_GCM test */ + + Console.WriteLine("\nStarting HASH tests"); + + hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA256); /* SHA-256 HASH test */ + hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA384); /* SHA-384 HASH test */ + hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA512); /* SHA-512 HASH test */ + hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA3_256); /* SHA3_256 HASH test */ + + wolfcrypt.Cleanup(); + + Console.WriteLine("\nAll tests completed successfully"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + Environment.Exit(-1); + } + } +} diff --git a/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.csproj b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.csproj new file mode 100644 index 0000000000..647d7ce7bd --- /dev/null +++ b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.csproj @@ -0,0 +1,123 @@ + + + + + Debug + AnyCPU + {A4F4A244-1306-47F4-A168-31F78D7362FA} + Exe + Properties + wolfCrypt_Test + wolfCrypt-Test + v4.8 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + $(SolutionDir)$(Configuration)\$(Platform)\ + DEBUG;TRACE + prompt + 3 + + + AnyCPU + pdbonly + true + $(SolutionDir)$(Configuration)\$(Platform)\ + TRACE + prompt + 4 + + + + + + true + $(SolutionDir)$(Configuration)\$(Platform)\ + DEBUG;TRACE + 4 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + $(SolutionDir)$(Configuration)\$(Platform)\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + \ No newline at end of file diff --git a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config index 49c50e046b..8a99d30db7 100755 --- a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config +++ b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj index 9af7a1f422..5bf4e8c8e0 100755 --- a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj +++ b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj @@ -9,15 +9,16 @@ Properties wolfSSL_DTLS_PSK_Server wolfSSL-DTLS-PSK-Server - v4.5 + v4.8 512 + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 4 @@ -26,14 +27,14 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE full x64 @@ -42,7 +43,7 @@ true - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-DTLS-Server/App.config b/wrapper/CSharp/wolfSSL-DTLS-Server/App.config index 49c50e046b..8a99d30db7 100755 --- a/wrapper/CSharp/wolfSSL-DTLS-Server/App.config +++ b/wrapper/CSharp/wolfSSL-DTLS-Server/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj b/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj index 1c9eb2b126..e0c4a57ea3 100755 --- a/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj +++ b/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj @@ -9,15 +9,16 @@ Properties wolfSSL_DTLS_Server wolfSSL-DTLS-Server - v4.5 + v4.8 512 + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 4 @@ -26,14 +27,14 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE full x64 @@ -43,7 +44,7 @@ 0 - ..\DLL Release\x64 + $(SolutionDir)$(Configuration)\$(Platform)\x64 TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config index 49c50e046b..8a99d30db7 100755 --- a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config +++ b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj index 4e6dae1a69..dc57d74f3b 100755 --- a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj +++ b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj @@ -9,15 +9,16 @@ Properties wolfSSL_Example_IOCallbacks wolfSSL-Example-IOCallbacks - v4.5 + v4.8 512 + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 4 @@ -26,14 +27,14 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE full x64 @@ -42,7 +43,7 @@ true - ..\DLL Release\x64 + $(SolutionDir)$(Configuration)\$(Platform)\x64 TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-TLS-Client/App.config b/wrapper/CSharp/wolfSSL-TLS-Client/App.config index f3ec453d92..8a99d30db7 100644 --- a/wrapper/CSharp/wolfSSL-TLS-Client/App.config +++ b/wrapper/CSharp/wolfSSL-TLS-Client/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj b/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj index 3a3d175e4c..7afffb9d4e 100644 --- a/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj +++ b/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj @@ -9,7 +9,7 @@ Properties wolfSSL_TLS_Client wolfSSL-TLS-Client - v4.5 + v4.8 512 publish\ true @@ -26,13 +26,14 @@ false false true + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 3 @@ -41,7 +42,7 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 @@ -51,7 +52,7 @@ true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE 4 full @@ -61,7 +62,7 @@ true - ..\DLL Release\x64 + $(SolutionDir)$(Configuration)\$(Platform)\x64 TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.csproj b/wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.csproj index b2113d6ae2..5c3e77e470 100644 --- a/wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.csproj +++ b/wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.csproj @@ -33,7 +33,7 @@ true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 4 @@ -42,14 +42,14 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE full x64 @@ -58,7 +58,7 @@ true - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config index 49c50e046b..8a99d30db7 100755 --- a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config +++ b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj index dab61d5376..1f31752ec7 100755 --- a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj +++ b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj @@ -9,15 +9,16 @@ Properties wolfSSL_TLS_PSK_Server wolfSSL-TLS-PSK-Server - v4.5 + v4.8 512 + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 4 @@ -26,14 +27,14 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE full x64 @@ -42,7 +43,7 @@ true - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-TLS-Server/App.config b/wrapper/CSharp/wolfSSL-TLS-Server/App.config index 49c50e046b..8a99d30db7 100755 --- a/wrapper/CSharp/wolfSSL-TLS-Server/App.config +++ b/wrapper/CSharp/wolfSSL-TLS-Server/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj b/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj index 35f8b0666e..1cc073e83c 100755 --- a/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj +++ b/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj @@ -9,7 +9,7 @@ Properties wolfSSL_TLS_Server wolfSSL-TLS-Server - v4.5 + v4.8 512 publish\ true @@ -26,13 +26,14 @@ false false true + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 3 @@ -41,7 +42,7 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 @@ -51,7 +52,7 @@ true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE 4 full @@ -61,7 +62,7 @@ true - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config index 49c50e046b..8a99d30db7 100644 --- a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config +++ b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj index 7c47cf557f..f1468d14f2 100644 --- a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj +++ b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj @@ -9,7 +9,7 @@ Properties wolfSSL_TLS_ServerThreaded wolfSSL-TLS-ServerThreaded - v4.5 + v4.8 512 publish\ true @@ -26,13 +26,14 @@ false false true + AnyCPU true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 3 @@ -41,7 +42,7 @@ AnyCPU pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 @@ -51,7 +52,7 @@ true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE 4 full @@ -61,7 +62,7 @@ true - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly diff --git a/wrapper/CSharp/wolfSSL_CSharp.sln b/wrapper/CSharp/wolfSSL_CSharp.sln index a4898062ae..48e170a48d 100644 --- a/wrapper/CSharp/wolfSSL_CSharp.sln +++ b/wrapper/CSharp/wolfSSL_CSharp.sln @@ -1,9 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL_CSharp", "wolfSSL_CSharp\wolfSSL_CSharp.csproj", "{52609808-0418-46D3-8E17-141927A1A39A}" ProjectSection(ProjectDependencies) = postProject - {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + {67932048-D67E-4C86-B55F-90899B9BDA64} = {67932048-D67E-4C86-B55F-90899B9BDA64} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-Server", "wolfSSL-TLS-Server\wolfSSL-TLS-Server.csproj", "{8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}" @@ -17,11 +19,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-DTLS-PSK-Server", " {52609808-0418-46D3-8E17-141927A1A39A} = {52609808-0418-46D3-8E17-141927A1A39A} EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wolfSSL", "wolfSSL", "{252D09D0-D007-4AEB-9F7A-A74408039A8A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "..\..\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "..\..\testsuite\testsuite.vcxproj", "{611E8971-46E0-4D0A-B5A1-632C3B00CB80}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "wolfssl.vcxproj", "{67932048-D67E-4C86-B55F-90899B9BDA64}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-Example-IOCallbacks", "wolfSSL-Example-IOCallbacks\wolfSSL-Example-IOCallbacks.csproj", "{E2415718-0A15-48DB-A774-01FB0093B626}" EndProject @@ -31,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-ServerThreaded" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-PSK-Client", "wolfSSL-TLS-PSK-Client\wolfSSL-TLS-PSK-Client.csproj", "{4F92ECF5-A1D8-4A13-AD0C-6571EB03C01C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfCrypt-Test", "wolfCrypt-Test\wolfCrypt-Test.csproj", "{A4F4A244-1306-47F4-A168-31F78D7362FA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -162,58 +162,35 @@ Global {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|x64.ActiveCfg = Release|x64 {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|x64.Build.0 = Release|x64 {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|Any CPU.Build.0 = Release|Any CPU {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|Win32.ActiveCfg = Release|Any CPU {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|Win32.Build.0 = Release|Any CPU {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|x64.ActiveCfg = Release|x64 {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.Release|x64.Build.0 = Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Any CPU.ActiveCfg = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Any CPU.Build.0 = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Any CPU.ActiveCfg = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Any CPU.Build.0 = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Any CPU.ActiveCfg = DLL Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Any CPU.Build.0 = DLL Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Any CPU.ActiveCfg = Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Any CPU.Build.0 = Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.ActiveCfg = Release|x64 - {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Any CPU.ActiveCfg = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Any CPU.Build.0 = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.ActiveCfg = Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.Build.0 = Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|x64.ActiveCfg = Debug|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|x64.Build.0 = Debug|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Any CPU.ActiveCfg = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Any CPU.Build.0 = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Any CPU.ActiveCfg = DLL Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Any CPU.Build.0 = DLL Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.Build.0 = DLL Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Any CPU.ActiveCfg = Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Any CPU.Build.0 = Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.ActiveCfg = Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.Build.0 = Release|Win32 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|x64.ActiveCfg = Release|x64 - {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|x64.Build.0 = Release|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|Any CPU.ActiveCfg = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|Any CPU.Build.0 = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|Win32.ActiveCfg = Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|Win32.Build.0 = Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|x64.ActiveCfg = DLL Debug|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Debug|x64.Build.0 = DLL Debug|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|Any CPU.ActiveCfg = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|Any CPU.Build.0 = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|Any CPU.ActiveCfg = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|Any CPU.Build.0 = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.DLL Release|x64.Build.0 = DLL Release|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|Any CPU.ActiveCfg = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|Any CPU.Build.0 = DLL Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|Win32.ActiveCfg = Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|Win32.Build.0 = Release|Win32 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|x64.ActiveCfg = DLL Release|x64 + {67932048-D67E-4C86-B55F-90899B9BDA64}.Release|x64.Build.0 = DLL Release|x64 {E2415718-0A15-48DB-A774-01FB0093B626}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2415718-0A15-48DB-A774-01FB0093B626}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2415718-0A15-48DB-A774-01FB0093B626}.Debug|Win32.ActiveCfg = Debug|Any CPU @@ -310,14 +287,34 @@ Global {4F92ECF5-A1D8-4A13-AD0C-6571EB03C01C}.Release|Win32.Build.0 = Release|Any CPU {4F92ECF5-A1D8-4A13-AD0C-6571EB03C01C}.Release|x64.ActiveCfg = Release|x64 {4F92ECF5-A1D8-4A13-AD0C-6571EB03C01C}.Release|x64.Build.0 = Release|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|Win32.Build.0 = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|x64.ActiveCfg = Debug|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Debug|x64.Build.0 = Debug|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|x64.ActiveCfg = Debug|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Debug|x64.Build.0 = Debug|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|Win32.Build.0 = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|x64.ActiveCfg = Release|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.DLL Release|x64.Build.0 = Release|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|Any CPU.Build.0 = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|Win32.ActiveCfg = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|Win32.Build.0 = Release|Any CPU + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|x64.ActiveCfg = Release|x64 + {A4F4A244-1306-47F4-A168-31F78D7362FA}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {73973223-5EE8-41CA-8E88-1D60E89A237B} = {252D09D0-D007-4AEB-9F7A-A74408039A8A} - {611E8971-46E0-4D0A-B5A1-632C3B00CB80} = {252D09D0-D007-4AEB-9F7A-A74408039A8A} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {63D316F8-C4EE-449A-B9A6-FC673C4D5D31} EndGlobalSection diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs new file mode 100644 index 0000000000..2e5f30e938 --- /dev/null +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs @@ -0,0 +1,2953 @@ +/* wolfCrypt.cs + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +using System; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; + +namespace wolfSSL.CSharp +{ + public class wolfcrypt + { + private const string wolfssl_dll = "wolfssl.dll"; + + /******************************** + * Init wolfSSL library + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfCrypt_Init(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfCrypt_Cleanup(); + + + /******************************** + * Random + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_rng_new(IntPtr nonce, UInt32 nonceSz, IntPtr heap); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wc_rng_free(IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RNG_GenerateBlock(IntPtr rng, IntPtr output, UInt32 sz); + + + /******************************** + * ECC + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_ecc_key_new(IntPtr heap); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wc_ecc_key_free(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_set_rng(IntPtr key, IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_make_key_ex(IntPtr rng, int keysize, IntPtr key, int curve_id); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_sign_hash(IntPtr hashPtr, uint hashlen, IntPtr sigPtr, IntPtr siglen, IntPtr rng, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_verify_hash(IntPtr sigPtr, uint siglen, IntPtr hashPtr, uint hashlen, IntPtr res, IntPtr key); + + /* ASN.1 DER format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_EccPrivateKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_EccPublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_EccPrivateKeyToDer(IntPtr key, byte[] output, uint inLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_EccPublicKeyToDer(IntPtr key, byte[] output, uint inLen, int with_AlgCurve); + + + /******************************** + * ECIES + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_ecc_ctx_new(int flags, IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_ecc_ctx_new_ex(int flags, IntPtr rng, IntPtr heap); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wc_ecc_ctx_free(IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_reset(IntPtr ctx, IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_set_algo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_ecc_ctx_get_own_salt(IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_set_peer_salt(IntPtr ctx, IntPtr salt); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_set_own_salt(IntPtr ctx, IntPtr salt, uint sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_set_kdf_salt(IntPtr ctx, IntPtr salt, uint sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_ctx_set_info(IntPtr ctx, IntPtr info, int sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_encrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_encrypt_ex(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx, int compressed); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_decrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx); + + + /******************************** + * ECDHE + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_ecc_shared_secret(IntPtr privateKey, IntPtr publicKey, byte[] outSharedSecret, ref int outlen); + + + /******************************** + * RSA + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr wc_NewRsaKey(IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_InitRsaKey(IntPtr key, IntPtr heap); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wc_FreeRsaKey(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_MakeRsaKey(IntPtr key, int keysize, Int32 exponent, IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaSSL_Sign(IntPtr hashPtr, int hashLen, IntPtr sigPtr, int sigLen, IntPtr key, IntPtr rng); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaSSL_Verify(IntPtr sigPtr, int sigLen, IntPtr hashPtr, int hashLen, IntPtr key); + + /* ASN.1 DER format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPublicEncrypt(IntPtr inPtr, int inLen, IntPtr outPtr, int outLen, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPrivateDecrypt(IntPtr inPtr, int inLen, IntPtr outPtr, int outLen, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPrivateKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPublicKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz); + + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPSS_Sign(IntPtr hashPtr, int hashLen, IntPtr sigPtr, int sigLen, int hashType, IntPtr rng, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPSS_Verify(IntPtr sigPtr, int sigLen, IntPtr hashPtr, int hashLen, int hashType, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_RsaPSS_CheckPadding(IntPtr sigPtr, int sigLen, int hashType, IntPtr key); + + + /******************************** + * ED25519 + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr wc_ed25519_new(IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_init(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern void wc_ed25519_free(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_make_key(IntPtr rng, int keysize, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_sign_msg(IntPtr inMsg, uint inlen, IntPtr outMsg, ref uint outlen, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_verify_msg(IntPtr sig, uint siglen, IntPtr msg, uint msgLen, ref int ret, IntPtr key); + + /* ASN.1 DER format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Ed25519PrivateKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Ed25519PublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Ed25519KeyToDer(IntPtr key, byte[] output, uint inLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Ed25519PrivateKeyToDer(IntPtr key, byte[] output, uint inLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Ed25519PublicKeyToDer(IntPtr key, byte[] output, uint inLen, int withAlg); + + /* RAW format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_make_public(IntPtr key, IntPtr pubKey, uint pubKeySz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_import_public(IntPtr inMsg, uint inLen, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_export_public(IntPtr key, IntPtr outMsg, ref uint outLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_export_private(IntPtr key, IntPtr outMsg, ref uint outLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_ed25519_size(IntPtr key); + + + /******************************** + * Curve25519 + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr wc_curve25519_new(IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_init(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wc_curve25519_free(IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_make_key(IntPtr rng, int keysize, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_shared_secret(IntPtr privateKey, IntPtr publicKey, byte[] outSharedSecret, ref int outlen); + + /* ASN.1 DER format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Curve25519PrivateKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Curve25519PublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Curve25519PrivateKeyToDer(IntPtr key, byte[] output, uint inLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_Curve25519PublicKeyToDer(IntPtr key, byte[] output, uint inLen, int withAlg); + + /* RAW format */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_import_private(IntPtr privKey, int privKeySz, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_curve25519_export_public(IntPtr key, byte[] outBuffer, ref uint outLen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_import_public(IntPtr pubKey, int pubKeySz, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_export_public(IntPtr key, IntPtr outPubKey, ref int outlen); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private static extern int wc_curve25519_export_key_raw(IntPtr key, byte[] priv, ref uint privSz, byte[] pub, ref uint pubSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_import_private_raw(IntPtr privKey, IntPtr pubKey, IntPtr key); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_curve25519_export_private_raw(IntPtr key, IntPtr outPrivKey, IntPtr outPubKey); + + + /******************************** + * AES-GCM + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_AesNew(IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesFree(IntPtr aes); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesInit(IntPtr aes, IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesGcmInit(IntPtr aes, IntPtr key, uint len, IntPtr iv, uint ivSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesGcmSetKey(IntPtr aes, IntPtr key, uint len); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesGcmEncrypt(IntPtr aes, IntPtr output, IntPtr input, uint sz, IntPtr iv, uint ivSz, IntPtr authTag, uint authTagSz, IntPtr authIn, uint authInSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_AesGcmDecrypt(IntPtr aes, IntPtr output, IntPtr input, uint sz, IntPtr iv, uint ivSz, IntPtr authTag, uint authTagSz, IntPtr authIn, uint authInSz); + + + /******************************** + * HASH + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_HashNew(uint hashType, IntPtr heap, int devId); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_HashInit(IntPtr hash, uint hashType); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_HashUpdate(IntPtr hash, uint hashType, IntPtr data, uint dataSz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_HashFinal(IntPtr hash, uint hashType, IntPtr output); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_HashFree(IntPtr hash, uint hashType); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wc_HashGetDigestSize(uint hashType); + + + /******************************** + * Logging + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wc_GetErrorString(int error); + + public delegate void loggingCb(int lvl, StringBuilder msg); + private static loggingCb internal_log; + + /// + /// Log a message to set logging function + /// + /// Level of log message + /// Message to log + private static void log(int lvl, string msg) + { + /* if log is not set then print nothing */ + if (internal_log == null) + return; + StringBuilder ptr = new StringBuilder(msg); + internal_log(lvl, ptr); + } + + + /******************************** + * Enum types from wolfSSL library + */ + /* Logging levels */ + public static readonly int ERROR_LOG = 0; + public static readonly int INFO_LOG = 1; + public static readonly int ENTER_LOG = 2; + public static readonly int LEAVE_LOG = 3; + public static readonly int OTHER_LOG = 4; + public static readonly int INVALID_DEVID = -2; + public static readonly int ECC_MAX_SIG_SIZE = 141; /* ECC max sig size */ + public static readonly int ECC_KEY_SIZE = 32; /* ECC key size */ + public static readonly int MAX_ECIES_TEST_SZ = 200; /* ECIES max sig size */ + public static readonly int ED25519_SIG_SIZE = 64; /* ED25519 pub + priv */ + public static readonly int ED25519_KEY_SIZE = 32; /* Private key only */ + public static readonly int ED25519_PUB_KEY_SIZE = 32; /* Compressed public */ + public static readonly int AES_128_KEY_SIZE = 16; /* for 128 bit */ + public static readonly int AES_192_KEY_SIZE = 24; /* for 192 bit */ + public static readonly int AES_256_KEY_SIZE = 32; /* for 256 bit */ + public static readonly int AES_BLOCK_SIZE = 16; + + /* Error codes */ + public static readonly int SUCCESS = 0; + public static readonly int SIG_VERIFY_E = -229; /* wolfcrypt signature verify error */ + public static readonly int MEMORY_E = -125; /* Out of memory error */ + public static readonly int EXCEPTION_E = -1; + public static readonly int BUFFER_E = -131; /* RSA buffer error, output too small/large */ + + + /*********************************************************************** + * Class Public Functions + **********************************************************************/ + + /// + /// Initialize wolfCrypt library + /// + /// 0 on success + public static int Init() + { + int ret; + try + { + ret = wolfCrypt_Init(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfCrypt init error " + e.ToString()); + ret = EXCEPTION_E; + } + return ret; + } + + /// + /// Clean up wolfCrypt library memory + /// + /// 0 on success + public static int Cleanup() + { + int ret; + try + { + ret = wolfCrypt_Cleanup(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfCrypt cleanup error " + e.ToString()); + ret = EXCEPTION_E; + } + return ret; + } + + + /*********************************************************************** + * Random + **********************************************************************/ + + /// + /// Create new WC_RNG context + /// + /// Pointer to allocated WC_RNG or null + public static IntPtr RandomNew() + { + IntPtr rng; + + try + { + /* Allocate and init new WC_RNG structure */ + rng = wc_rng_new( + IntPtr.Zero, 0, /* Nonce (optional / used by FIPS only) */ + IntPtr.Zero); /* Heap hint for static memory only */ + } + catch (Exception e) + { + log(ERROR_LOG, "random new exception " + e.ToString()); + rng = IntPtr.Zero; + } + + return rng; + } + + /// + /// Free WC_RNG context + /// + /// Pointer to allocated WC_RNG + public static void RandomFree(IntPtr rng) + { + if (rng != IntPtr.Zero) + { + /* Free WC_RNG structure */ + wc_rng_free(rng); + } + } + + /// + /// Generate random data (use existing WC_RNG context) + /// + /// WC_RNG created from RandomNew() + /// buffer to populate random data + /// size of buffer + /// 0=success or negative for error + public static int Random(IntPtr rng, byte[] buf, int sz) + { + int ret; + IntPtr data; + + try + { + /* Allocate global buffer for wolfAPI random */ + data = Marshal.AllocHGlobal(sz); + if (data != IntPtr.Zero) + { + /* Generate random block */ + ret = wc_RNG_GenerateBlock(rng, data, Convert.ToUInt32(sz)); + if (ret == 0) + { + /* copy returned data */ + Marshal.Copy(data, buf, 0, sz); + } + else + { + log(ERROR_LOG, "random generate block error " + ret + ": " + GetError(ret)); + } + Marshal.FreeHGlobal(data); + } + else + { + ret = MEMORY_E; + } + } + catch (Exception e) + { + log(ERROR_LOG, "random generate block exception " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Generate random data (single shot) + /// + /// buffer to populate random data + /// size of buffer + /// 0=success or negative for error + public static int Random(byte[] buf, int sz) + { + int ret; + IntPtr rng = RandomNew(); + if (rng == IntPtr.Zero) + { + return MEMORY_E; + } + ret = Random(rng, buf, sz); + RandomFree(rng); + return ret; + } + /* END Random */ + + + /*********************************************************************** + * ECC + **********************************************************************/ + + /// + /// Generate a new ECC private / public key pair + /// + /// Key size in bytes (example: SECP256R1 = 32) + /// Allocated ECC key structure or null + public static IntPtr EccMakeKey(int keysize, IntPtr rng) + { + int ret; + IntPtr key = IntPtr.Zero; + + try + { + /* Allocate and init new WC_RNG structure */ + key = wc_ecc_key_new(IntPtr.Zero); + if (key != IntPtr.Zero) + { + ret = wc_ecc_make_key_ex(rng, keysize, key, 0); /* 0=use default curve */ + if (ret != 0) + { + EccFreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC make key exception " + e.ToString()); + + EccFreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Sets the ECC rng structure + /// + /// Supplied key as a pointer + /// rng context as a pointer + /// Returns 0 on success + public static int EccSetRng(IntPtr key, IntPtr rng) + { + int ret = 0; + + try + { + /* Check */ + if (key == IntPtr.Zero) + { + log(ERROR_LOG, "Invalid key or rng pointer."); + return MEMORY_E; + } + + /* Set ECC rng */ + ret = wc_ecc_set_rng(key, rng); + if (ret != 0) + { + log(ERROR_LOG, "ECC set rng failed returned:" + ret); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC set rng exception " + e.ToString()); + } + + return ret; + } + + /// + /// Generate a new ECC private / public key pair + /// + /// ASN.1 private key buffer (see ecc_clikey_der_256) + /// Allocated ECC key structure or null + public static IntPtr EccImportKey(byte[] keyASN1) + { + int ret; + IntPtr key = IntPtr.Zero; + + try + { + key = wc_ecc_key_new(IntPtr.Zero); + if (key != IntPtr.Zero) + { + IntPtr idx = Marshal.AllocHGlobal(sizeof(uint)); + IntPtr keydata = Marshal.AllocHGlobal(keyASN1.Length); + Marshal.WriteInt32(idx, 0); + Marshal.Copy(keyASN1, 0, keydata, keyASN1.Length); + ret = wc_EccPrivateKeyDecode(keydata, idx, key, Convert.ToUInt32(keyASN1.Length)); + if (ret != 0) + { + EccFreeKey(key); + key = IntPtr.Zero; + } + Marshal.FreeHGlobal(idx); /* not used */ + Marshal.FreeHGlobal(keydata); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC import key exception " + e.ToString()); + EccFreeKey(key); /* make sure its free'd */ + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Sign a hash using ECC + /// + /// ECC key structure + /// Hash to sign + /// Buffer to receive the signature + /// Length of the signature on success, otherwise a negative error code + public static int EccSign(IntPtr key, byte[] hash, byte[] signature) + { + int ret; + int signedLength = 0; + IntPtr hashPtr = IntPtr.Zero; + IntPtr sigPtr = IntPtr.Zero; + IntPtr sigLen = IntPtr.Zero; + IntPtr rng = IntPtr.Zero; + + try + { + rng = RandomNew(); + hashPtr = Marshal.AllocHGlobal(hash.Length); + sigPtr = Marshal.AllocHGlobal(signature.Length); + sigLen = Marshal.AllocHGlobal(sizeof(uint)); + + Marshal.WriteInt32(sigLen, signature.Length); + Marshal.Copy(hash, 0, hashPtr, hash.Length); + ret = wc_ecc_sign_hash(hashPtr, Convert.ToUInt32(hash.Length), sigPtr, sigLen, rng, key); + + /* Output actual signature length */ + if (ret == 0) + { + signedLength = Marshal.ReadInt32(sigLen); + if (signedLength <= signature.Length) + { + Marshal.Copy(sigPtr, signature, 0, signedLength); + } + else + { + ret = BUFFER_E; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC sign exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr); + if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr); + if (sigLen != IntPtr.Zero) Marshal.FreeHGlobal(sigLen); + if (rng != IntPtr.Zero) RandomFree(rng); + } + + return ret == 0 ? signedLength : ret; + } + + /// + /// Verify a signature using ECC + /// + /// ECC key structure + /// Signature to verify + /// Expected hash value + /// 0 on success, otherwise an error code + public static int EccVerify(IntPtr key, byte[] signature, byte[] hash) + { + int ret; + IntPtr hashPtr = IntPtr.Zero; + IntPtr sigPtr = IntPtr.Zero; + IntPtr res = IntPtr.Zero; + + try + { + hashPtr = Marshal.AllocHGlobal(hash.Length); + sigPtr = Marshal.AllocHGlobal(signature.Length); + res = Marshal.AllocHGlobal(sizeof(int)); + + Marshal.Copy(hash, 0, hashPtr, hash.Length); + Marshal.Copy(signature, 0, sigPtr, signature.Length); + + ret = wc_ecc_verify_hash(sigPtr, Convert.ToUInt32(signature.Length), hashPtr, Convert.ToUInt32(hash.Length), res, key); + + if (ret == 0) + { + int verifyResult = Marshal.ReadInt32(res); + ret = verifyResult == 1 ? 0 : EXCEPTION_E; + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC verify exception " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr); + if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr); + if (res != IntPtr.Zero) Marshal.FreeHGlobal(res); + } + + return ret; + } + + /// + /// Export ECC Private Key to DER format + /// + /// ECC key structure + /// DER-encoded private key as byte array + public static int EccExportPrivateKeyToDer(IntPtr key, out byte[] derKey) + { + int ret; + derKey = null; + + try + { + int bufferSize = wc_EccPrivateKeyToDer(key, null, 0); + if (bufferSize < 0) { + log(ERROR_LOG, "ECC private key get size failed " + bufferSize.ToString()); + return bufferSize; + } + derKey = new byte[bufferSize]; + ret = wc_EccPrivateKeyToDer(key, derKey, (uint)bufferSize); + if (ret < 0) + { + log(ERROR_LOG, "ECC private key to der failed " + ret.ToString()); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC export private exception " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Export ECC Public Key to DER format + /// + /// ECC key structure + /// Include algorithm curve in the output + /// DER-encoded public key as byte array + public static int EccExportPublicKeyToDer(IntPtr key, out byte[] derKey, bool includeCurve) + { + int ret; + derKey = null; + + try + { + int bufferSize = wc_EccPublicKeyToDer(key, null, 0, includeCurve ? 1 : 0); + if (bufferSize < 0) { + log(ERROR_LOG, "ECC public key get size failed " + bufferSize.ToString()); + return bufferSize; + } + derKey = new byte[bufferSize]; + ret = wc_EccPublicKeyToDer(key, derKey, (uint)bufferSize, includeCurve ? 1 : 0); + if (ret < 0) + { + log(ERROR_LOG, "ECC public key to der failed " + ret.ToString()); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC export public exception " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Import ECC Public Key from DER format + /// + /// DER-encoded public key + /// Allocated ECC key structure or null + public static IntPtr EccImportPublicKeyFromDer(byte[] keyDer) + { + int ret; + IntPtr key = IntPtr.Zero; + + try + { + key = wc_ecc_key_new(IntPtr.Zero); + if (key != IntPtr.Zero) + { + uint idx = 0; + ret = wc_EccPublicKeyDecode(keyDer, ref idx, key, (uint)keyDer.Length); + if (ret != 0) + { + EccFreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC import public key exception " + e.ToString()); + EccFreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Free an ECC key structure + /// + /// ECC key structure allocated using EccMakeKey() or EccImportKey() + public static void EccFreeKey(IntPtr key) + { + if (key != IntPtr.Zero) + { + wc_ecc_key_free(key); + } + } + /* END ECC */ + + + /*********************************************************************** + * ECIES + **********************************************************************/ + + /// + /// Create a new ECIES context with flags, RNG, and custom heap. + /// + /// Flags for the context initialization. + /// Random Number Generator (RNG) pointer. + /// Custom heap pointer for memory allocations. + /// Pointer to the newly created ECIES context or IntPtr.Zero on failure. + public static IntPtr EciesNewCtx(int flags, IntPtr rng, IntPtr heap) + { + IntPtr ctx = IntPtr.Zero; + heap = IntPtr.Zero; + + try + { + ctx = wc_ecc_ctx_new_ex(flags, rng, heap); + if (ctx == IntPtr.Zero) + { + log(ERROR_LOG, "ECIES context creation with custom heap failed: returned IntPtr.Zero"); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES context creation with custom heap failed: " + e.ToString()); + return IntPtr.Zero; + } + + return ctx; + } + + /// + /// Reset the ECIES context with a new RNG. + /// + /// Pointer to the ECIES context to reset. + /// New RNG to set. + /// 0 on success, or a negative error code on failure. + public static int EciesCtxReset(IntPtr ctx, IntPtr rng) + { + int ret; + + try + { + ret = wc_ecc_ctx_reset(ctx, rng); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES context reset exception: " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Set encryption, KDF, and MAC algorithms for the ECIES context. + /// + /// Pointer to the ECIES context. + /// Encryption algorithm identifier. + /// Key Derivation Function (KDF) algorithm identifier. + /// MAC algorithm identifier. + /// 0 on success, or a negative error code on failure. + public static int EciesSetAlgo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo) + { + int ret; + + try + { + ret = wc_ecc_ctx_set_algo(ctx, encAlgo, kdfAlgo, macAlgo); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES set algorithm exception: " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Get the ECIES own salt as a byte array. + /// + /// Pointer to the ECIES context. + /// Byte array representing the own salt, or null if there is an error. + public static byte[] EciesGetOwnSalt(IntPtr ctx) + { + IntPtr saltPtr = IntPtr.Zero; + byte[] salt = null; + + try + { + /* Check ctx */ + if (ctx == IntPtr.Zero) + { + log(ERROR_LOG, "Invalid ECIES context pointer."); + return null; + } + + /* Get own salt */ + saltPtr = wc_ecc_ctx_get_own_salt(ctx); + if (saltPtr == IntPtr.Zero) + { + log(ERROR_LOG, "Failed to get own salt."); + return null; + } + + /* Allocate salt size and copy to byte array */ + salt = new byte[(int)ecKeySize.EXCHANGE_SALT_SZ]; + Marshal.Copy(saltPtr, salt, 0, (int)ecKeySize.EXCHANGE_SALT_SZ); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES get own salt exception: " + e.ToString()); + return null; + } + finally + { + /* Cleanup */ + if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr); + } + + return salt; + } + + /// + /// Set the peer salt for the ECIES context. + /// + /// Pointer to the ECIES context. + /// Peer salt as a byte array. + /// 0 on success, or a negative error code on failure. + public static int EciesSetPeerSalt(IntPtr ctx, byte[] salt) + { + IntPtr saltPtr = IntPtr.Zero; + int ret; + + try + { + /* Allocate memory */ + saltPtr = Marshal.AllocHGlobal(salt.Length); + Marshal.Copy(salt, 0, saltPtr, salt.Length); + + /* Set the peer salt */ + ret = wc_ecc_ctx_set_peer_salt(ctx, saltPtr); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES set peer salt exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr); + } + + return ret; + } + + /// + /// Set the own salt for the ECIES context. + /// + /// Pointer to the ECIES context. + /// Own salt as a byte array. + /// 0 on success, or a negative error code on failure. + public static int EciesSetOwnSalt(IntPtr ctx, byte[] salt) + { + IntPtr saltPtr = IntPtr.Zero; + uint saltSz; + int ret; + + try + { + /* Allocate memory */ + saltSz = (uint)salt.Length; + saltPtr = Marshal.AllocHGlobal(salt.Length); + Marshal.Copy(salt, 0, saltPtr, salt.Length); + + /* Set the own salt */ + ret = wc_ecc_ctx_set_own_salt(ctx, saltPtr, saltSz); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES set own salt exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr); + } + + return ret; + } + + /// + /// Set the KDF salt for the ECIES context. + /// + /// Pointer to the ECIES context. + /// KDF salt as a byte array. + /// 0 on success, or a negative error code on failure. + public static int EciesSetKdfSalt(IntPtr ctx, byte[] salt) + { + IntPtr saltPtr = IntPtr.Zero; + uint saltSz; + int ret; + + try + { + /* Allocate memory */ + saltSz = (uint)salt.Length; + saltPtr = Marshal.AllocHGlobal(salt.Length); + Marshal.Copy(salt, 0, saltPtr, salt.Length); + + /* Set the KDF salt */ + ret = wc_ecc_ctx_set_kdf_salt(ctx, saltPtr, saltSz); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES set KDF salt exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr); + } + + return ret; + } + + /// + /// Set the info for the ECIES context. + /// + /// Pointer to the ECIES context. + /// Info as a byte array. + /// 0 on success, or a negative error code on failure. + public static int EciesSetInfo(IntPtr ctx, byte[] info) + { + IntPtr infoPtr = IntPtr.Zero; + int ret; + + try + { + /* Allocate memory */ + infoPtr = Marshal.AllocHGlobal(info.Length); + Marshal.Copy(info, 0, infoPtr, info.Length); + + /* Set the info */ + ret = wc_ecc_ctx_set_info(ctx, infoPtr, info.Length); + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES set info exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (infoPtr != IntPtr.Zero) Marshal.FreeHGlobal(infoPtr); + } + + return ret; + } + + /// + /// Encrypt a message using ECIES. + /// + /// Private key. + /// Public key. + /// Message to encrypt. + /// Message size. + /// Output buffer. + /// ECIES context. + /// 0 on success, or a negative error code on failure. + public static int EciesEncrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx) + { + int ret; + int outBufferLength = 0; + IntPtr msgPtr = IntPtr.Zero; + IntPtr outBufferPtr = IntPtr.Zero; + IntPtr outSz = IntPtr.Zero; + + try + { + /* Allocate memory */ + msgPtr = Marshal.AllocHGlobal(msg.Length); + outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length); + outSz = Marshal.AllocHGlobal(sizeof(uint)); + + Marshal.WriteInt32(outSz, outBuffer.Length); + Marshal.Copy(msg, 0, msgPtr, msg.Length); + + /* Encrypt */ + ret = wc_ecc_encrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx); + if (ret < 0) + { + log(ERROR_LOG, "Failed to encrypt message using ECIES. Error code: " + ret); + } + /* Output actual output buffer length */ + if (ret == 0) + { + outBufferLength = Marshal.ReadInt32(outSz); + if (outBufferLength <= outBuffer.Length) + { + Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength); + } + else + { + ret = BUFFER_E; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES encryption exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr); + if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr); + if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz); + } + + return ret == 0 ? outBufferLength : ret; + } + + /// + /// Decrypt a message using ECIES. + /// + /// Private key. + /// Public key. + /// Encrypted message. + /// Message size. + /// Output buffer for the decrypted message. + /// ECIES context. + /// 0 on success, or a negative error code on failure. + public static int EciesDecrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx) + { + int ret; + int outBufferLength = 0; + IntPtr msgPtr = IntPtr.Zero; + IntPtr outBufferPtr = IntPtr.Zero; + IntPtr outSz = IntPtr.Zero; + + try + { + /* Allocate memory */ + msgPtr = Marshal.AllocHGlobal(msg.Length); + outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length); + outSz = Marshal.AllocHGlobal(sizeof(uint)); + + Marshal.WriteInt32(outSz, outBuffer.Length); + Marshal.Copy(msg, 0, msgPtr, msg.Length); + + /* Decrypt */ + ret = wc_ecc_decrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx); + if (ret < 0) + { + log(ERROR_LOG, "Failed to decrypt message using ECIES. Error code: " + ret); + } + /* Output actual output buffer length */ + if (ret == 0) + { + outBufferLength = Marshal.ReadInt32(outSz); + if (outBufferLength <= outBuffer.Length) + { + Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength); + } + else + { + ret = BUFFER_E; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECIES decryption exception: " + e.ToString()); + return EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr); + if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr); + if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz); + } + + return ret == 0 ? outBufferLength : ret; + } + + /// + /// Free the ECIES context. + /// + /// Pointer to the ECIES context to free. + public static void EciesFreeCtx(IntPtr ctx) + { + if (ctx != IntPtr.Zero) + { + wc_ecc_ctx_free(ctx); + } + } + + /******************************** + * ENUMS + */ + public enum ecEncAlgo { + ecAES_128_CBC = 1, /* default */ + ecAES_256_CBC = 2, + ecAES_128_CTR = 3, + ecAES_256_CTR = 4 + } + + public enum ecKdfAlgo { + ecHKDF_SHA256 = 1, /* default */ + ecHKDF_SHA1 = 2, + ecKDF_X963_SHA1 = 3, + ecKDF_X963_SHA256 = 4, + ecKDF_SHA1 = 5, + ecKDF_SHA256 = 6 + } + + public enum ecMacAlgo { + ecHMAC_SHA256 = 1, /* default */ + ecHMAC_SHA1 = 2 + } + + public enum ecKeySize { + KEY_SIZE_128 = 16, + 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 + } + + public enum ecFlags { + REQ_RESP_CLIENT = 1, + REQ_RESP_SERVER = 2 + } + /* END ECIES */ + + + /*********************************************************************** + * ECDHE + **********************************************************************/ + + /// + /// Generate a shared secret using ECC + /// + /// ECC private key + /// ECC public key + /// Buffer to receive the shared secret + /// 0 on success, otherwise an error code + public static int EcdheSharedSecret(IntPtr privateKey, IntPtr publicKey, byte[] secret, IntPtr rng) + { + int ret; + int secretLength = secret.Length; + + try + { + /* set RNG for Public Key */ + ret = EccSetRng(privateKey, rng); + if (ret != 0) + { + throw new Exception("Failed to set Public Key RNG Error code: " + ret); + } + + /* set RNG for Private Key */ + ret = EccSetRng(publicKey, rng); + if (ret != 0) + { + throw new Exception("Failed to set Private Key RNG. Error code: " + ret); + } + + /* Generate shared secret */ + if (privateKey != IntPtr.Zero || publicKey != IntPtr.Zero) + { + ret = wc_ecc_shared_secret(privateKey, publicKey, secret, ref secretLength); + if (ret != 0) + { + throw new Exception("Failed to compute ECC shared secret. Error code: " + ret); + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ECC shared secret exception " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + /* END ECDHE */ + + + /*********************************************************************** + * RSA + **********************************************************************/ + + /// + /// Generate a new RSA private/public key pair + /// + /// Pointer to the heap for memory allocation + /// (use IntPtr.Zero if not applicable) + /// Device ID (if applicable, otherwise use 0) + /// Key size in bits (example: 2048) + /// Exponent for RSA key generation (default is 65537) + /// Allocated RSA key structure or null on failure + public static IntPtr RsaMakeKey(IntPtr heap, int devId, int keysize, Int32 exponent) + { + int ret; + IntPtr key = IntPtr.Zero; + IntPtr rng = IntPtr.Zero; + + try + { + /* Allocate and init new RSA key structure */ + key = wc_NewRsaKey(heap, devId); + if (key != IntPtr.Zero) + { + rng = RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("Failed to create rng."); + } + + ret = wc_MakeRsaKey(key, keysize, exponent, rng); + if (ret != 0) + { + RsaFreeKey(key); + key = IntPtr.Zero; + } + + RandomFree(rng); + rng = IntPtr.Zero; + } + } + catch (Exception e) + { + log(ERROR_LOG, "RSA make key exception " + e.ToString()); + if (rng != IntPtr.Zero) RandomFree(rng); + if (key != IntPtr.Zero) RsaFreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + public static IntPtr RsaMakeKey(IntPtr heap, int devId, int keysize) + { + return RsaMakeKey(heap, devId, keysize, 65537); + } + + /// + /// Import an RSA private key from ASN.1 buffer + /// + /// ASN.1 private key buffer + /// Allocated RSA key structure or null + public static IntPtr RsaImportKey(byte[] keyASN1) + { + int ret; + IntPtr key = IntPtr.Zero; + + try + { + key = wc_NewRsaKey(IntPtr.Zero, INVALID_DEVID); + if (key != IntPtr.Zero) + { + IntPtr idx = Marshal.AllocHGlobal(sizeof(uint)); + IntPtr keydata = Marshal.AllocHGlobal(keyASN1.Length); + Marshal.WriteInt32(idx, 0); + Marshal.Copy(keyASN1, 0, keydata, keyASN1.Length); + ret = wc_RsaPrivateKeyDecode(keydata, idx, key, Convert.ToUInt32(keyASN1.Length)); + if (ret != 0) + { + RsaFreeKey(key); + key = IntPtr.Zero; + } + Marshal.FreeHGlobal(idx); /* not used */ + Marshal.FreeHGlobal(keydata); + } + } + catch (Exception e) + { + log(ERROR_LOG, "RSA make key exception " + e.ToString()); + RsaFreeKey(key); /* make sure its free'd */ + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Sign a hash using RSA and SSL-style padding + /// + /// RSA key structure + /// Hash to sign + /// Buffer to receive the signature + /// Length of the signature on success, otherwise an error code + public static int RsaSignSSL(IntPtr key, byte[] hash, byte[] signature) + { + IntPtr hashPtr = Marshal.AllocHGlobal(hash.Length); + IntPtr sigPtr = Marshal.AllocHGlobal(signature.Length); + IntPtr rng = IntPtr.Zero; + int ret; + + try + { + rng = RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("Failed to create RNG."); + } + + Marshal.Copy(hash, 0, hashPtr, hash.Length); + + ret = wc_RsaSSL_Sign(hashPtr, hash.Length, sigPtr, signature.Length, key, rng); + if (ret >= 0) /* `wc_RsaSSL_Sign` returns the signature length on success */ + { + Marshal.Copy(sigPtr, signature, 0, ret); + } + } + finally + { + if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr); + if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr); + if (rng != IntPtr.Zero) RandomFree(rng); + } + + return ret; + } + + /// + /// Verify a signature using RSA and SSL-style padding + /// + /// RSA key structure + /// Signature to verify + /// Expected hash value + /// 0 on success, otherwise an error code + public static int RsaVerifySSL(IntPtr key, byte[] signature, byte[] hash) + { + IntPtr hashPtr = IntPtr.Zero; + IntPtr sigPtr = IntPtr.Zero; + int ret; + + try + { + hashPtr = Marshal.AllocHGlobal(hash.Length); + sigPtr = Marshal.AllocHGlobal(signature.Length); + + Marshal.Copy(signature, 0, sigPtr, signature.Length); + + ret = wc_RsaSSL_Verify(sigPtr, signature.Length, hashPtr, hash.Length, key); + + if (ret == hash.Length) + { + byte[] verifiedHash = new byte[hash.Length]; + Marshal.Copy(hashPtr, verifiedHash, 0, hash.Length); + + if (ByteArrayVerify(verifiedHash, hash)) + { + ret = 0; + } + else + { + ret = SIG_VERIFY_E; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "RSA verify exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr); + if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr); + } + + return ret; + } + + /// + /// Encrypt data using RSA public key encryption + /// + /// RSA key structure + /// Data to encrypt + /// Buffer to receive the encrypted data + /// 0 on success, otherwise an error code + public static int RsaPublicEncrypt(IntPtr key, byte[] input, byte[] output) + { + IntPtr inPtr = Marshal.AllocHGlobal(input.Length); + IntPtr outPtr = Marshal.AllocHGlobal(output.Length); + Marshal.Copy(input, 0, inPtr, input.Length); + + int ret = wc_RsaPublicEncrypt(inPtr, input.Length, outPtr, output.Length, key); + + if (ret > 0) + { + Marshal.Copy(outPtr, output, 0, ret); + } + + Marshal.FreeHGlobal(inPtr); + Marshal.FreeHGlobal(outPtr); + + return ret > 0 ? 0 : ret; + } + + /// + /// Decrypt data using RSA private key decryption + /// + /// RSA key structure + /// Encrypted data + /// Buffer to receive the decrypted data + /// 0 on success, otherwise an error code + public static int RsaPrivateDecrypt(IntPtr key, byte[] input, byte[] output) + { + IntPtr inPtr = Marshal.AllocHGlobal(input.Length); + IntPtr outPtr = Marshal.AllocHGlobal(output.Length); + Marshal.Copy(input, 0, inPtr, input.Length); + + int ret = wc_RsaPrivateDecrypt(inPtr, input.Length, outPtr, output.Length, key); + + if (ret > 0) + { + Marshal.Copy(outPtr, output, 0, ret); + } + + Marshal.FreeHGlobal(inPtr); + Marshal.FreeHGlobal(outPtr); + + return ret > 0 ? 0 : ret; + } + + /// + /// Free an RSA key structure + /// + /// RSA key structure allocated using RsaMakeKey() or RsaImportKey() + public static void RsaFreeKey(IntPtr key) + { + if (key != IntPtr.Zero) + { + wc_FreeRsaKey(key); + } + } + /* END RSA */ + + + /*********************************************************************** + * ED25519 + **********************************************************************/ + + /// + /// Generate a new ED25519 key pair with a specified heap, device ID, and internally managed RNG. + /// + /// Heap to use for memory allocations (can be IntPtr.Zero). + /// Device ID for hardware-based keys (can be 0 for software). + /// 0 on success, or an error code on failure. + public static IntPtr Ed25519MakeKey(IntPtr heap, int devId) + { + int ret = 0; + IntPtr rng = IntPtr.Zero; + IntPtr key = IntPtr.Zero; + + try + { + rng = RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("Failed to create RNG."); + } + + key = wc_ed25519_new(heap, devId); + if (key != IntPtr.Zero) + { + ret = wc_ed25519_make_key(rng, 32, key); + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 make key exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (rng != IntPtr.Zero) RandomFree(rng); + if (ret != 0) + { + wc_ed25519_free(key); + key = IntPtr.Zero; + } + } + + return key; + } + + /// + /// Sign a message with an ED25519 private key. + /// + /// Message to be signed + /// Buffer to receive the signature + /// Private key used for signing + /// 0 on success, otherwise an error code + public static int Ed25519SignMsg(byte[] inMsg, out byte[] outMsg, IntPtr key) + { + int ret; + IntPtr inMsgPtr = Marshal.AllocHGlobal(inMsg.Length); + IntPtr outMsgPtr = Marshal.AllocHGlobal(ED25519_SIG_SIZE); + outMsg = null; + + try + { + Marshal.Copy(inMsg, 0, inMsgPtr, inMsg.Length); + uint outMsgSize = (uint)ED25519_SIG_SIZE; + ret = wc_ed25519_sign_msg(inMsgPtr, (uint)inMsg.Length, outMsgPtr, ref outMsgSize, key); + if (ret == 0) + { + outMsg = new byte[outMsgSize]; + Marshal.Copy(outMsgPtr, outMsg, 0, (int)outMsgSize); + } + } + finally + { + /* Clenup */ + if (inMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(inMsgPtr); + if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr); + } + + return ret; + } + + /// + /// Verify a signature of a message with an ED25519 public key. + /// + /// Signature to verify + /// Message that was signed + /// Public key used for verification + /// 0 if the verification succeeds, otherwise an error code + public static int Ed25519VerifyMsg(byte[] sig, byte[] msg, IntPtr key) + { + IntPtr sigPtr = IntPtr.Zero; + IntPtr msgPtr = IntPtr.Zero; + int ret = 0; + + try + { + /* Allocate memory */ + sigPtr = Marshal.AllocHGlobal(sig.Length); + msgPtr = Marshal.AllocHGlobal(msg.Length); + + Marshal.Copy(sig, 0, sigPtr, sig.Length); + Marshal.Copy(msg, 0, msgPtr, msg.Length); + + int verify = 0; + ret = wc_ed25519_verify_msg(sigPtr, (uint)sig.Length, msgPtr, (uint)msg.Length, ref verify, key); + + if (ret == 0 && verify == 1) + { + ret = 0; + } + else + { + ret = SIG_VERIFY_E; + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 verify exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr); + if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr); + } + + return ret; + } + + /// + /// Decode an ED25519 private key from DER format. + /// + /// DER-encoded private key as byte array. + /// Allocated ED25519 key structure or IntPtr.Zero on failure. + public static IntPtr Ed25519PrivateKeyDecode(byte[] input) + { + IntPtr key = IntPtr.Zero; + uint idx = 0; + int ret; + + try + { + key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID); + if (key != IntPtr.Zero) + { + ret = wc_Ed25519PrivateKeyDecode(input, ref idx, key, (uint)input.Length); + if (ret != 0) + { + Ed25519FreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 private key decode exception: " + e.ToString()); + if (key != IntPtr.Zero) Ed25519FreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Decode an ED25519 public key from DER format. + /// + /// DER-encoded public key as byte array. + /// Allocated ED25519 key structure or IntPtr.Zero on failure. + public static IntPtr Ed25519PublicKeyDecode(byte[] input) + { + IntPtr key = IntPtr.Zero; + uint idx = 0; + int ret; + + try + { + key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID); + if (key != IntPtr.Zero) + { + ret = wc_Ed25519PublicKeyDecode(input, ref idx, key, (uint)input.Length); + if (ret != 0) + { + Ed25519FreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 public key decode exception: " + e.ToString()); + if (key != IntPtr.Zero) Ed25519FreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Export an ED25519 key to DER format. + /// + /// ED25519 key structure. + /// DER-encoded public key as byte array. + /// DER-encoded key as byte array. + public static int Ed25519ExportKeyToDer(IntPtr key, out byte[] privKey) + { + int ret; + privKey = null; + + try + { + /* Get length */ + int len = wc_Ed25519KeyToDer(key, null, 0); + if (len < 0) + { + log(ERROR_LOG, "Failed to determine length. Error code: " + len); + return len; + } + + privKey = new byte[len]; + ret = wc_Ed25519KeyToDer(key, privKey, (uint)privKey.Length); + + if (ret < 0) + { + log(ERROR_LOG, "Failed to export ED25519 private key to DER format. Error code: " + ret); + return ret; + } + } + catch(Exception e) + { + log(ERROR_LOG, "ED25519 export private key to DER exception: " + e.ToString()); + return EXCEPTION_E; + } + + return ret; + } + + /// + /// Export an ED25519 private key to DER format. + /// + /// ED25519 private key structure. + /// DER-encoded private key as byte array. + /// DER-encoded private key as byte array. + public static int Ed25519ExportPrivateKeyToDer(IntPtr key, out byte[] derKey) + { + int ret; + derKey = null; + + try + { + /* Determine length */ + int len = wc_Ed25519PrivateKeyToDer(key, null, 0); + if (len < 0) + { + log(ERROR_LOG, "Failed to determine length. Error code: " + len); + return len; + } + + derKey = new byte[len]; + ret = wc_Ed25519PrivateKeyToDer(key, derKey, (uint)derKey.Length); + + if (ret < 0) + { + log(ERROR_LOG, "Failed to export ED25519 private key to DER format. Error code: " + ret); + return ret; + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 export private key to DER exception: " + e.ToString()); + return EXCEPTION_E; + } + + return ret; + } + + /// + /// Export an ED25519 public key to DER format. + /// + /// ED25519 public key structure. + /// Whether to include the algorithm identifier in the output. + /// DER-encoded public key as byte array. + /// An error code indicating success (0) or failure (negative value). + public static int Ed25519ExportPublicKeyToDer(IntPtr key, out byte[] pubKey, bool includeAlg) + { + int ret; + pubKey = null; + + try + { + /* Determine length */ + int len = wc_Ed25519PublicKeyToDer(key, null, 0, 1); + if (len < 0) + { + log(ERROR_LOG, "Failed to determine length. Error code: " + len); + return len; + } + + pubKey = new byte[len]; + ret = wc_Ed25519PublicKeyToDer(key, pubKey, (uint)pubKey.Length, includeAlg ? 1 : 0); + if (ret < 0) + { + log(ERROR_LOG, "Failed to export ED25519 public key to DER format. Error code: " + ret); + return ret; + } + } + catch (Exception e) + { + log(ERROR_LOG, "ED25519 export public key to DER exception: " + e.ToString()); + return EXCEPTION_E; + } + + return ret; + } + + /// + /// Free an ED25519 key. + /// + /// Key to be freed + public static void Ed25519FreeKey(IntPtr key) + { + wc_ed25519_free(key); + } + /* END ED25519 */ + + + /*********************************************************************** + * RAW ED25519 + **********************************************************************/ + + /// + /// Initialize an ED25519 key. + /// + /// Buffer to receive the initialized key + /// 0 on success, otherwise an error code + public static int Ed25519InitKey(out IntPtr key) + { + key = IntPtr.Zero; + try + { + key = Marshal.AllocHGlobal(ED25519_SIG_SIZE); + int ret = wc_ed25519_init(key); + + if (ret != 0) + { + Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + } + + return ret; + } + catch + { + /* Cleanup */ + Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + throw; + } + } + + /// + /// Import a public key into an ED25519 key structure. + /// + /// Public key to import + /// Length of the public key + /// Buffer to receive the imported key + /// 0 on success, otherwise an error code + public static int Ed25519ImportPublic(byte[] inMsg, uint inLen, out IntPtr key) + { + int ret; + key = IntPtr.Zero; + IntPtr inMsgPtr = IntPtr.Zero; + + try + { + /* Allocate memory */ + key = Marshal.AllocHGlobal(ED25519_PUB_KEY_SIZE); + if (key == IntPtr.Zero) + { + throw new OutOfMemoryException("Failed to allocate memory for the key."); + } + + inMsgPtr = Marshal.AllocHGlobal(inMsg.Length); + if (inMsgPtr == IntPtr.Zero) + { + throw new OutOfMemoryException("Failed to allocate memory for the input message."); + } + Marshal.Copy(inMsg, 0, inMsgPtr, inMsg.Length); + + ret = wc_ed25519_import_public(inMsgPtr, inLen, key); + if (ret != 0) + { + return ret; + } + } + catch (Exception ex) + { + Console.WriteLine($"Exception in EdImportPublic: {ex.Message}"); + + return EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (inMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(inMsgPtr); + if (key != IntPtr.Zero) Marshal.FreeHGlobal(key); + } + + return ret; + } + + /// + /// Export a public key from an ED25519 key structure. + /// + /// ED25519 key structure + /// Buffer to receive the exported public key + /// Length of the exported public key + /// 0 on success, otherwise an error code + public static int Ed25519ExportPublic(IntPtr key, byte[] outMsg, out uint outLen) + { + int ret; + IntPtr outMsgPtr = IntPtr.Zero; + + try + { + outMsgPtr = Marshal.AllocHGlobal(outMsg.Length); + outLen = (uint)outMsg.Length; + ret = wc_ed25519_export_public(key, outMsgPtr, ref outLen); + if (ret == 0) + { + Marshal.Copy(outMsgPtr, outMsg, 0, (int)outLen); + } + else + { + outLen = 0; + } + } + finally + { + /* Cleanup */ + if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr); + } + + return ret; + } + + /// + /// Export a private key from an ED25519 key structure. + /// + /// ED25519 key structure + /// Buffer to receive the exported private key + /// Length of the exported private key + /// 0 on success, otherwise an error code + public static int Ed25519ExportPrivate(IntPtr key, byte[] outMsg, out uint outLen) + { + int ret; + IntPtr outMsgPtr = IntPtr.Zero; + + try + { + outMsgPtr = Marshal.AllocHGlobal(outMsg.Length); + outLen = (uint)outMsg.Length; + ret = wc_ed25519_export_private(key, outMsgPtr, ref outLen); + if (ret == 0) + { + Marshal.Copy(outMsgPtr, outMsg, 0, (int)outLen); + } + else + { + outLen = 0; + } + } + finally + { + /* Cleanup */ + if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr); + } + + return ret; + } + + /// + /// Generate a public key from a private key. + /// + /// The private key used to generate the public key + /// Buffer to receive the public key + /// Size of the public key buffer + /// 0 on success, otherwise an error code + public static int Ed25519MakePublic(IntPtr key, byte[] pubKey, out uint pubKeySz) + { + int ret; + IntPtr pubKeyPtr = Marshal.AllocHGlobal(pubKey.Length); + + try + { + pubKeySz = (uint)pubKey.Length; + ret = wc_ed25519_make_public(key, pubKeyPtr, pubKeySz); + if (ret == 0) + { + Marshal.Copy(pubKeyPtr, pubKey, 0, (int)pubKeySz); + } + } + finally + { + /* Cleanup */ + if (pubKeyPtr != IntPtr.Zero) Marshal.FreeHGlobal(pubKeyPtr); + } + + return ret; + } + + /// + /// Get the size of the ED25519 key. + /// + /// ED25519 key structure + /// Size of the key, or an error code if failed + public static int Ed25519GetKeySize(IntPtr key) + { + return wc_ed25519_size(key); + } + /* END RAW ED25519 */ + + + /*********************************************************************** + * Curve25519 + **********************************************************************/ + + /// + /// Generate a new Curve25519 key pair with a specified heap, device ID, and internally managed RNG. + /// + /// Heap to use for memory allocations (can be IntPtr.Zero). + /// Device ID for hardware-based keys (can be 0 for software). + /// 0 on success, or an error code on failure. + public static IntPtr Curve25519MakeKey(IntPtr heap, int devId) + { + int ret = 0; + IntPtr rng = IntPtr.Zero; + IntPtr key = IntPtr.Zero; + + try + { + rng = RandomNew(); + if (rng == IntPtr.Zero) + { + throw new Exception("Failed to create RNG."); + } + + key = wc_curve25519_new(heap, devId); + if (key != IntPtr.Zero) + { + ret = wc_curve25519_make_key(rng, 32, key); + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 make key exception: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (rng != IntPtr.Zero) RandomFree(rng); + if (ret != 0) + { + wc_curve25519_free(key); + key = IntPtr.Zero; + } + } + + return key; + } + + /// + /// Decode an Curve25519 private key from DER format. + /// + /// DER-encoded private key as byte array. + /// Allocated Curve25519 key structure or IntPtr.Zero on failure. + public static IntPtr Curve25519PrivateKeyDecode(byte[] input) + { + IntPtr key = IntPtr.Zero; + uint idx = 0; + int ret; + + try + { + key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID); + if (key != IntPtr.Zero) + { + ret = wc_Ed25519PrivateKeyDecode(input, ref idx, key, (uint)input.Length); + if (ret != 0) + { + Curve25519FreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 private key decode exception: " + e.ToString()); + if (key != IntPtr.Zero) Curve25519FreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Decode an Curve25519 public key from DER format. + /// + /// DER-encoded public key as byte array. + /// Allocated Curve25519 key structure or IntPtr.Zero on failure. + public static IntPtr Curve25519PublicKeyDecode(byte[] input) + { + IntPtr key = IntPtr.Zero; + uint idx = 0; + int ret; + + try + { + key = wc_curve25519_new(IntPtr.Zero, INVALID_DEVID); + if (key != IntPtr.Zero) + { + ret = wc_Curve25519PublicKeyDecode(input, ref idx, key, (uint)input.Length); + if (ret != 0) + { + Curve25519FreeKey(key); + key = IntPtr.Zero; + } + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 public key decode exception: " + e.ToString()); + if (key != IntPtr.Zero) Curve25519FreeKey(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Export an Curve25519 key to DER format. + /// + /// Curve25519 key structure. + /// DER-encoded public key as byte array. + /// DER-encoded key as byte array. + public static int Curve25519ExportPrivateKeyToDer(IntPtr key, out byte[] derKey) + { + int ret; + derKey = null; + + try + { + /* Determine length */ + int len = wc_Curve25519PrivateKeyToDer(key, null, 0); + if (len < 0) + { + log(ERROR_LOG, "Failed to determine length. Error code: " + len); + return len; + } + + derKey = new byte[len]; + ret = wc_Curve25519PrivateKeyToDer(key, derKey, (uint)derKey.Length); + + if (ret < 0) + { + log(ERROR_LOG, "Failed to export Curve25519 private key to DER format. Error code: " + ret); + return ret; + } + } + catch (Exception e) + { + log(ERROR_LOG, "CURVE25519 export private key to DER exception: " + e.ToString()); + return EXCEPTION_E; + } + + return ret; + } + + /// + /// Export an Curve25519 public key to DER format. + /// + /// Curve25519 public key structure. + /// Whether to include the algorithm identifier in the output. + /// DER-encoded public key as byte array. + /// An error code indicating success (0) or failure (negative value). + public static int Curve25519ExportPublicKeyToDer(IntPtr key, out byte[] derKey, bool includeAlg) + { + int ret; + derKey = null; + + try + { + /* Determine length */ + int len = wc_Curve25519PublicKeyToDer(key, null, 0, 1); + if (len < 0) + { + log(ERROR_LOG, "Failed to determine length. Error code: " + len); + return len; + } + + derKey = new byte[len]; + ret = wc_Curve25519PublicKeyToDer(key, derKey, (uint)derKey.Length, includeAlg ? 1 : 0); + if (ret < 0) + { + log(ERROR_LOG, "Failed to export Curve25519 public key to DER format. Error code: " + ret); + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 export public key to DER exception: " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Free an Curve25519 key. + /// + /// Key to be freed + public static void Curve25519FreeKey(IntPtr key) + { + wc_curve25519_free(key); + } + /* END Curve25519 */ + + + /*********************************************************************** + * RAW Curve25519 + **********************************************************************/ + + /// + /// Generate a shared secret using Curve25519 + /// + /// Curve25519 private key + /// Curve25519 public key + /// Buffer to receive the shared secret + /// 0 on success, otherwise an error code + public static int Curve25519SharedSecret(IntPtr privateKey, IntPtr publicKey, byte[] secret) + { + int ret; + int secretLength = secret.Length; + + try + { + ret = wc_curve25519_shared_secret(privateKey, publicKey, secret, ref secretLength); + if (ret != 0) + { + throw new Exception("Failed to compute Curve25519 shared secret. Error code: " + ret); + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 shared secret exception " + e.ToString()); + ret = EXCEPTION_E; + } + + return ret; + } + + /// + /// Import a Curve25519 private key from a byte array + /// + /// Private key byte array + /// Allocated Curve25519 key structure or null + public static IntPtr Curve25519ImportPrivateKey(byte[] privateKey) + { + IntPtr key = IntPtr.Zero; + + try + { + key = Marshal.AllocHGlobal(privateKey.Length); + Marshal.Copy(privateKey, 0, key, privateKey.Length); + int ret = wc_curve25519_import_private(key, privateKey.Length, key); + if (ret != 0) + { + Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 import private key exception " + e.ToString()); + if (key != IntPtr.Zero) Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Import a Curve25519 public key from a byte array + /// + /// Public key byte array + /// Allocated Curve25519 key structure or null + public static IntPtr Curve25519ImportPublicKey(byte[] publicKey) + { + IntPtr key = IntPtr.Zero; + + try + { + key = Marshal.AllocHGlobal(publicKey.Length); + Marshal.Copy(publicKey, 0, key, publicKey.Length); + int ret = wc_curve25519_import_public(key, publicKey.Length, key); + if (ret != 0) + { + Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + } + } + catch (Exception e) + { + log(ERROR_LOG, "Curve25519 import public key exception " + e.ToString()); + if (key != IntPtr.Zero) Marshal.FreeHGlobal(key); + key = IntPtr.Zero; + } + + return key; + } + + /// + /// Export a Curve25519 private key to a byte array + /// + /// Curve25519 key structure + /// Private key as byte array + public static byte[] Curve25519ExportPrivateKey(IntPtr key) + { + byte[] privateKey = new byte[ED25519_KEY_SIZE]; + uint privSize = (uint)privateKey.Length; + int ret = wc_curve25519_export_public(key, privateKey, ref privSize); + if (ret != 0) + { + throw new Exception("Failed to export Curve25519 private key. Error code: " + ret); + } + return privateKey; + } + + /// + /// Export a Curve25519 public key to a byte array + /// + /// Curve25519 key structure + /// Public key as byte array + public static byte[] Curve25519ExportPublicKey(IntPtr key) + { + byte[] publicKey = new byte[ED25519_PUB_KEY_SIZE]; + uint pubSize = (uint)publicKey.Length; + int ret = wc_curve25519_export_public(key, publicKey, ref pubSize); + if (ret != 0) + { + throw new Exception("Failed to export Curve25519 public key. Error code: " + ret); + } + return publicKey; + } + + /// + /// Export both private and public keys from a Curve25519 key structure + /// + /// Curve25519 key structure + /// A tuple containing the private key and public key as byte arrays + public static (byte[] privateKey, byte[] publicKey) Curve25519ExportKeyRaw(IntPtr key) + { + byte[] privateKey = new byte[ED25519_KEY_SIZE]; + byte[] publicKey = new byte[ED25519_PUB_KEY_SIZE]; + uint privSize = (uint)privateKey.Length; + uint pubSize = (uint)publicKey.Length; + int ret = wc_curve25519_export_key_raw(key, privateKey, ref privSize, publicKey, ref pubSize); + if (ret != 0) + { + throw new Exception("Failed to export Curve25519 keys. Error code: " + ret); + } + return (privateKey, publicKey); + } + /* END RAW Curve25519 */ + + + /*********************************************************************** + * AES-GCM + **********************************************************************/ + + /// + /// Creates a new AES context. + /// + /// Pointer to a memory heap, or IntPtr.Zero to use the default heap. + /// The device ID to associate with this AES context. + /// A pointer to the newly created AES context, or IntPtr.Zero on failure. + public static IntPtr AesNew(IntPtr heap, int devId) + { + IntPtr aesPtr = IntPtr.Zero; + + try + { + aesPtr = wc_AesNew(heap, devId); + + if (aesPtr == IntPtr.Zero) + { + throw new Exception("Failed to create AES context."); + } + + } + catch (Exception e) + { + Console.WriteLine($"AES context creation failed: {e.Message}"); + } + + return aesPtr; + } + + /// + /// Initialize and set the AES key for AES-GCM operations. + /// + /// AES-GCM context pointer. + /// The AES key (either 128, 192, or 256 bits). + /// 0 on success, otherwise an error code. + public static int AesGcmSetKey(IntPtr aes, byte[] key) + { + IntPtr keyPtr = IntPtr.Zero; + int ret; + + try + { + /* Allocate memory */ + keyPtr = Marshal.AllocHGlobal(key.Length); + Marshal.Copy(key, 0, keyPtr, key.Length); + + ret = wc_AesGcmSetKey(aes, keyPtr, (uint)key.Length); + if (ret != 0) + { + throw new Exception($"AES-GCM initialization failed with error code {ret}"); + } + } + finally + { + /* Cleanup */ + if (keyPtr != IntPtr.Zero) Marshal.FreeHGlobal(keyPtr); + } + + return ret; + } + + /// + /// Wrapper method to initialize the AES-GCM context with a given key and IV. + /// + /// Pointer to the AES-GCM context that needs to be initialized. + /// Byte array containing the AES key. + /// Byte array containing the initialization vector (IV). + public static int AesGcmInit(IntPtr aes, byte[] key, byte[] iv) + { + IntPtr keyPtr = IntPtr.Zero; + IntPtr ivPtr = IntPtr.Zero; + int ret; + + try + { + /* Allocate memory for key and IV */ + keyPtr = Marshal.AllocHGlobal(key.Length); + Marshal.Copy(key, 0, keyPtr, key.Length); + + ivPtr = Marshal.AllocHGlobal(iv.Length); + Marshal.Copy(iv, 0, ivPtr, iv.Length); + + ret = wc_AesGcmInit(aes, keyPtr, (uint)key.Length, ivPtr, (uint)iv.Length); + if (ret != 0) + { + throw new Exception($"AES-GCM initialization failed with error code {ret}"); + } + } + finally + { + /* Cleanup */ + if (keyPtr != IntPtr.Zero) Marshal.FreeHGlobal(keyPtr); + if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr); + } + + return ret; + } + + /// + /// Encrypt data using AES-GCM + /// + /// AES-GCM context pointer. + /// Initialization Vector (IV) + /// Data to encrypt + /// Buffer to receive the encrypted data + /// Buffer to receive the authentication tag + /// 0 on success, otherwise an error code + public static int AesGcmEncrypt(IntPtr aes, byte[] iv, byte[] plaintext, + byte[] ciphertext, byte[] authTag, byte[] addAuth = null) + { + int ret; + IntPtr ivPtr = IntPtr.Zero; + IntPtr ciphertextPtr = IntPtr.Zero; + IntPtr plaintextPtr = IntPtr.Zero; + IntPtr authTagPtr = IntPtr.Zero; + IntPtr addAuthPtr = IntPtr.Zero; + uint addAuthSz = 0; + + try + { + /* Allocate memory */ + ivPtr = Marshal.AllocHGlobal(iv.Length); + ciphertextPtr = Marshal.AllocHGlobal(ciphertext.Length); + plaintextPtr = Marshal.AllocHGlobal(plaintext.Length); + authTagPtr = Marshal.AllocHGlobal(authTag.Length); + if (addAuth != null) { + addAuthSz = (uint)addAuth.Length; + addAuthPtr = Marshal.AllocHGlobal(addAuth.Length); + Marshal.Copy(addAuth, 0, addAuthPtr, addAuth.Length); + } + + Marshal.Copy(iv, 0, ivPtr, iv.Length); + Marshal.Copy(plaintext, 0, plaintextPtr, plaintext.Length); + + /* Encrypt data */ + ret = wc_AesGcmEncrypt(aes, ciphertextPtr, plaintextPtr, (uint)plaintext.Length, + ivPtr, (uint)iv.Length, authTagPtr, (uint)authTag.Length, addAuthPtr, addAuthSz); + if (ret < 0) + { + log(ERROR_LOG, "Failed to Encrypt data using AES-GCM. Error code: " + ret); + } + else { + Marshal.Copy(ciphertextPtr, ciphertext, 0, ciphertext.Length); + Marshal.Copy(authTagPtr, authTag, 0, authTag.Length); + ret = 0; + } + } + catch (Exception e) + { + log(ERROR_LOG, "AES-GCM Encryption failed: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr); + if (ciphertextPtr != IntPtr.Zero) Marshal.FreeHGlobal(ciphertextPtr); + if (plaintextPtr != IntPtr.Zero) Marshal.FreeHGlobal(plaintextPtr); + if (authTagPtr != IntPtr.Zero) Marshal.FreeHGlobal(authTagPtr); + if (addAuthPtr != IntPtr.Zero) Marshal.FreeHGlobal(addAuthPtr); + } + + return ret; + } + + /// + /// Decrypt data using AES-GCM + /// + /// AES-GCM context pointer. + /// Initialization Vector (IV) + /// Data to decrypt + /// Buffer to receive the decrypted data + /// Authentication tag for verification + /// 0 on success, otherwise an error code + public static int AesGcmDecrypt(IntPtr aes, byte[] iv, byte[] ciphertext, + byte[] plaintext, byte[] authTag, byte[] addAuth = null) + { + int ret; + IntPtr ivPtr = IntPtr.Zero; + IntPtr ciphertextPtr = IntPtr.Zero; + IntPtr plaintextPtr = IntPtr.Zero; + IntPtr authTagPtr = IntPtr.Zero; + IntPtr addAuthPtr = IntPtr.Zero; + uint addAuthSz = 0; + + try + { + /* Allocate memory */ + ivPtr = Marshal.AllocHGlobal(iv.Length); + ciphertextPtr = Marshal.AllocHGlobal(ciphertext.Length); + plaintextPtr = Marshal.AllocHGlobal(plaintext.Length); + authTagPtr = Marshal.AllocHGlobal(authTag.Length); + if (addAuth != null) { + addAuthSz = (uint)addAuth.Length; + addAuthPtr = Marshal.AllocHGlobal(addAuth.Length); + Marshal.Copy(addAuth, 0, addAuthPtr, addAuth.Length); + } + + Marshal.Copy(iv, 0, ivPtr, iv.Length); + Marshal.Copy(ciphertext, 0, ciphertextPtr, ciphertext.Length); + Marshal.Copy(authTag, 0, authTagPtr, authTag.Length); + + /* Decrypt data */ + ret = wc_AesGcmDecrypt(aes, plaintextPtr, ciphertextPtr, (uint)ciphertext.Length, + ivPtr, (uint)iv.Length, authTagPtr, (uint)authTag.Length, addAuthPtr, addAuthSz); + if (ret < 0) + { + log(ERROR_LOG, "Failed to Decrypt data using AES-GCM. Error code: " + ret); + } + else { + Marshal.Copy(plaintextPtr, plaintext, 0, plaintext.Length); + ret = 0; + } + } + catch (Exception e) + { + log(ERROR_LOG, "AES-GCM Decryption failed: " + e.ToString()); + ret = EXCEPTION_E; + } + finally + { + /* Cleanup */ + if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr); + if (ciphertextPtr != IntPtr.Zero) Marshal.FreeHGlobal(ciphertextPtr); + if (plaintextPtr != IntPtr.Zero) Marshal.FreeHGlobal(plaintextPtr); + if (authTagPtr != IntPtr.Zero) Marshal.FreeHGlobal(authTagPtr); + if (addAuthPtr != IntPtr.Zero) Marshal.FreeHGlobal(addAuthPtr); + } + + return ret; + } + + /// + /// Free AES-GCM context + /// + /// AES-GCM context + public static void AesGcmFree(IntPtr aes) + { + if (aes != IntPtr.Zero) + { + wc_AesFree(aes); + } + } + /* END AES-GCM */ + + + /*********************************************************************** + * HASH + **********************************************************************/ + + /// + /// Allocate and set up a new hash context with proper error handling + /// + /// The type of hash (SHA-256, SHA-384, etc.) + /// Pointer to the heap for memory allocation (use IntPtr.Zero if not applicable) + /// Device ID (if applicable, otherwise use INVALID_DEVID) + /// Allocated hash context pointer or IntPtr.Zero on failure + public static IntPtr HashNew(uint hashType, IntPtr heap, int devId) + { + IntPtr hash = IntPtr.Zero; + + try + { + /* Allocate new hash */ + hash = wc_HashNew(hashType, heap, devId); + if (hash == IntPtr.Zero) + { + throw new Exception("Failed to allocate new hash context."); + } + } + catch (Exception e) + { + log(ERROR_LOG, "HashNew Exception: " + e.ToString()); + } + + return hash; + } + + /// + /// Initialize the hash context for a specific hash type with proper error handling + /// + /// Hash context pointer + /// The type of hash (SHA-256, SHA-384, etc.) + /// 0 on success, otherwise an error code + public static int InitHash(IntPtr hash, uint hashType) + { + int ret = 0; + + try + { + /* Check hash */ + if (hash == IntPtr.Zero) + throw new Exception("Hash context is null."); + + ret = wc_HashInit(hash, hashType); + if (ret != 0) + { + throw new Exception($"Failed to initialize hash context. Error code: {ret}"); + } + } + catch (Exception e) + { + /* Cleanup */ + log(ERROR_LOG, "InitHash Exception: " + e.ToString()); + if (hash != IntPtr.Zero) wc_HashFree(hash, hashType); + } + + return ret; + } + + /// + /// Update the hash with data + /// + /// Hash context pointer + /// The type of hash + /// Byte array of the data to hash + /// 0 on success, otherwise an error code + public static int HashUpdate(IntPtr hash, uint hashType, byte[] data) + { + int ret = 0; + IntPtr dataPtr = IntPtr.Zero; + + try + { + /* Check parameters */ + if (hash == IntPtr.Zero) + throw new Exception("Hash context is null."); + if (data == null || data.Length == 0) + throw new Exception("Invalid data array."); + + /* Allocate memory */ + dataPtr = Marshal.AllocHGlobal(data.Length); + Marshal.Copy(data, 0, dataPtr, data.Length); + + /* Update hash */ + ret = wc_HashUpdate(hash, hashType, dataPtr, (uint)data.Length); + if (ret != 0) + { + throw new Exception($"Failed to update hash. Error code: {ret}"); + } + } + catch (Exception e) + { + log(ERROR_LOG, "HashUpdate Exception: " + e.ToString()); + } + finally + { + /* Cleanup */ + if (dataPtr != IntPtr.Zero) Marshal.FreeHGlobal(dataPtr); + } + + return ret; + } + + /// + /// Finalize the hash and output the result + /// + /// Hash context pointer + /// The type of hash + /// Byte array where the hash output will be stored + /// 0 on success, otherwise an error code + public static int HashFinal(IntPtr hash, uint hashType, out byte[] output) + { + int ret = 0; + IntPtr outputPtr = IntPtr.Zero; + + try + { + /* Get hash size and initialize */ + int hashSize = wc_HashGetDigestSize(hashType); + output = new byte[hashSize]; + + /* Check hash */ + if (hash == IntPtr.Zero) + throw new Exception("Hash context is null."); + if (hashSize <= 0) + throw new Exception("Invalid hash size."); + + /* Allocate memory */ + outputPtr = Marshal.AllocHGlobal(hashSize); + + ret = wc_HashFinal(hash, hashType, outputPtr); + if (ret != 0) + { + throw new Exception($"Failed to finalize hash. Error code: {ret}"); + } + + Marshal.Copy(outputPtr, output, 0, hashSize); + } + catch (Exception e) + { + log(ERROR_LOG, "HashFinal Exception: " + e.ToString()); + output = null; + } + finally + { + /* Cleanup */ + if (outputPtr != IntPtr.Zero) Marshal.FreeHGlobal(outputPtr); + } + + return ret; + } + + /// + /// Free the allocated hash context with proper error handling + /// + /// Hash context pointer to be freed + /// The type of hash + /// 0 on success, otherwise an error code + public static int HashFree(IntPtr hash, uint hashType) + { + int ret = 0; + + try + { + /* Check hash */ + if (hash == IntPtr.Zero) + throw new Exception("Hash context is null, cannot free."); + + /* Free hash */ + ret = wc_HashFree(hash, hashType); + if (ret != 0) + { + throw new Exception($"Failed to free hash context. Error code: {ret}"); + } + } + catch (Exception e) + { + log(ERROR_LOG, "HashFree Exception: " + e.ToString()); + } + + return ret; + } + + /// + /// Hash type enum values + /// + public enum hashType + { + WC_HASH_TYPE_NONE = 0, + WC_HASH_TYPE_MD2 = 1, + WC_HASH_TYPE_MD4 = 2, + WC_HASH_TYPE_MD5 = 3, + WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 5, + WC_HASH_TYPE_SHA256 = 6, + WC_HASH_TYPE_SHA384 = 7, + WC_HASH_TYPE_SHA512 = 8, + WC_HASH_TYPE_MD5_SHA = 9, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + WC_HASH_TYPE_BLAKE2S = 15, + } + /* END HASH */ + + + /*********************************************************************** + * Logging / Other + **********************************************************************/ + + /// + /// Set the function to use for logging + /// + /// Function that conforms as to loggingCb + /// 0 on success + public static int SetLogging(loggingCb input) + { + internal_log = input; + return SUCCESS; + } + + /// + /// Get error string for wolfCrypt error codes + /// + /// Negative error number from wolfCrypt API + /// Error string + public static string GetError(int error) + { + try + { + IntPtr errStr = wc_GetErrorString(error); + return Marshal.PtrToStringAnsi(errStr); + } + catch (Exception e) + { + log(ERROR_LOG, "Get error exception " + e.ToString()); + return string.Empty; + } + } + + /// + /// Compares two byte arrays. + /// + /// The first byte array to compare. + /// The second byte array to compare. + /// True if both arrays are equal; otherwise, false. + public static bool ByteArrayVerify(byte[] array1, byte[] array2) + { + if (ReferenceEquals(array1, array2)) return true; + if (array1 == null || array2 == null) return false; + if (array1.Length != array2.Length) return false; + + for (int i = 0; i < array1.Length; i++) + { + if (array1[i] != array2[i]) return false; + } + return true; + } + } +} + + diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj index c7df2aafcd..a560347cc9 100755 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj @@ -17,7 +17,7 @@ true full false - ..\DLL Debug\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE prompt 3 @@ -25,14 +25,14 @@ pdbonly true - ..\DLL Release\Win32\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE prompt 4 true - ..\DLL Debug\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ DEBUG;TRACE 3 full @@ -41,7 +41,7 @@ MinimumRecommendedRules.ruleset - ..\DLL Release\x64\ + $(SolutionDir)$(Configuration)\$(Platform)\ TRACE true pdbonly @@ -60,6 +60,7 @@ + diff --git a/wrapper/CSharp/wolfssl.vcxproj b/wrapper/CSharp/wolfssl.vcxproj new file mode 100644 index 0000000000..534c4255c4 --- /dev/null +++ b/wrapper/CSharp/wolfssl.vcxproj @@ -0,0 +1,456 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + DLL Debug + Win32 + + + DLL Debug + x64 + + + DLL Release + Win32 + + + DLL Release + x64 + + + Release + Win32 + + + Release + x64 + + + + {67932048-d67e-4c86-b55f-90899b9bda64} + wolfssl + Win32Proj + + + + StaticLibrary + v143 + Unicode + true + + + DynamicLibrary + v143 + Unicode + true + + + StaticLibrary + v143 + Unicode + true + + + DynamicLibrary + v143 + Unicode + true + + + StaticLibrary + v143 + Unicode + + + DynamicLibrary + v143 + Unicode + + + StaticLibrary + v143 + Unicode + + + DynamicLibrary + v143 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\$(ProjectName)_obj\ + + + $(SolutionDir)$(Configuration)\AnyCPU\ + $(Configuration)\AnyCPU\$(ProjectName)_obj\ + + + $(SolutionDir)$(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\$(ProjectName)_obj\ + + + $(SolutionDir)$(Configuration)\AnyCPU\ + $(Configuration)\AnyCPU\$(ProjectName)_obj\ + + + $(SolutionDir)Release\$(Platform)\ + Release\$(Platform)\$(ProjectName)_obj\ + + + $(SolutionDir)Release\AnyCPU\ + Release\AnyCPU\$(ProjectName)_obj\ + + + $(SolutionDir)Debug\$(Platform)\ + Debug\$(Platform)\$(ProjectName)_obj\ + + + $(SolutionDir)Debug\AnyCPU\ + Debug\AnyCPU\$(ProjectName)_obj\ + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + false + true + false + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + false + true + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + true + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + + + + true + true + true + true + + + + + +