diff options
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c')
-rw-r--r-- | FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c | 6595 |
1 files changed, 6595 insertions, 0 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c new file mode 100644 index 000000000..d9207900c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c @@ -0,0 +1,6595 @@ +/* evp.c + * + * Copyright (C) 2006-2020 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 + */ + +#if !defined(WOLFSSL_EVP_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning evp.c does not need to be compiled separately from ssl.c + #endif +#elif defined(WOLFCRYPT_ONLY) +#else + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <wolfssl/wolfcrypt/settings.h> + +#include <wolfssl/openssl/ecdsa.h> +#include <wolfssl/openssl/evp.h> + +#if defined(OPENSSL_EXTRA) + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CBC = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CBC = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CBC = NULL; + #endif + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_OFB = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_OFB = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_OFB = NULL; + #endif + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_XTS = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_XTS = NULL; + #endif + #endif /* WOLFSSL_AES_XTS */ + + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB1 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB1 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB1 = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB8 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB8 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB8 = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB128 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB128 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB128 = NULL; + #endif + #endif /* WOLFSSL_AES_CFB */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_GCM = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_GCM = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_GCM = NULL; + #endif + #endif /* HAVE_AESGCM */ + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CTR = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CTR = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CTR = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_ECB = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_ECB = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_ECB = NULL; + #endif + #define EVP_AES_SIZE 11 + #ifdef WOLFSSL_AES_CFB + #define EVP_AESCFB_SIZE 14 + #endif +#endif + +#ifndef NO_DES3 + static char *EVP_DES_CBC = NULL; + static char *EVP_DES_ECB = NULL; + + static char *EVP_DES_EDE3_CBC = NULL; + static char *EVP_DES_EDE3_ECB = NULL; + + #define EVP_DES_SIZE 7 + #define EVP_DES_EDE3_SIZE 12 +#endif + +#ifdef HAVE_IDEA + static char *EVP_IDEA_CBC; + #define EVP_IDEA_SIZE 8 +#endif + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); + + +/* Getter function for cipher key length + * + * c WOLFSSL_EVP_CIPHER structure to get key length from + * + * NOTE: OpenSSL_add_all_ciphers() should be called first before using this + * function + * + * Returns size of key in bytes + */ +int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c) +{ + WOLFSSL_ENTER("wolfSSL_EVP_Cipher_key_length"); + + if (c == NULL) { + return 0; + } + + switch (cipherType(c)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: return 16; + case AES_192_CBC_TYPE: return 24; + case AES_256_CBC_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_CFB) + case AES_128_CFB1_TYPE: return 16; + case AES_192_CFB1_TYPE: return 24; + case AES_256_CFB1_TYPE: return 32; + case AES_128_CFB8_TYPE: return 16; + case AES_192_CFB8_TYPE: return 24; + case AES_256_CFB8_TYPE: return 32; + case AES_128_CFB128_TYPE: return 16; + case AES_192_CFB128_TYPE: return 24; + case AES_256_CFB128_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: return 16; + case AES_192_OFB_TYPE: return 24; + case AES_256_OFB_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: return 16; + case AES_256_XTS_TYPE: return 32; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: return 16; + case AES_192_GCM_TYPE: return 24; + case AES_256_GCM_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: return 16; + case AES_192_CTR_TYPE: return 24; + case AES_256_CTR_TYPE: return 32; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: return 16; + case AES_192_ECB_TYPE: return 24; + case AES_256_ECB_TYPE: return 32; + #endif +#endif /* !NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 24; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 24; + #endif + default: + return 0; + } +} + + +int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + +int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + + +WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) +{ + WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); + wolfSSL_EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +} + +int wolfSSL_EVP_CIPHER_CTX_reset(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int ret = WOLFSSL_FAILURE; + + if (ctx != NULL) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_reset"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + ret = WOLFSSL_SUCCESS; + } + + return ret; +} + +unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return 0; + return ctx->flags & WOLFSSL_EVP_CIPH_MODE; +} + +int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + + +int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv, + int enc) +{ + (void)impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc); +} + +int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + +int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && !ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + +int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && !ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + + +int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex"); + return wolfSSL_EVP_DigestInit(ctx, type); +} + +#ifdef DEBUG_WOLFSSL_EVP +#define PRINT_BUF(b, sz) { int _i; for(_i=0; _i<(sz); _i++) { \ + printf("%02x(%c),", (b)[_i], (b)[_i]); if ((_i+1)%8==0)printf("\n");}} +#else +#define PRINT_BUF(b, sz) +#endif + +static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz) +{ + int fill; + + if (sz > 0) { + if ((sz+ctx->bufUsed) > ctx->block_size) { + fill = ctx->block_size - ctx->bufUsed; + } else { + fill = sz; + } + XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill); + ctx->bufUsed += fill; + return fill; + } else return 0; +} + +static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, int inl) +{ + int ret = 0; + + switch (ctx->cipherType) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + if (ctx->enc) { + if (out){ + /* encrypt confidential data*/ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data */ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + in, inl); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + else { + if (out){ + /* decrypt confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, in, inl, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, + ctx->authTag, ctx->authTagSz, + in, inl); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + break; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + if (ctx->enc) + ret = wc_AesOfbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesOfbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(WOLFSSL_AES_CFB) + #if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + if (ctx->enc) + ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, out, in, + inl * WOLFSSL_BIT_SIZE); + else + ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, out, in, + inl * WOLFSSL_BIT_SIZE); + break; + + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + if (ctx->enc) + ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + if (ctx->enc) + ret = wc_AesCfbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCfbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + if (ctx->enc) + ret = wc_AesXtsEncrypt(&ctx->cipher.xts, out, in, inl, + ctx->iv, ctx->ivSz); + else + ret = wc_AesXtsDecrypt(&ctx->cipher.xts, out, in, inl, + ctx->iv, ctx->ivSz); + break; +#endif +#endif /* !NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: + if (ctx->enc) + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + else + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_CBC_TYPE: + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + break; + #if defined(WOLFSSL_DES_ECB) + case DES_ECB_TYPE: + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_ECB_TYPE: + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + break; + #endif + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + wc_Arc4Process(&ctx->cipher.arc4, out, in, inl); + break; + #endif + default: + return WOLFSSL_FAILURE; + } + + if (ret != 0) + return WOLFSSL_FAILURE; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return WOLFSSL_SUCCESS; /* success */ +} + +#if defined(HAVE_AESGCM) +static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + /* process blocks */ + if (evpCipherBlock(ctx, out, in, inl) == 0) + return WOLFSSL_FAILURE; + *outl = inl; + return WOLFSSL_SUCCESS; +} +#endif + +/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int blocks; + int fill; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + if ((ctx == NULL) || (inl < 0) || (outl == NULL)|| (in == NULL)) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } + + *outl = 0; + if (inl == 0) { + return WOLFSSL_SUCCESS; + } + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + switch (ctx->cipherType) { + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: +/* if out == NULL, in/inl contains the additional authenticated data for GCM */ + return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl); + default: + /* fall-through */ + break; + } +#endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */ + + if (out == NULL) { + return WOLFSSL_FAILURE; + } + + + if (ctx->bufUsed > 0) { /* concatenate them if there is anything */ + fill = fillBuff(ctx, in, inl); + inl -= fill; + in += fill; + } + + /* check if the buff is full, and if so flash it out */ + if (ctx->bufUsed == ctx->block_size) { + byte* output = out; + + /* During decryption we save the last block to check padding on Final. + * Update the last block stored if one has already been stored */ + if (ctx->enc == 0) { + if (ctx->lastUsed == 1) { + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl+= ctx->block_size; + out += ctx->block_size; + } + output = ctx->lastBlock; /* redirect output to last block buffer */ + ctx->lastUsed = 1; + } + + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, output, ctx->buf, ctx->block_size) == 0) { + return WOLFSSL_FAILURE; + } + PRINT_BUF(out, ctx->block_size); + ctx->bufUsed = 0; + + /* if doing encryption update the new output block, decryption will + * always have the last block saved for when Final is called */ + if ((ctx->enc != 0)) { + *outl+= ctx->block_size; + out += ctx->block_size; + } + } + + blocks = inl / ctx->block_size; + if (blocks > 0) { + /* During decryption we save the last block to check padding on Final. + * Update the last block stored if one has already been stored */ + if ((ctx->enc == 0) && (ctx->lastUsed == 1)) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl += ctx->block_size; + out += ctx->block_size; + ctx->lastUsed = 0; + } + + /* process blocks */ + if (evpCipherBlock(ctx, out, in, blocks * ctx->block_size) == 0) { + return WOLFSSL_FAILURE; + } + PRINT_BUF(in, ctx->block_size*blocks); + PRINT_BUF(out,ctx->block_size*blocks); + inl -= ctx->block_size * blocks; + in += ctx->block_size * blocks; + if (ctx->enc == 0) { + if ((ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) || + (ctx->block_size == 1)) { + ctx->lastUsed = 0; + *outl += ctx->block_size * blocks; + } else { + /* in the case of decryption and padding, store the last block + * here in order to verify the padding when Final is called */ + if (inl == 0) { /* if not 0 then we know leftovers are checked*/ + ctx->lastUsed = 1; + blocks = blocks - 1; /* save last block to check padding in + * EVP_CipherFinal call */ + XMEMCPY(ctx->lastBlock, &out[ctx->block_size * blocks], + ctx->block_size); + } + *outl += ctx->block_size * blocks; + } + } else { + *outl += ctx->block_size * blocks; + } + } + + + if (inl > 0) { + /* put fraction into buff */ + fillBuff(ctx, in, inl); + /* no increase of outl */ + } + (void)out; /* silence warning in case not read */ + + return WOLFSSL_SUCCESS; +} + +static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int i; + for (i = ctx->bufUsed; i < ctx->block_size; i++) + ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed); +} + +static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) +{ + int i; + int n; + n = buff[ctx->block_size-1]; + if (n > ctx->block_size) return -1; + for (i = 0; i < n; i++) { + if (buff[ctx->block_size-i-1] != n) + return -1; + } + return ctx->block_size - n; +} + +int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + int ret = WOLFSSL_SUCCESS; + if (!ctx || !outl) + return WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + switch (ctx->cipherType) { + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + *outl = 0; + /* Clear IV, since IV reuse is not recommended for AES GCM. */ + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + return WOLFSSL_SUCCESS; + default: + /* fall-through */ + break; + } +#endif /* !NO_AES && HAVE_AESGCM */ + + if (!out) + return WOLFSSL_FAILURE; + + if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + if (ctx->bufUsed != 0) return WOLFSSL_FAILURE; + *outl = 0; + } + else if (ctx->enc) { + if (ctx->block_size == 1) { + *outl = 0; + } + else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) { + padBlock(ctx); + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) { + WOLFSSL_MSG("Final Cipher Block failed"); + ret = WOLFSSL_FAILURE; + } + else { + PRINT_BUF(out, ctx->block_size); + *outl = ctx->block_size; + } + } + } + else { + if (ctx->block_size == 1) { + *outl = 0; + } + else if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + WOLFSSL_MSG("Final Cipher Block not enough padding"); + ret = WOLFSSL_FAILURE; + } + else if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { + XMEMCPY(out, ctx->lastBlock, fl); + *outl = fl; + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + /* return error in cases where the block length is incorrect */ + WOLFSSL_MSG("Final Cipher Block bad length"); + ret = WOLFSSL_FAILURE; + } + } + else { + ret = WOLFSSL_FAILURE; + } + } + else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + /* return error in cases where the block length is incorrect */ + ret = WOLFSSL_FAILURE; + } + } + if (ret == WOLFSSL_SUCCESS) { + /* reset cipher state after final */ + wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1); + } + return ret; +} + + +#ifdef WOLFSSL_EVP_DECRYPT_LEGACY +/* This is a version of DecryptFinal to work with data encrypted with + * wolfSSL_EVP_EncryptFinal() with the broken padding. (pre-v3.12.0) + * Only call this after wolfSSL_EVP_CipherFinal() fails on a decrypt. + * Note, you don't know if the padding is good or bad with the old + * encrypt, but it is likely to be or bad. It will update the output + * length with the block_size so the last block is still captured. */ +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + if (ctx == NULL || out == NULL || outl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_legacy"); + if (ctx->block_size == 1) { + *outl = 0; + return WOLFSSL_SUCCESS; + } + if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + return WOLFSSL_FAILURE; + } + /* The original behavior of CipherFinal() was like it is now, + * but checkPad would return 0 in case of a bad pad. It would + * treat the pad as 0, and leave the data in the output buffer, + * and not try to copy anything. This converts checkPad's -1 error + * code to block_size. + */ + if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) < 0) { + fl = ctx->block_size; + } + else { + XMEMCPY(out, ctx->lastBlock, fl); + } + *outl = fl; + } + /* return error in cases where the block length is incorrect */ + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif + + +int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + switch (ctx->cipherType) { +#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) +#if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: +#endif +#if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: +#endif +#if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: +#endif +#if defined(WOLFSSL_AES_CFB) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: +#endif +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: +#endif +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: +#endif + + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: +#endif /* !NO_AES */ +#ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_ECB_TYPE: + case DES_EDE3_CBC_TYPE: + case DES_EDE3_ECB_TYPE: +#endif + return ctx->block_size; +#endif /* !NO_AES || !NO_DES3 */ + default: + return 0; + } +} + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; /* dummy for #ifdef */ +#ifndef NO_DES3 + else if (EVP_DES_CBC && XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0) + return DES_CBC_TYPE; + else if (EVP_DES_EDE3_CBC && XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_CBC_TYPE; +#if !defined(NO_DES3) + else if (EVP_DES_ECB && XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0) + return DES_ECB_TYPE; + else if (EVP_DES_EDE3_ECB && XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_ECB_TYPE; +#endif /* NO_DES3 && HAVE_AES_ECB */ +#endif +#if !defined(NO_AES) +#if defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CBC && XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + return AES_128_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CBC && XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + return AES_192_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CBC && XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + return AES_256_CBC_TYPE; + #endif +#endif /* HAVE_AES_CBC */ +#if defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_GCM && XSTRNCMP(cipher, EVP_AES_128_GCM, EVP_AES_SIZE) == 0) + return AES_128_GCM_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_GCM && XSTRNCMP(cipher, EVP_AES_192_GCM, EVP_AES_SIZE) == 0) + return AES_192_GCM_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_GCM && XSTRNCMP(cipher, EVP_AES_256_GCM, EVP_AES_SIZE) == 0) + return AES_256_GCM_TYPE; + #endif +#endif /* HAVE_AESGCM */ +#if defined(WOLFSSL_AES_COUNTER) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CTR && XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0) + return AES_128_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CTR && XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0) + return AES_192_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CTR && XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0) + return AES_256_CTR_TYPE; + #endif +#endif /* HAVE_AES_CBC */ +#if defined(HAVE_AES_ECB) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_ECB && XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0) + return AES_128_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_ECB && XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0) + return AES_192_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_ECB && XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0) + return AES_256_ECB_TYPE; + #endif +#endif /*HAVE_AES_CBC */ +#if defined(WOLFSSL_AES_XTS) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_XTS && XSTRNCMP(cipher, EVP_AES_128_XTS, EVP_AES_SIZE) == 0) + return AES_128_XTS_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_XTS && XSTRNCMP(cipher, EVP_AES_256_XTS, EVP_AES_SIZE) == 0) + return AES_256_XTS_TYPE; + #endif +#endif /* WOLFSSL_AES_XTS */ +#if defined(WOLFSSL_AES_CFB) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB1 && XSTRNCMP(cipher, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB1 && XSTRNCMP(cipher, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB1 && XSTRNCMP(cipher, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB8 && XSTRNCMP(cipher, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB8 && XSTRNCMP(cipher, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB8 && XSTRNCMP(cipher, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB128 && XSTRNCMP(cipher, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB128_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB128 && XSTRNCMP(cipher, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB128_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB128 && XSTRNCMP(cipher, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB128_TYPE; + #endif +#endif /*HAVE_AES_CBC */ +#endif /* !NO_AES */ + else return 0; +} + +int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return BAD_FUNC_ARG; + switch (cipherType(cipher)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return AES_BLOCK_SIZE; + #endif +#endif /* NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 8; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 8; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + switch (cipherType(cipher)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + return WOLFSSL_EVP_CIPH_GCM_MODE; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return WOLFSSL_EVP_CIPH_CTR_MODE; + #endif + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; +#endif /* NO_ASE */ + #ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_EDE3_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + case DES_ECB_TYPE: + case DES_EDE3_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + return EVP_CIPH_STREAM_CIPHER; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags |= flags; + } +} + +void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags &= ~flags; + } +} + +unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + if (padding) { + ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING; + } + else { + ctx->flags |= WOLFSSL_EVP_CIPH_NO_PADDING; + } + return 1; +} + +int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) +{ + (void)digest; + /* nothing to do */ + return 0; +} + + +/* Frees the WOLFSSL_EVP_PKEY_CTX passed in. + * + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_free"); + if (ctx->pkey != NULL) + wolfSSL_EVP_PKEY_free(ctx->pkey); + if (ctx->peerKey != NULL) + wolfSSL_EVP_PKEY_free(ctx->peerKey); + XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_SUCCESS; +} + + +/* Creates a new WOLFSSL_EVP_PKEY_CTX structure. + * + * pkey key structure to use with new WOLFSSL_EVP_PEKY_CTX + * e engine to use. It should be NULL at this time. + * + * return the new structure on success and NULL if failed. + */ +WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e) +{ + WOLFSSL_EVP_PKEY_CTX* ctx; + int type = NID_undef; + + if (pkey == NULL) return 0; + if (e != NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_new"); + + ctx = (WOLFSSL_EVP_PKEY_CTX*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY_CTX), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ctx == NULL) return NULL; + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX)); + ctx->pkey = pkey; +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + ctx->padding = RSA_PKCS1_PADDING; +#endif + type = wolfSSL_EVP_PKEY_type(pkey->type); + + if (type != NID_undef) { + if (wc_LockMutex(&pkey->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock pkey mutex"); + } + pkey->references++; + + wc_UnLockMutex(&pkey->refMutex); + } + return ctx; +} + + +/* Sets the type of RSA padding to use. + * + * ctx structure to set padding in. + * padding RSA padding type + * + * returns WOLFSSL_SUCCESS on success. + */ +int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_set_rsa_padding"); + ctx->padding = padding; + return WOLFSSL_SUCCESS; +} + +/* create a PKEY contxt and return it */ +WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_EVP_PKEY_CTX* ctx = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_new_id"); + + pkey = wolfSSL_EVP_PKEY_new_ex(NULL); + if (pkey) { + pkey->type = id; + ctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + } + } + return ctx; +} + +/* Returns WOLFSSL_SUCCESS or error */ +int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits) +{ + if (ctx) { + ctx->nbits = bits; + } + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_init"); + + if (!ctx) { + return WOLFSSL_FAILURE; + } + wolfSSL_EVP_PKEY_free(ctx->peerKey); + ctx->op = EVP_PKEY_OP_DERIVE; + ctx->padding = 0; + ctx->nbits = 0; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer) +{ + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_set_peer"); + + if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE) { + return WOLFSSL_FAILURE; + } + wolfSSL_EVP_PKEY_free(ctx->peerKey); + ctx->peerKey = peer; + if (!wolfSSL_EVP_PKEY_up_ref(peer)) { + ctx->peerKey = NULL; + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} + +#if !defined(NO_DH) && defined(HAVE_ECC) +int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + int len; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive"); + + if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE || !ctx->pkey || !ctx->peerKey || !keylen + || ctx->pkey->type != ctx->peerKey->type) { + return WOLFSSL_FAILURE; + } + switch (ctx->pkey->type) { +#ifndef NO_DH + case EVP_PKEY_DH: + /* Use DH */ + if (!ctx->pkey->dh || !ctx->peerKey->dh || !ctx->peerKey->dh->pub_key) { + return WOLFSSL_FAILURE; + } + if ((len = wolfSSL_DH_size(ctx->pkey->dh)) <= 0) { + return WOLFSSL_FAILURE; + } + if (key) { + if (*keylen < (size_t)len) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_DH_compute_key(key, ctx->peerKey->dh->pub_key, + ctx->pkey->dh) != len) { + return WOLFSSL_FAILURE; + } + } + *keylen = (size_t)len; + break; +#endif +#ifdef HAVE_ECC + case EVP_PKEY_EC: + /* Use ECDH */ + if (!ctx->pkey->ecc || !ctx->peerKey->ecc) { + return WOLFSSL_FAILURE; + } + /* set internal key if not done */ + if (!ctx->pkey->ecc->inSet) { + if (SetECKeyInternal(ctx->pkey->ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + } + if (!ctx->peerKey->ecc->exSet || !ctx->peerKey->ecc->pub_key->internal) { + if (SetECKeyExternal(ctx->peerKey->ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return WOLFSSL_FAILURE; + } + } + if (!(len = wc_ecc_size((ecc_key*)ctx->pkey->ecc->internal))) { + return WOLFSSL_FAILURE; + } + if (key) { + word32 len32 = (word32)len; + if (*keylen < len32) { + WOLFSSL_MSG("buffer too short"); + return WOLFSSL_FAILURE; + } + if (wc_ecc_shared_secret_ssh((ecc_key*)ctx->pkey->ecc->internal, + (ecc_point*)ctx->peerKey->ecc->pub_key->internal, + key, &len32) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + return WOLFSSL_FAILURE; + } + len = (int)len32; + } + *keylen = (size_t)len; + break; +#endif + default: + WOLFSSL_MSG("Unknown key type"); + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} +#endif + +/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. + * + * ctx structure to decrypt with + * out buffer to hold the results + * outlen initially holds size of out buffer and gets set to decrypt result size + * in buffer decrypt + * inlen length of in buffer + * + * returns WOLFSSL_SUCCESS on success. + */ +int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_decrypt"); + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure for decryption + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with decryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_decrypt_init"); + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_DECRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * out buffer to hold encrypted data + * outlen length of out buffer + * in data to be encrypted + * inlen length of in buffer + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt"); + if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE; + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) + break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt_init"); + + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_ENCRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} +/****************************************************************************** +* wolfSSL_EVP_PKEY_sign_init - initializes a public key algorithm context for +* a signing operation. +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns -2 +*/ +WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + int ret = -2; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign_init"); + if (!ctx || !ctx->pkey) + return ret; + + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_SIGN; + ret = WOLFSSL_SUCCESS; + break; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + ret = -2; + } + return ret; +} +/****************************************************************************** +* wolfSSL_EVP_PKEY_sign - performs a public key signing operation using ctx +* The data to be signed should be hashed since the function does not hash the data. +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ + +WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, size_t tbslen) +{ + int len = 0; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign"); + + if (!ctx || ctx->op != EVP_PKEY_OP_SIGN || !ctx->pkey) + return WOLFSSL_FAILURE; + + (void)sig; + (void)siglen; + (void)tbs; + (void)tbslen; + (void)len; + + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_private_encrypt((int)tbslen, (unsigned char*)tbs, sig, + ctx->pkey->rsa, ctx->padding); + if (len < 0) + break; + else { + *siglen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + +/* Get the size in bits for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size in bits of key on success + */ +int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey) +{ + int bytes; + + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_bits"); + if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0; + return bytes*8; +} + + +int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + (void)ctx; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, + WOLFSSL_EVP_PKEY **ppkey) +{ + int ret = WOLFSSL_FAILURE; + int ownPkey = 0; + WOLFSSL_EVP_PKEY* pkey; + + if (ctx == NULL || ppkey == NULL) { + return BAD_FUNC_ARG; + } + + pkey = *ppkey; + if (pkey == NULL) { + ownPkey = 1; + pkey = wolfSSL_EVP_PKEY_new(); + + if (pkey == NULL) + return ret; + } + + switch (pkey->type) { +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + pkey->rsa = wolfSSL_RSA_generate_key(ctx->nbits, WC_RSA_EXPONENT, + NULL, NULL); + if (pkey->rsa) { + pkey->ownRsa = 1; + pkey->pkey_sz = wolfSSL_i2d_RSAPrivateKey(pkey->rsa, + (unsigned char**)&pkey->pkey.ptr); + ret = WOLFSSL_SUCCESS; + } + break; +#endif +#ifdef HAVE_ECC + case EVP_PKEY_EC: + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc) { + ret = wolfSSL_EC_KEY_generate_key(pkey->ecc); + if (ret == WOLFSSL_SUCCESS) { + pkey->ownEcc = 1; + } + } +#endif + default: + break; + } + + if (ret != WOLFSSL_SUCCESS && ownPkey) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + + *ppkey = pkey; + + return ret; +} + +/* Get the size in bytes for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size of a key on success which is the maximum size of a + * signature + */ +int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_size"); + + switch (pkey->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + return (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(pkey->rsa)); +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + case EVP_PKEY_EC: + if (pkey->ecc == NULL || pkey->ecc->internal == NULL) { + WOLFSSL_MSG("No ECC key has been set"); + break; + } + return wc_ecc_size((ecc_key*)(pkey->ecc->internal)); +#endif /* HAVE_ECC */ + + default: + break; + } + return 0; +} + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) +{ + (void)pkey; + /* not using missing params callback and returning zero to indicate success */ + return 0; +} +#endif + +WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b) +{ + int ret = -1; /* failure */ + int a_sz = 0, b_sz = 0; + + if (a == NULL || b == NULL) + return ret; + + /* check its the same type of key */ + if (a->type != b->type) + return ret; + + /* get size based on key type */ + switch (a->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + a_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(a->rsa)); + b_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(b->rsa)); + break; +#endif /* !NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + if (a->ecc == NULL || a->ecc->internal == NULL || + b->ecc == NULL || b->ecc->internal == NULL) { + return ret; + } + a_sz = wc_ecc_size((ecc_key*)(a->ecc->internal)); + b_sz = wc_ecc_size((ecc_key*)(b->ecc->internal)); + break; +#endif /* HAVE_ECC */ + default: + break; + } /* switch (a->type) */ + + /* check size */ + if (a_sz <= 0 || b_sz <= 0 || a_sz != b_sz) { + return ret; + } + + /* check public key size */ + if (a->pkey_sz > 0 && b->pkey_sz > 0 && a->pkey_sz != b->pkey_sz) { + return ret; + } + + /* check public key */ + if (a->pkey.ptr && b->pkey.ptr) { + if (XMEMCMP(a->pkey.ptr, b->pkey.ptr, a->pkey_sz) != 0) { + return ret; + } + } + ret = 0; /* success */ + + return ret; +} + +/* Initialize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + +WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignInit"); + return wolfSSL_EVP_DigestInit_ex(ctx,type,impl); +} + + +/* Update structure with data for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for sign + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_SignUpdate("); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + +static const struct s_ent { + const int macType; + const int nid; + const char *name; +} md_tbl[] = { +#ifndef NO_MD4 + {WC_HASH_TYPE_MD4, NID_md4, "MD4"}, +#endif /* NO_MD4 */ + +#ifndef NO_MD5 + {WC_HASH_TYPE_MD5, NID_md5, "MD5"}, +#endif /* NO_MD5 */ + +#ifndef NO_SHA + {WC_HASH_TYPE_SHA, NID_sha1, "SHA"}, +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + {WC_HASH_TYPE_SHA224, NID_sha224, "SHA224"}, +#endif /* WOLFSSL_SHA224 */ +#ifndef NO_SHA256 + {WC_HASH_TYPE_SHA256, NID_sha256, "SHA256"}, +#endif + +#ifdef WOLFSSL_SHA384 + {WC_HASH_TYPE_SHA384, NID_sha384, "SHA384"}, +#endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA512 + {WC_HASH_TYPE_SHA512, NID_sha512, "SHA512"}, +#endif /* WOLFSSL_SHA512 */ +#ifndef WOLFSSL_NOSHA3_224 + {WC_HASH_TYPE_SHA3_224, NID_sha3_224, "SHA3_224"}, +#endif +#ifndef WOLFSSL_NOSHA3_256 + {WC_HASH_TYPE_SHA3_256, NID_sha3_256, "SHA3_256"}, +#endif + {WC_HASH_TYPE_SHA3_384, NID_sha3_384, "SHA3_384"}, +#ifndef WOLFSSL_NOSHA3_512 + {WC_HASH_TYPE_SHA3_512, NID_sha3_512, "SHA3_512"}, +#endif + {0, 0, NULL} +}; + +static int wolfSSL_EVP_md2macType(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + + if (md != NULL) { + for( ent = md_tbl; ent->name != NULL; ent++) { + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->macType; + } + } + } + return WC_HASH_TYPE_NONE; +} + +/* Finalize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sigret buffer to hold resulting signature + * siglen length of sigret buffer + * pkey key to sign with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey) +{ + unsigned int mdsize; + unsigned char md[WC_MAX_DIGEST_SIZE]; + int ret; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignFinal"); + + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sigret; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) break; + return wolfSSL_RSA_sign(nid, md, mdsize, sigret, + siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + + +/* Update structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for verify + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyUpdate"); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + + +/* Finalize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sig buffer holding signature + * siglen length of sig buffer + * pkey key to verify with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey) +{ + int ret; + unsigned char md[WC_MAX_DIGEST_SIZE]; + unsigned int mdsize; + + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyFinal"); + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sig; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) break; + return wolfSSL_RSA_verify(nid, md, mdsize, sig, + (unsigned int)siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + +int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher) +{ + (void)cipher; + /* nothing to do */ + return 0; +} + + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen) +{ + WOLFSSL_EVP_PKEY* pkey; + + (void)e; + + if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0)) + return NULL; + + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL && keylen > 0) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + else { + XMEMCPY(pkey->pkey.ptr, key, keylen); + pkey->pkey_sz = keylen; + pkey->type = pkey->save_type = type; + } + } + + return pkey; +} + + +const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len) +{ + if (pkey == NULL || len == NULL) + return NULL; + + *len = (size_t)pkey->pkey_sz; + + return (const unsigned char*)pkey->pkey.ptr; +} + + +/* Initialize an EVP_DigestSign/Verify operation. + * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey->type == EVP_PKEY_HMAC) { + int hashType; + const unsigned char* key; + size_t keySz; + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + hashType = WC_SHA256; + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + hashType = WC_SHA224; + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + hashType = WC_SHA384; + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + hashType = WC_SHA512; + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + hashType = WC_MD5; + } + #endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + hashType = WC_SHA; + } + #endif /* NO_SHA */ + else + return BAD_FUNC_ARG; + + key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); + + if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) + return WOLFSSL_FAILURE; + + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return WOLFSSL_FAILURE; + + ctx->macType = NID_hmac; + } + else { + int ret; + + if (ctx->pctx == NULL) { + ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_EVP_DigestInit(ctx, type); + if (ret == WOLFSSL_SUCCESS && pctx != NULL) + *pctx = ctx->pctx; + return ret; + } + + return WOLFSSL_SUCCESS; +} + +/* Update an EVP_DigestSign/Verify operation. + * Update a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + else + return wolfSSL_EVP_DigestUpdate(ctx, d, cnt); +} + +/* Finalize an EVP_DigestSign/Verify operation - common part only. + * Finalize a digest for RSA and ECC keys, or HMAC for HMAC key. + * Copies the digest so that you can keep updating. + */ +static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *md, unsigned int* mdlen) +{ + int ret; + + if (ctx->pctx == NULL) { + Hmac hmacCopy; + + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + ret = wc_HmacFinal(&hmacCopy, md) == 0; + wc_HmacFree(&hmacCopy); + return ret; + } + else { + WOLFSSL_EVP_MD_CTX ctxCopy; + + if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + return ret; + } +} + +/* Get the length of the mac based on the digest algorithm. */ +static int wolfssl_mac_len(unsigned char macType) +{ + int hashLen; + + switch (macType) { + #ifndef NO_MD5 + case WC_MD5: + hashLen = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + hashLen = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + hashLen = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + hashLen = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + hashLen = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + hashLen = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + hashLen = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ + + default: + hashLen = 0; + } + + return hashLen; +} + +int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestSignInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, cnt); +} + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return WOLFSSL_FAILURE; + + /* Return the maximum size of the signaure when sig is NULL. */ + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (sig == NULL) { + *siglen = hashLen; + return WOLFSSL_SUCCESS; + } + } +#ifndef NO_RSA + else if (ctx->pctx->pkey->type == EVP_PKEY_RSA) { + if (sig == NULL) { + *siglen = wolfSSL_RSA_size(ctx->pctx->pkey->rsa); + return WOLFSSL_SUCCESS; + } + } +#endif /* !NO_RSA */ +#ifdef HAVE_ECC + else if (ctx->pctx->pkey->type == EVP_PKEY_EC) { + if (sig == NULL) { + /* SEQ + INT + INT */ + *siglen = ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx].size * 2 + + 8; + return WOLFSSL_SUCCESS; + } + } +#endif + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Copy the HMAC result as signature. */ + if ((unsigned int)(*siglen) > hashLen) + *siglen = hashLen; + /* May be a truncated signature. */ + + XMEMCPY(sig, digest, *siglen); + ret = WOLFSSL_SUCCESS; + } + else { + /* Sign the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + unsigned int sigSz; + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) + break; + ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz, + ctx->pctx->pkey->rsa); + if (ret >= 0) + *siglen = sigSz; + break; + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen, + ctx->pctx->pkey->ecc); + if (ecdsaSig == NULL) + break; + *siglen = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + ret = WOLFSSL_SUCCESS; + break; + } + #endif + default: + break; + } + } + + ForceZero(digest, sizeof(digest)); + return ret; +} +int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestVerifyInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + size_t cnt) +{ + WOLFSSL_ENTER("EVP_DigestVerifyUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt); +} + + +int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + const unsigned char *sig, size_t siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + + WOLFSSL_ENTER("EVP_DigestVerifyFinal"); + + if (ctx == NULL || sig == NULL) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (siglen > hashLen) + return WOLFSSL_FAILURE; + /* May be a truncated signature. */ + } + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Check HMAC result matches the signature. */ + if (XMEMCMP(sig, digest, siglen) == 0) + return WOLFSSL_SUCCESS; + return WOLFSSL_FAILURE; + } + else { + /* Verify the signature with the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) + return WOLFSSL_FAILURE; + return wolfSSL_RSA_verify(nid, digest, hashLen, sig, + (unsigned int)siglen, + ctx->pctx->pkey->rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + int ret; + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_d2i_ECDSA_SIG(NULL, &sig, (long)siglen); + if (ecdsaSig == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_ECDSA_do_verify(digest, hashLen, ecdsaSig, + ctx->pctx->pkey->ecc); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + return ret; + } + #endif + default: + break; + } + } + + return WOLFSSL_FAILURE; +} + + +#ifdef WOLFSSL_APACHE_HTTPD +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) + #include <termios.h> +#endif + +#ifndef XGETPASSWD + static int XGETPASSWD(char* buf, int bufSz) { + int ret = WOLFSSL_SUCCESS; + + /* turn off echo for passwords */ + #ifdef USE_WINDOWS_API + DWORD originalTerm; + DWORD newTerm; + CONSOLE_SCREEN_BUFFER_INFO screenOrig; + HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE); + if (GetConsoleMode(stdinHandle, &originalTerm) == 0) { + WOLFSSL_MSG("Couldn't get the original terminal settings"); + return WOLFSSL_FAILURE; + } + newTerm = originalTerm; + newTerm &= ~ENABLE_ECHO_INPUT; + if (SetConsoleMode(stdinHandle, newTerm) == 0) { + WOLFSSL_MSG("Couldn't turn off echo"); + return WOLFSSL_FAILURE; + } + #else + struct termios originalTerm; + struct termios newTerm; + if (tcgetattr(STDIN_FILENO, &originalTerm) != 0) { + WOLFSSL_MSG("Couldn't get the original terminal settings"); + return WOLFSSL_FAILURE; + } + XMEMCPY(&newTerm, &originalTerm, sizeof(struct termios)); + + newTerm.c_lflag &= ~ECHO; + newTerm.c_lflag |= (ICANON | ECHONL); + if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) { + WOLFSSL_MSG("Couldn't turn off echo"); + return WOLFSSL_FAILURE; + } + #endif + + if (XFGETS(buf, bufSz, stdin) == NULL) { + ret = WOLFSSL_FAILURE; + } + + /* restore default echo */ + #ifdef USE_WINDOWS_API + if (SetConsoleMode(stdinHandle, originalTerm) == 0) { + WOLFSSL_MSG("Couldn't restore the terminal settings"); + return WOLFSSL_FAILURE; + } + #else + if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) { + WOLFSSL_MSG("Couldn't restore the terminal settings"); + return WOLFSSL_FAILURE; + } + #endif + return ret; + } +#endif + +/* returns 0 on success and -2 or -1 on failure */ +int wolfSSL_EVP_read_pw_string(char* buf, int bufSz, const char* banner, int v) +{ + printf("%s", banner); + if (XGETPASSWD(buf, bufSz) == WOLFSSL_FAILURE) { + return -1; + } + (void)v; /* fgets always sanity checks size of input vs buffer */ + return 0; +} +#endif /* WOLFSSL_APACHE_HTTPD */ + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) +int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + int keylen, unsigned char *out) +{ + const char *nostring = ""; + int ret = 0; + + if (pass == NULL) { + passlen = 0; + pass = nostring; + } + else if (passlen == -1) { + passlen = (int)XSTRLEN(pass); + } + + ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, + iter, keylen, WC_SHA); + if (ret == 0) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* !NO_PWDBASED !NO_SHA*/ + +#if !defined(NO_PWDBASED) +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + const WOLFSSL_EVP_MD *digest, + int keylen, unsigned char *out) +{ + const char *nostring = ""; + int ret = 0; + + if (pass == NULL) { + passlen = 0; + pass = nostring; + } else if (passlen == -1) { + passlen = (int)XSTRLEN(pass); + } + + ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, + iter, keylen, wolfSSL_EVP_md2macType(digest)); + if (ret == 0) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* !NO_PWDBASED */ + +static const struct cipher{ + unsigned char type; + const char *name; + int nid; +} cipher_tbl[] = { + +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + {AES_128_CBC_TYPE, "AES-128-CBC", NID_aes_128_cbc}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CBC_TYPE, "AES-192-CBC", NID_aes_192_cbc}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CBC_TYPE, "AES-256-CBC", NID_aes_256_cbc}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB1_TYPE, "AES-128-CFB1", NID_aes_128_cfb1}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB1_TYPE, "AES-192-CFB1", NID_aes_192_cfb1}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB1_TYPE, "AES-256-CFB1", NID_aes_256_cfb1}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB8_TYPE, "AES-128-CFB8", NID_aes_128_cfb8}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB8_TYPE, "AES-192-CFB8", NID_aes_192_cfb8}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB8_TYPE, "AES-256-CFB8", NID_aes_256_cfb8}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB128_TYPE, "AES-128-CFB128", NID_aes_128_cfb128}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB128_TYPE, "AES-192-CFB128", NID_aes_192_cfb128}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB128_TYPE, "AES-256-CFB128", NID_aes_256_cfb128}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_OFB_TYPE, "AES-128-OFB", NID_aes_128_ofb}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_OFB_TYPE, "AES-192-OFB", NID_aes_192_ofb}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_OFB_TYPE, "AES-256-OFB", NID_aes_256_ofb}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_XTS_TYPE, "AES-128-XTS", NID_aes_128_xts}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_XTS_TYPE, "AES-256-XTS", NID_aes_256_xts}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_GCM_TYPE, "AES-128-GCM", NID_aes_128_gcm}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_GCM_TYPE, "AES-192-GCM", NID_aes_192_gcm}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_GCM_TYPE, "AES-256-GCM", NID_aes_256_gcm}, + #endif + #ifdef WOLFSSL_AES_128 + {AES_128_CTR_TYPE, "AES-128-CTR", NID_aes_128_ctr}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CTR_TYPE, "AES-192-CTR", NID_aes_192_ctr}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CTR_TYPE, "AES-256-CTR", NID_aes_256_ctr}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_ECB_TYPE, "AES-128-ECB", NID_aes_128_ecb}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_ECB_TYPE, "AES-192-ECB", NID_aes_192_ecb}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_ECB_TYPE, "AES-256-ECB", NID_aes_256_ecb}, + #endif + +#endif + +#ifndef NO_DES3 + {DES_CBC_TYPE, "DES-CBC", NID_des_cbc}, + {DES_ECB_TYPE, "DES-ECB", NID_des_ecb}, + + {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC", NID_des_ede3_cbc}, + {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB", NID_des_ede3_ecb}, +#endif + +#ifndef NO_RC4 + {ARC4_TYPE, "ARC4", NID_undef}, +#endif + +#ifdef HAVE_IDEA + {IDEA_CBC_TYPE, "IDEA-CBC", NID_idea_cbc}, +#endif + { 0, NULL, 0} +}; + +/* returns cipher using provided ctx type */ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_CIPHER_CTX_cipher( + const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + const struct cipher* c; + + if (!ctx || !ctx->cipherType) { + return NULL; + } + + for (c = cipher_tbl; c->type != 0; c++) { + if (ctx->cipherType == c->type) { + return wolfSSL_EVP_get_cipherbyname(c->name); + } + } + + return NULL; +} + +int wolfSSL_EVP_CIPHER_nid(const WOLFSSL_EVP_CIPHER *cipher) +{ + const struct cipher* c; + + if (!cipher) { + return 0; + } + + for (c = cipher_tbl; c->type != 0; c++) { + if (XSTRNCMP(cipher, c->name, XSTRLEN(c->name)+1) == 0) { + return c->nid; + } + } + + return 0; +} + +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) +{ + + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { +#ifndef NO_DES3 + {"DES-CBC", "DES"}, + {"DES-CBC", "des"}, + {"DES-ECB", "DES-ECB"}, + {"DES-ECB", "des-ecb"}, + {"DES-EDE3-CBC", "DES3"}, + {"DES-EDE3-CBC", "des3"}, + {"DES-EDE3-ECB", "DES-EDE3"}, + {"DES-EDE3-ECB", "des-ede3"}, + {"DES-EDE3-ECB", "des-ede3-ecb"}, +#endif +#ifdef HAVE_IDEA + {"IDEA-CBC", "IDEA"}, + {"IDEA-CBC", "idea"}, +#endif +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + {"AES-128-CBC", "AES128-CBC"}, + {"AES-128-CBC", "aes128-cbc"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-CBC", "AES192-CBC"}, + {"AES-192-CBC", "aes192-cbc"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-CBC", "AES256-CBC"}, + {"AES-256-CBC", "aes256-cbc"}, + #endif + #endif + #ifdef WOLFSSL_AES_128 + {"AES-128-ECB", "AES128-ECB"}, + {"AES-128-ECB", "aes128-ecb"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-ECB", "AES192-ECB"}, + {"AES-192-ECB", "aes192-ecb"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-ECB", "AES256-ECB"}, + #endif + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + {"AES-128-GCM", "aes-128-gcm"}, + {"AES-128-GCM", "id-aes128-GCM"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-GCM", "aes-192-gcm"}, + {"AES-192-GCM", "id-aes192-GCM"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-GCM", "aes-256-gcm"}, + {"AES-256-GCM", "id-aes256-GCM"}, + #endif + #endif +#endif +#ifndef NO_RC4 + {"ARC4", "RC4"}, +#endif + { NULL, NULL} + }; + + const struct cipher *ent; + const struct alias *al; + + WOLFSSL_ENTER("EVP_get_cipherbyname"); + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = cipher_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (WOLFSSL_EVP_CIPHER *)ent->name; + } + + return NULL; +} + +/* + * return an EVP_CIPHER structure when cipher NID is passed. + * + * id cipher NID + * + * return WOLFSSL_EVP_CIPHER +*/ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id) +{ + WOLFSSL_ENTER("EVP_get_cipherbynid"); + + switch(id) { + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + case NID_aes_128_cbc: + return wolfSSL_EVP_aes_128_cbc(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_cbc: + return wolfSSL_EVP_aes_192_cbc(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_cbc: + return wolfSSL_EVP_aes_256_cbc(); + #endif + #endif + #ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ctr: + return wolfSSL_EVP_aes_128_ctr(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ctr: + return wolfSSL_EVP_aes_192_ctr(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ctr: + return wolfSSL_EVP_aes_256_ctr(); + #endif + #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AES_ECB + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ecb: + return wolfSSL_EVP_aes_128_ecb(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ecb: + return wolfSSL_EVP_aes_192_ecb(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ecb: + return wolfSSL_EVP_aes_256_ecb(); + #endif + #endif /* HAVE_AES_ECB */ + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case NID_aes_128_gcm: + return wolfSSL_EVP_aes_128_gcm(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_gcm: + return wolfSSL_EVP_aes_192_gcm(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_gcm: + return wolfSSL_EVP_aes_256_gcm(); + #endif + #endif +#endif + +#ifndef NO_DES3 + case NID_des_cbc: + return wolfSSL_EVP_des_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ecb: + return wolfSSL_EVP_des_ecb(); +#endif + case NID_des_ede3_cbc: + return wolfSSL_EVP_des_ede3_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ede3_ecb: + return wolfSSL_EVP_des_ede3_ecb(); +#endif +#endif /*NO_DES3*/ + +#ifdef HAVE_IDEA + case NID_idea_cbc: + return wolfSSL_EVP_idea_cbc(); +#endif + + default: + WOLFSSL_MSG("Bad cipher id value"); + } + + return NULL; +} + +void wolfSSL_EVP_init(void) +{ +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC"); + #endif + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB1 = (char *)EVP_get_cipherbyname("AES-128-CFB1"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB1 = (char *)EVP_get_cipherbyname("AES-192-CFB1"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB1 = (char *)EVP_get_cipherbyname("AES-256-CFB1"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB8 = (char *)EVP_get_cipherbyname("AES-128-CFB8"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB8 = (char *)EVP_get_cipherbyname("AES-192-CFB8"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB8 = (char *)EVP_get_cipherbyname("AES-256-CFB8"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB128 = (char *)EVP_get_cipherbyname("AES-128-CFB128"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB128 = (char *)EVP_get_cipherbyname("AES-192-CFB128"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB128 = (char *)EVP_get_cipherbyname("AES-256-CFB128"); + #endif + #endif /* WOLFSSL_AES_CFB */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + EVP_AES_128_OFB = (char *)EVP_get_cipherbyname("AES-128-OFB"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_OFB = (char *)EVP_get_cipherbyname("AES-192-OFB"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_OFB = (char *)EVP_get_cipherbyname("AES-256-OFB"); + #endif + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + EVP_AES_128_XTS = (char *)EVP_get_cipherbyname("AES-128-XTS"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_XTS = (char *)EVP_get_cipherbyname("AES-256-XTS"); + #endif + #endif /* WOLFSSL_AES_XTS */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + EVP_AES_128_GCM = (char *)EVP_get_cipherbyname("AES-128-GCM"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_GCM = (char *)EVP_get_cipherbyname("AES-192-GCM"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_GCM = (char *)EVP_get_cipherbyname("AES-256-GCM"); + #endif + #endif /* HAVE_AESGCM*/ + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB"); + #endif +#endif /* ifndef NO_AES*/ + +#ifndef NO_DES3 + EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC"); + EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB"); + + EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC"); + EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB"); +#endif + +#ifdef HAVE_IDEA + EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC"); +#endif +} + +#if !defined(NO_PWDBASED) +int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, + int* pHash, int* pHashSz) +{ + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int hashSz; + + if (XSTRLEN(evp) < 3) { + /* do not try comparing strings if size is too small */ + return WOLFSSL_FAILURE; + } + + if (XSTRNCMP("SHA", evp, 3) == 0) { + if (XSTRLEN(evp) > 3) { + #ifndef NO_SHA256 + if (XSTRNCMP("SHA256", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA256; + } + else + #endif + #ifdef WOLFSSL_SHA384 + if (XSTRNCMP("SHA384", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA384; + } + else + #endif + #ifdef WOLFSSL_SHA512 + if (XSTRNCMP("SHA512", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA512; + } + else + #endif + { + WOLFSSL_MSG("Unknown SHA hash"); + } + } + else { + hash = WC_HASH_TYPE_SHA; + } + } +#ifdef WOLFSSL_MD2 + else if (XSTRNCMP("MD2", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD2; + } +#endif +#ifndef NO_MD4 + else if (XSTRNCMP("MD4", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD4; + } +#endif +#ifndef NO_MD5 + else if (XSTRNCMP("MD5", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD5; + } +#endif + + if (pHash) + *pHash = hash; + + hashSz = wc_HashGetDigestSize(hash); + if (pHashSz) + *pHashSz = hashSz; + + if (hashSz < 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* this function makes the assumption that out buffer is big enough for digest*/ +int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng) +{ + int err; + int hashType = WC_HASH_TYPE_NONE; + int hashSz; + + WOLFSSL_ENTER("wolfSSL_EVP_Digest"); + if (in == NULL || out == NULL || evp == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return WOLFSSL_FAILURE; + } + + err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz); + if (err != WOLFSSL_SUCCESS) + return err; + + if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, hashSz) != 0) { + return WOLFSSL_FAILURE; + } + + if (outSz != NULL) + *outSz = hashSz; + + (void)eng; + return WOLFSSL_SUCCESS; +} +#endif + +const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) +{ + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"MD4", "ssl3-md4"}, + {"MD5", "ssl3-md5"}, + {"SHA", "ssl3-sha1"}, + {"SHA", "SHA1"}, + { NULL, NULL} + }; + + const struct alias *al; + const struct s_ent *ent; + + + for (al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for (ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (EVP_MD *)ent->name; + } + return NULL; +} + +int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + WOLFSSL_ENTER("EVP_MD_type"); + for( ent = md_tbl; ent->name != NULL; ent++){ + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->nid; + } + } + return 0; +} + +#ifndef NO_MD4 + + /* return a pointer to MD4 EVP type */ + const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_md4"); + return EVP_get_digestbyname("MD4"); + } + +#endif /* !NO_MD4 */ + + +#ifndef NO_MD5 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) + { + WOLFSSL_ENTER("EVP_md5"); + return EVP_get_digestbyname("MD5"); + } + +#endif /* !NO_MD5 */ + + +#ifndef NO_WOLFSSL_STUB + const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void) + { + WOLFSSL_STUB("EVP_mdc2"); + return NULL; + } +#endif + +#ifndef NO_SHA + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) + { + WOLFSSL_ENTER("EVP_sha1"); + return EVP_get_digestbyname("SHA"); + } +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void) + { + WOLFSSL_ENTER("EVP_sha224"); + return EVP_get_digestbyname("SHA224"); + } + +#endif /* WOLFSSL_SHA224 */ + + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) + { + WOLFSSL_ENTER("EVP_sha256"); + return EVP_get_digestbyname("SHA256"); + } + +#ifdef WOLFSSL_SHA384 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) + { + WOLFSSL_ENTER("EVP_sha384"); + return EVP_get_digestbyname("SHA384"); + } + +#endif /* WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) + { + WOLFSSL_ENTER("EVP_sha512"); + return EVP_get_digestbyname("SHA512"); + } + +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_224(void) + { + WOLFSSL_ENTER("EVP_sha3_224"); + return EVP_get_digestbyname("SHA3_224"); + } +#endif /* WOLFSSL_NOSHA3_224 */ + + +#ifndef WOLFSSL_NOSHA3_256 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void) + { + WOLFSSL_ENTER("EVP_sha3_256"); + return EVP_get_digestbyname("SHA3_256"); + } +#endif /* WOLFSSL_NOSHA3_256 */ + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void) + { + WOLFSSL_ENTER("EVP_sha3_384"); + return EVP_get_digestbyname("SHA3_384"); + } + +#ifndef WOLFSSL_NOSHA3_512 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void) + { + WOLFSSL_ENTER("EVP_sha3_512"); + return EVP_get_digestbyname("SHA3_512"); + } +#endif /* WOLFSSL_NOSHA3_512 */ +#endif /* WOLFSSL_SHA3 */ + + WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void) + { + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_ENTER("EVP_MD_CTX_new"); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_OPENSSL); + if (ctx){ + wolfSSL_EVP_MD_CTX_init(ctx); + } + return ctx; + } + + WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_free"); + wolfSSL_EVP_MD_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + + /* returns the NID of message digest used by the ctx */ + int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) { + const struct s_ent *ent; + + WOLFSSL_ENTER("EVP_MD_CTX_type"); + + if (ctx) { + for(ent = md_tbl; ent->name != NULL; ent++) { + if (ctx->macType == ent->macType) { + return ent->nid; + } + } + /* Return whatever we got */ + return ctx->macType; + } + return 0; + } + + + /* returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + return wolfSSL_EVP_MD_CTX_copy_ex(out, in); + } + + /* returns digest size */ + int wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + /* returns block size */ + int wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_block_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + + /* Deep copy of EVP_MD hasher + * return WOLFSSL_SUCCESS on success */ + static int wolfSSL_EVP_MD_Copy_Hasher(WOLFSSL_EVP_MD_CTX* des, + const WOLFSSL_EVP_MD_CTX* src) + { + if (src->macType == NID_hmac) { + wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); + } + else { + switch (src->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Copy((wc_Md5*)&src->hash.digest, + (wc_Md5*)&des->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaCopy((wc_Sha*)&src->hash.digest, + (wc_Sha*)&des->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Copy((wc_Sha224*)&src->hash.digest, + (wc_Sha224*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Copy((wc_Sha256*)&src->hash.digest, + (wc_Sha256*)&des->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Copy((wc_Sha384*)&src->hash.digest, + (wc_Sha384*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Copy((wc_Sha512*)&src->hash.digest, + (wc_Sha512*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + + case WC_HASH_TYPE_SHA3_384: + wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; + } + + /* copies structure in to the structure out + * + * returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex"); + XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX)); + if (in->pctx != NULL) { + out->pctx = wolfSSL_EVP_PKEY_CTX_new(in->pctx->pkey, NULL); + if (out->pctx == NULL) + return WOLFSSL_FAILURE; + } + return wolfSSL_EVP_MD_Copy_Hasher(out, (WOLFSSL_EVP_MD_CTX*)in); + } + + void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); + } + + const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) + { + const struct s_ent *ent; + if (ctx == NULL) + return NULL; + WOLFSSL_ENTER("EVP_MD_CTX_md"); + for(ent = md_tbl; ent->name != NULL; ent++) { + if(ctx->macType == ent->macType) { + return (const WOLFSSL_EVP_MD *)ent->name; + } + } + return (WOLFSSL_EVP_MD *)NULL; + } + + #ifndef NO_AES + + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); + if (EVP_AES_128_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CBC; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc"); + if (EVP_AES_192_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CBC; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc"); + if (EVP_AES_256_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CBC; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb1"); + if (EVP_AES_128_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB1; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb1"); + if (EVP_AES_192_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB1; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb1"); + if (EVP_AES_256_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB1; + } + #endif /* WOLFSSL_AES_256 */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb8"); + if (EVP_AES_128_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB8; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb8"); + if (EVP_AES_192_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB8; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb8"); + if (EVP_AES_256_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB8; + } + #endif /* WOLFSSL_AES_256 */ +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb128"); + if (EVP_AES_128_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB128; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb128"); + if (EVP_AES_192_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB128; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb128"); + if (EVP_AES_256_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB128; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_CFB */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ofb"); + if (EVP_AES_128_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_OFB; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ofb"); + if (EVP_AES_192_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_OFB; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ofb"); + if (EVP_AES_256_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_OFB; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_xts(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_xts"); + if (EVP_AES_128_XTS == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_XTS; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_xts(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_xts"); + if (EVP_AES_256_XTS == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_XTS; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_XTS */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_gcm"); + if (EVP_AES_128_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_GCM; + } + #endif /* WOLFSSL_GCM_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_gcm"); + if (EVP_AES_192_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_GCM; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_gcm"); + if (EVP_AES_256_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_GCM; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AESGCM */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); + if (EVP_AES_128_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CTR; + } + #endif /* WOLFSSL_AES_2128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr"); + if (EVP_AES_192_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CTR; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr"); + if (EVP_AES_256_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CTR; + } + #endif /* WOLFSSL_AES_256 */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); + if (EVP_AES_128_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_ECB; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb"); + if (EVP_AES_192_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_ECB; + } + #endif /* WOLFSSL_AES_192*/ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb"); + if (EVP_AES_256_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_ECB; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* NO_AES */ + +#ifndef NO_DES3 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); + if (EVP_DES_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_DES_CBC; + } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); + if (EVP_DES_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_DES_ECB; + } +#endif + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); + if (EVP_DES_EDE3_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_DES_EDE3_CBC; + } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb"); + if (EVP_DES_EDE3_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_DES_EDE3_ECB; + } +#endif +#endif /* NO_DES3 */ + +#ifndef NO_RC4 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) + { + static const char* type = "ARC4"; + WOLFSSL_ENTER("wolfSSL_EVP_rc4"); + return type; + } +#endif + +#ifdef HAVE_IDEA + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc"); + if (EVP_IDEA_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_IDEA_CBC; + } +#endif + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void) + { + static const char* type = "NULL"; + WOLFSSL_ENTER("wolfSSL_EVP_enc_null"); + return type; + } + + int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); + if (ctx->pctx != NULL) + wolfSSL_EVP_PKEY_CTX_free(ctx->pctx); + + if (ctx->macType == NID_hmac) { + wc_HmacFree(&ctx->hash.hmac); + } + else { + switch (ctx->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Free((wc_Md5*)&ctx->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaFree((wc_Sha*)&ctx->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Free((wc_Sha224*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Free((wc_Sha256*)&ctx->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Free((wc_Sha384*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Free((wc_Sha512*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wc_Sha3_224_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + + case WC_HASH_TYPE_SHA3_384: + wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest); + break; + + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wc_Sha3_512_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + } + ForceZero(ctx, sizeof(*ctx)); + ctx->macType = WC_HASH_TYPE_NONE; + return 1; + } + + void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_init"); + if (ctx) { + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_CIPHER_CTX)); + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + ctx->enc = 1; /* start in encrypt mode */ + } + } + +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) + static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) + { + int i; + for (i = ctrSz-1; i >= 0; i--) { + if (++ctr[i]) + break; + } + } +#endif + + /* This function allows cipher specific parameters to be + determined and set. */ + int wolfSSL_EVP_CIPHER_CTX_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, int type, \ + int arg, void *ptr) + { + int ret = WOLFSSL_FAILURE; +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG) + WC_RNG rng; +#endif + if (ctx == NULL) + return WOLFSSL_FAILURE; + + (void)arg; + (void)ptr; + + WOLFSSL_ENTER("EVP_CIPHER_CTX_ctrl"); + + switch(type) { + case EVP_CTRL_INIT: + wolfSSL_EVP_CIPHER_CTX_init(ctx); + if(ctx) + ret = WOLFSSL_SUCCESS; + break; + case EVP_CTRL_SET_KEY_LENGTH: + ret = wolfSSL_EVP_CIPHER_CTX_set_key_length(ctx, arg); + break; +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG) + case EVP_CTRL_GCM_SET_IVLEN: + if(arg <= 0 || arg > 16) + return WOLFSSL_FAILURE; + ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg); + break; + case EVP_CTRL_AEAD_SET_IV_FIXED: + if (arg == -1) { + /* arg == -1 copies ctx->ivSz from ptr */ + ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, (byte*)ptr, ctx->ivSz); + } + else { + /* + * Fixed field must be at least 4 bytes and invocation + * field at least 8. + */ + if ((arg < 4) || (ctx->ivSz - arg) < 8) { + WOLFSSL_MSG("Fixed field or invocation field too short"); + ret = WOLFSSL_FAILURE; + break; + } + if (wc_InitRng(&rng) != 0) { + WOLFSSL_MSG("wc_InitRng failed"); + ret = WOLFSSL_FAILURE; + break; + } + if (arg) { + XMEMCPY(ctx->iv, ptr, arg); + } + if (wc_RNG_GenerateBlock(&rng, ctx->iv + arg, + ctx->ivSz - arg) != 0) { + /* rng is freed immediately after if block so no need + * to do it here + */ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + ret = WOLFSSL_FAILURE; + } + + if (wc_FreeRng(&rng) != 0) { + WOLFSSL_MSG("wc_FreeRng failed"); + ret = WOLFSSL_FAILURE; + break; + } + } + break; +#if !defined(_WIN32) && !defined(HAVE_FIPS) + case EVP_CTRL_GCM_IV_GEN: + if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) { + ret = WOLFSSL_FAILURE; + WOLFSSL_MSG("Key or IV not set"); + break; + } + if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) { + WOLFSSL_MSG("wc_AesGcmSetIV failed"); + ret = WOLFSSL_FAILURE; + } + /* OpenSSL increments the IV. Not sure why */ + IncCtr(ctx->iv, ctx->ivSz); + break; +#endif + case EVP_CTRL_AEAD_SET_TAG: + if(arg <= 0 || arg > 16 || (ptr == NULL)) + return WOLFSSL_FAILURE; + + XMEMCPY(ctx->authTag, ptr, arg); + ctx->authTagSz = arg; + ret = WOLFSSL_SUCCESS; + + break; + case EVP_CTRL_AEAD_GET_TAG: + if(arg <= 0 || arg > 16) + return WOLFSSL_FAILURE; + + XMEMCPY(ptr, ctx->authTag, arg); + ret = WOLFSSL_SUCCESS; + break; +#endif /* HAVE_AESGCM && !HAVE_SELFTEST && !WC_NO_RNG */ + default: + WOLFSSL_MSG("EVP_CIPHER_CTX_ctrl operation not yet handled"); + ret = WOLFSSL_FAILURE; + } + return ret; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); + if (ctx) { + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + } + + return WOLFSSL_SUCCESS; + } + + /* Permanent stub for Qt compilation. */ + #if defined(WOLFSSL_QT) && !defined(NO_WOLFSSL_STUB) + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_rc2_cbc"); + WOLFSSL_STUB("EVP_rc2_cbc"); + return NULL; + } + #endif + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + + int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type, + const WOLFSSL_EVP_MD* md, const byte* salt, + const byte* data, int sz, int count, byte* key, byte* iv) + { + int ret; + int hashType = WC_HASH_TYPE_NONE; + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info; + #else + EncryptedInfo info[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + #endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + + ret = wc_EncryptedInfoGet(info, type); + if (ret < 0) + goto end; + + if (data == NULL) { + ret = info->keySz; + goto end; + } + + ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL); + if (ret == WOLFSSL_FAILURE) + goto end; + + ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt, + EVP_SALT_SIZE, count, hashType, NULL); + if (ret == 0) + ret = info->keySz; + + end: + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + if (ret < 0) + return 0; /* failure - for compatibility */ + + return ret; + } + +#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + +#ifndef NO_AES + static int AesSetKey_ex(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir, int direct) + { + int ret; + /* wc_AesSetKey clear aes.reg if iv == NULL. + Keep IV for openSSL compatibility */ + if (iv == NULL) + XMEMCPY((byte *)aes->tmp, (byte *)aes->reg, AES_BLOCK_SIZE); + if (direct) { + #if defined(WOLFSSL_AES_DIRECT) + ret = wc_AesSetKeyDirect(aes, key, len, iv, dir); + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + ret = wc_AesSetKey(aes, key, len, iv, dir); + } + if (iv == NULL) + XMEMCPY((byte *)aes->reg, (byte *)aes->tmp, AES_BLOCK_SIZE); + return ret; + } +#endif + + /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, const byte* key, + const byte* iv, int enc) + { + int ret = 0; + (void)key; + (void)iv; + (void)enc; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return WOLFSSL_FAILURE; + } + + if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) { + WOLFSSL_MSG("no type set"); + return WOLFSSL_FAILURE; + } + if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){ + /* only first EVP_CipherInit invoke. ctx->cipherType is set below */ + XMEMSET(&ctx->cipher, 0, sizeof(ctx->cipher)); + ctx->flags = 0; + } + /* always clear buffer state */ + ctx->bufUsed = 0; + ctx->lastUsed = 0; + +#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV + if (!iv && ctx->ivSz) { + iv = ctx->iv; + } +#endif + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CBC"); + ctx->cipherType = AES_128_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CBC"); + ctx->cipherType = AES_192_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CBC"); + ctx->cipherType = AES_256_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ +#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_GCM"); + ctx->cipherType = AES_128_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_GCM"); + ctx->cipherType = AES_192_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_GCM"); + ctx->cipherType = AES_256_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AESGCM */ +#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CTR"); + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->cipherType = AES_128_CTR_TYPE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 16; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CTR"); + ctx->cipherType = AES_192_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 24; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CTR"); + ctx->cipherType = AES_256_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 32; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_256 */ +#endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_ECB"); + ctx->cipherType = AES_128_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_ECB"); + ctx->cipherType = AES_192_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_ECB"); + ctx->cipherType = AES_256_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB1"); + ctx->cipherType = AES_128_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB1"); + ctx->cipherType = AES_192_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB1"); + ctx->cipherType = AES_256_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB8"); + ctx->cipherType = AES_128_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB8"); + ctx->cipherType = AES_192_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB8"); + ctx->cipherType = AES_256_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB128"); + ctx->cipherType = AES_128_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB128"); + ctx->cipherType = AES_192_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB128"); + ctx->cipherType = AES_256_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CFB */ + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_OFB"); + ctx->cipherType = AES_128_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_OFB"); + ctx->cipherType = AES_192_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_OFB"); + ctx->cipherType = AES_256_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_OFB */ + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_XTS_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_XTS"); + ctx->cipherType = AES_128_XTS_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_XTS_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + ctx->ivSz = AES_BLOCK_SIZE; + + if (iv != NULL) { + if (iv != ctx->iv) /* Valgrind error when src == dst */ + XMEMCPY(ctx->iv, iv, ctx->ivSz); + } + else + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("wc_AesXtsSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_XTS_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_XTS"); + ctx->cipherType = AES_256_XTS_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_XTS_MODE; + ctx->keyLen = 64; + ctx->block_size = 1; + ctx->ivSz = AES_BLOCK_SIZE; + + if (iv != NULL) { + if (iv != ctx->iv) /* Valgrind error when src == dst */ + XMEMCPY(ctx->iv, iv, ctx->ivSz); + } + else + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("wc_AesXtsSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_XTS */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + if (ctx->cipherType == DES_CBC_TYPE || + (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_CBC"); + ctx->cipherType = DES_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + ctx->ivSz = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des_SetKey(&ctx->cipher.des, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) + wc_Des_SetIV(&ctx->cipher.des, iv); + } +#ifdef WOLFSSL_DES_ECB + else if (ctx->cipherType == DES_ECB_TYPE || + (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_ECB"); + ctx->cipherType = DES_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + WOLFSSL_MSG("Des_SetKey"); + ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } +#endif + else if (ctx->cipherType == DES_EDE3_CBC_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_CBC"); + ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + ctx->ivSz = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) { + ret = wc_Des3_SetIV(&ctx->cipher.des3, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + else if (ctx->cipherType == DES_EDE3_ECB_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_ECB"); + ctx->cipherType = DES_EDE3_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } +#endif /* NO_DES3 */ +#ifndef NO_RC4 + if (ctx->cipherType == ARC4_TYPE || (type && + XSTRNCMP(type, "ARC4", 4) == 0)) { + WOLFSSL_MSG("ARC4"); + ctx->cipherType = ARC4_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_STREAM_CIPHER; + ctx->block_size = 1; + if (ctx->keyLen == 0) /* user may have already set */ + ctx->keyLen = 16; /* default to 128 */ + if (key) + wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen); + } +#endif /* NO_RC4 */ +#ifdef HAVE_IDEA + if (ctx->cipherType == IDEA_CBC_TYPE || + (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { + WOLFSSL_MSG("EVP_IDEA_CBC"); + ctx->cipherType = IDEA_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = IDEA_KEY_SIZE; + ctx->block_size = 8; + ctx->ivSz = IDEA_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen, + iv, ctx->enc ? IDEA_ENCRYPTION : + IDEA_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) + wc_IdeaSetIV(&ctx->cipher.idea, iv); + } +#endif /* HAVE_IDEA */ + if (ctx->cipherType == NULL_CIPHER_TYPE || (type && + XSTRNCMP(type, "NULL", 4) == 0)) { + WOLFSSL_MSG("NULL cipher"); + ctx->cipherType = NULL_CIPHER_TYPE; + ctx->keyLen = 0; + ctx->block_size = 16; + } +#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV + if (iv && iv != ctx->iv) { + if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + } +#endif + (void)ret; /* remove warning. If execution reaches this point, ret=0 */ + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length"); + if (ctx) + return ctx->keyLen; + + return 0; /* failure */ + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int keylen) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length"); + if (ctx) + ctx->keyLen = keylen; + else + return 0; /* failure */ + + return WOLFSSL_SUCCESS; + } +#if defined(HAVE_AESGCM) + /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ + int wolfSSL_EVP_CIPHER_CTX_set_iv_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int ivLen) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length"); + if (ctx) + ctx->ivSz= ivLen; + else + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + + /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ + int wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv, + int ivLen) + { + int expectedIvLen; + + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length"); + if (!ctx || !iv || !ivLen) { + return WOLFSSL_FAILURE; + } + + expectedIvLen = wolfSSL_EVP_CIPHER_CTX_iv_length(ctx); + + if (expectedIvLen == 0 || expectedIvLen != ivLen) { + WOLFSSL_MSG("Wrong ivLen value"); + return WOLFSSL_FAILURE; + } + + return wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, -1); + } +#endif + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, + word32 len) + { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_EVP_Cipher"); + + if (ctx == NULL || src == NULL || + (dst == NULL && + ctx->cipherType != AES_128_GCM_TYPE && + ctx->cipherType != AES_192_GCM_TYPE && + ctx->cipherType != AES_256_GCM_TYPE)) { + WOLFSSL_MSG("Bad function argument"); + return 0; /* failure */ + } + + if (ctx->cipherType == 0xff) { + WOLFSSL_MSG("no init"); + return 0; /* failure */ + } + + switch (ctx->cipherType) { + +#ifndef NO_AES +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* HAVE_AES_CBC */ + +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + if (ctx->enc) + ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, dst, src, len); + break; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + if (ctx->enc) + ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + if (ctx->enc) + ret = wc_AesCfbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + if (ctx->enc) + ret = wc_AesOfbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesOfbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_OFB */ +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + if (ctx->enc) + ret = wc_AesXtsEncrypt(&ctx->cipher.xts, dst, src, len, + ctx->iv, ctx->ivSz); + else + ret = wc_AesXtsDecrypt(&ctx->cipher.xts, dst, src, len, + ctx->iv, ctx->ivSz); + break; +#endif /* WOLFSSL_AES_XTS */ + +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + if (ctx->enc) { + if (dst){ + /* encrypt confidential data*/ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src, len, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data */ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + src, len); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + else { + if (dst){ + /* decrypt confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src, len, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, + ctx->authTag, ctx->authTagSz, + src, len); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + break; +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + if (ctx->enc) + wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len); + else + wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES3 CBC"); + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); + break; +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); + break; +#endif +#endif /* !NO_DES3 */ + +#ifndef NO_RC4 + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + wc_Arc4Process(&ctx->cipher.arc4, dst, src, len); + break; +#endif + +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + if (ctx->enc) + wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len); + else + wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len); + break; +#endif + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL CIPHER"); + XMEMCPY(dst, src, len); + break; + + default: { + WOLFSSL_MSG("bad type"); + return 0; /* failure */ + } + } + + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + + if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); + return WOLFSSL_SUCCESS; /* success */ + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* md) + { + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("EVP_DigestInit"); + + if (ctx == NULL || md == NULL) { + return BAD_FUNC_ARG; + } + + + #ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); + #endif + + /* Set to 0 if no match */ + ctx->macType = wolfSSL_EVP_md2macType(md); + if (XSTRNCMP(md, "SHA256", 6) == 0) { + ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(md, "SHA224", 6) == 0) { + ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(md, "SHA384", 6) == 0) { + ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(md, "SHA512", 6) == 0) { + ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); + } + #endif + #ifndef NO_MD4 + else if (XSTRNCMP(md, "MD4", 3) == 0) { + wolfSSL_MD4_Init(&(ctx->hash.digest.md4)); + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(md, "MD5", 3) == 0) { + ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5)); + } + #endif +#ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + else if (XSTRNCMP(md, "SHA3_224", 8) == 0) { + ret = wolfSSL_SHA3_224_Init(&(ctx->hash.digest.sha3_224)); + } + #endif + #ifndef WOLFSSL_NOSHA3_256 + else if (XSTRNCMP(md, "SHA3_256", 8) == 0) { + ret = wolfSSL_SHA3_256_Init(&(ctx->hash.digest.sha3_256)); + } + #endif + else if (XSTRNCMP(md, "SHA3_384", 8) == 0) { + ret = wolfSSL_SHA3_384_Init(&(ctx->hash.digest.sha3_384)); + } + #ifndef WOLFSSL_NOSHA3_512 + else if (XSTRNCMP(md, "SHA3_512", 8) == 0) { + ret = wolfSSL_SHA3_512_Init(&(ctx->hash.digest.sha3_512)); + } + #endif +#endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(md, "SHA", 3) == 0) { + ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); + } + #endif /* NO_SHA */ + else { + ctx->macType = WC_HASH_TYPE_NONE; + return BAD_FUNC_ARG; + } + + return ret; + } + + /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */ + int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, + size_t sz) + { + int macType; + + WOLFSSL_ENTER("EVP_DigestUpdate"); + + macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx)); + switch (macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + case WC_HASH_TYPE_SHA3_384: + wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + int macType; + + WOLFSSL_ENTER("EVP_DigestFinal"); + macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx)); + switch (macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash); + if (s) *s = MD4_DIGEST_SIZE; + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); + if (s) *s = WC_MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); + if (s) *s = WC_SHA_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash); + if (s) *s = WC_SHA224_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); + if (s) *s = WC_SHA256_DIGEST_SIZE; + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); + if (s) *s = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); + if (s) *s = WC_SHA512_DIGEST_SIZE; + break; +#endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_224_DIGEST_SIZE; + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_256_DIGEST_SIZE; + break; + #endif + case WC_HASH_TYPE_SHA3_384: + wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_384_DIGEST_SIZE; + break; + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_512_DIGEST_SIZE; + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + WOLFSSL_ENTER("EVP_DigestFinal_ex"); + return EVP_DigestFinal(ctx, md, s); + } + + void wolfSSL_EVP_cleanup(void) + { + /* nothing to do here */ + } + +const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) +{ + WOLFSSL_MSG("wolfSSL_get_digestbynid"); + + switch(id) { +#ifndef NO_MD5 + case NID_md5: + return wolfSSL_EVP_md5(); +#endif +#ifndef NO_SHA + case NID_sha1: + return wolfSSL_EVP_sha1(); +#endif + default: + WOLFSSL_MSG("Bad digest id value"); + } + + return NULL; +} + +#ifndef NO_RSA +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(WOLFSSL_EVP_PKEY *pkey) +{ + if (!pkey) { + return NULL; + } + return pkey->rsa; +} + +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_RSA* local; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA"); + + if (key == NULL) { + return NULL; + } + + local = wolfSSL_RSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure"); + return NULL; + } + + if (key->type == EVP_PKEY_RSA) { + if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_RSA_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_RSA_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key"); + wolfSSL_RSA_free(local); + local = NULL; + } + return local; +} + +/* with set1 functions the pkey struct does not own the RSA structure + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) +{ +#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) + int derMax = 0; + int derSz = 0; + byte* derBuf = NULL; + RsaKey* rsa = NULL; +#endif + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA"); + if ((pkey == NULL) || (key == NULL)) + return WOLFSSL_FAILURE; + + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->rsa = key; + pkey->ownRsa = 0; /* pkey does not own RSA */ + pkey->type = EVP_PKEY_RSA; + if (key->inSet == 0) { + if (SetRsaInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + +#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) + rsa = (RsaKey*)key->internal; + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * information */ + derMax = 5 * wolfSSL_RSA_size(key) + (2 * AES_BLOCK_SIZE); + + derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + if (rsa->type == RSA_PRIVATE) { + /* Private key to DER */ + derSz = wc_RsaKeyToDer(rsa, derBuf, derMax); + } + else { + /* Public key to DER */ + derSz = wc_RsaKeyToPublicDer(rsa, derBuf, derMax); + } + + if (derSz < 0) { + if (rsa->type == RSA_PRIVATE) { + WOLFSSL_MSG("wc_RsaKeyToDer failed"); + } + else { + WOLFSSL_MSG("wc_RsaKeyToPublicDer failed"); + } + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_KEY_GEN && !HAVE_USER_RSA */ + +#ifdef WC_RSA_BLINDING + if (key->ownRng == 0) { + if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) { + WOLFSSL_MSG("Error setting RSA rng"); + return WOLFSSL_FAILURE; + } + } +#endif + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#if !defined (NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN) +/* with set1 functions the pkey struct does not own the DSA structure + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key) +{ + int derMax = 0; + int derSz = 0; + DsaKey* dsa = NULL; + byte* derBuf = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DSA"); + + if((pkey == NULL) || (key == NULL))return WOLFSSL_FAILURE; + if (pkey->dsa != NULL && pkey->ownDsa == 1) { + wolfSSL_DSA_free(pkey->dsa); + } + pkey->dsa = key; + pkey->ownDsa = 0; /* pkey does not own DSA */ + pkey->type = EVP_PKEY_DSA; + if (key->inSet == 0) { + if (SetDsaInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + dsa = (DsaKey*)key->internal; + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ + derMax = 4 * wolfSSL_BN_num_bytes(key->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + if (dsa->type == DSA_PRIVATE) { + /* Private key to DER */ + derSz = wc_DsaKeyToDer(dsa, derBuf, derMax); + } + else { + /* Public key to DER */ + derSz = wc_DsaKeyToPublicDer(dsa, derBuf, derMax); + } + + if (derSz < 0) { + if (dsa->type == DSA_PRIVATE) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + } + else { + WOLFSSL_MSG("wc_DsaKeyToPublicDer failed"); + } + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_DSA* local; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DSA"); + + if (key == NULL) { + WOLFSSL_MSG("Bad function argument"); + return NULL; + } + + local = wolfSSL_DSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DSA structure"); + return NULL; + } + + if (key->type == EVP_PKEY_DSA) { + if (wolfSSL_DSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_DSA_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_DSA_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DSA key"); + wolfSSL_DSA_free(local); + local = NULL; + } + return local; +} +#endif /* !NO_DSA && !HAVE_SELFTEST && WOLFSSL_KEY_GEN */ + +#ifdef HAVE_ECC +WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_EC_KEY *eckey = NULL; + if (pkey) { +#ifdef HAVE_ECC + eckey = pkey->ecc; +#endif + } + return eckey; +} + +WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_EC_KEY* local; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_EC_KEY"); + + if (key == NULL) { + return NULL; + } + + local = wolfSSL_EC_KEY_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure"); + return NULL; + } + + if (key->type == EVP_PKEY_EC) { + if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_EC_KEY_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, + key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != SSL_SUCCESS) { + + wolfSSL_EC_KEY_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an EC key"); + wolfSSL_EC_KEY_free(local); + local = NULL; + } +#ifdef OPENSSL_ALL + if (!local && key->ecc) { + local = wolfSSL_EC_KEY_dup(key->ecc); + } +#endif + return local; +} +#endif /* HAVE_ECC */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if !defined(NO_DH) && !defined(NO_FILESYSTEM) +/* with set1 functions the pkey struct does not own the DH structure + * Build the following DH Key format from the passed in WOLFSSL_DH + * then store in WOLFSSL_EVP_PKEY in DER format. + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) +{ + byte havePublic = 0, havePrivate = 0; + int ret; + word32 derSz = 0; + byte* derBuf = NULL; + DhKey* dhkey = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DH"); + + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + if (pkey->dh != NULL && pkey->ownDh == 1) + wolfSSL_DH_free(pkey->dh); + + pkey->dh = key; + pkey->ownDh = 0; /* pkey does not own DH */ + pkey->type = EVP_PKEY_DH; + if (key->inSet == 0) { + if (SetDhInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDhInternal failed"); + return WOLFSSL_FAILURE; + } + } + + dhkey = (DhKey*)key->internal; + + havePublic = mp_unsigned_bin_size(&dhkey->pub) > 0; + havePrivate = mp_unsigned_bin_size(&dhkey->priv) > 0; + + /* Get size of DER buffer only */ + if (havePublic && !havePrivate) { + ret = wc_DhPubKeyToDer(dhkey, NULL, &derSz); + } else if (havePrivate && !havePublic) { + ret = wc_DhPrivKeyToDer(dhkey, NULL, &derSz); + } else { + ret = wc_DhParamsToDer(dhkey,NULL,&derSz); + } + + if (derSz <= 0 || ret != LENGTH_ONLY_E) { + WOLFSSL_MSG("Failed to get size of DH Key"); + return WOLFSSL_FAILURE; + } + + derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Fill DER buffer */ + if (havePublic && !havePrivate) { + ret = wc_DhPubKeyToDer(dhkey, derBuf, &derSz); + } else if (havePrivate && !havePublic) { + ret = wc_DhPrivKeyToDer(dhkey, derBuf, &derSz); + } else { + ret = wc_DhParamsToDer(dhkey,derBuf,&derSz); + } + + if (ret <= 0) { + WOLFSSL_MSG("Failed to export DH Key"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* Store DH key into pkey (DER format) */ + pkey->pkey.ptr = (char*)derBuf; + pkey->pkey_sz = derSz; + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key) +{ + if (!key) { + return NULL; + } + return key->dh; +} + +WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_DH* local = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DH"); + + if (key == NULL || key->dh == NULL) { + WOLFSSL_MSG("Bad function argument"); + return NULL; + } + + if (key->type == EVP_PKEY_DH) { + local = wolfSSL_DH_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DH structure"); + return NULL; + } + + if (wolfSSL_DH_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + wolfSSL_DH_free(local); + WOLFSSL_MSG("Error wolfSSL_DH_LoadDer"); + local = NULL; + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DH key"); + wolfSSL_DH_free(local); + return NULL; + } + + return local; +} +#endif /* NO_DH && NO_FILESYSTEM */ + +int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_assign"); + + /* pkey and key checked if NULL in subsequent assign functions */ + switch(type) { + #ifndef NO_RSA + case EVP_PKEY_RSA: + ret = wolfSSL_EVP_PKEY_assign_RSA(pkey, (WOLFSSL_RSA*)key); + break; + #endif + #ifndef NO_DSA + case EVP_PKEY_DSA: + ret = wolfSSL_EVP_PKEY_assign_DSA(pkey, (WOLFSSL_DSA*)key); + break; + #endif + #ifdef HAVE_ECC + case EVP_PKEY_EC: + ret = wolfSSL_EVP_PKEY_assign_EC_KEY(pkey, (WOLFSSL_EC_KEY*)key); + break; + #endif + #ifdef NO_DH + case EVP_PKEY_DH: + ret = wolfSSL_EVP_PKEY_assign_DH(pkey, (WOLFSSL_DH*)key); + break; + #endif + default: + WOLFSSL_MSG("Unknown EVP_PKEY type in wolfSSL_EVP_PKEY_assign."); + ret = WOLFSSL_FAILURE; + } + + return ret; +} +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + +#if defined(HAVE_ECC) +/* try and populate public pkey_sz and pkey.ptr */ +static void ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc) +{ + int ret; + if (!pkey || !ecc) + return; + if ((ret = wc_EccPublicKeyDerSize(ecc, 1)) > 0) { + int derSz = ret; + char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf) { + ret = wc_EccPublicKeyToDer(ecc, (byte*)derBuf, derSz, 1); + if (ret >= 0) { + if (pkey->pkey.ptr) { + XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL); + } + pkey->pkey_sz = ret; + pkey->pkey.ptr = derBuf; + } + else { /* failure - okay to ignore */ + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + } + } + } +} + +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) +{ +#ifdef HAVE_ECC + if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_EC_KEY"); +#ifndef NO_RSA + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->ownRsa = 0; +#endif +#ifndef NO_DSA + if (pkey->dsa != NULL && pkey->ownDsa == 1) { + wolfSSL_DSA_free(pkey->dsa); + } + pkey->ownDsa = 0; +#endif +#ifndef NO_DH + if (pkey->dh != NULL && pkey->ownDh == 1) { + wolfSSL_DH_free(pkey->dh); + } + pkey->ownDh = 0; +#endif + if (pkey->ecc != NULL && pkey->ownEcc == 1) { + wolfSSL_EC_KEY_free(pkey->ecc); + } + pkey->ecc = key; + pkey->ownEcc = 0; /* pkey does not own EC key */ + pkey->type = EVP_PKEY_EC; + ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + return WOLFSSL_SUCCESS; +#else + (void)pkey; + (void)key; + return WOLFSSL_FAILURE; +#endif +} + +void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state"); + return (void*)&ctx->cipher.arc4.x; + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return NULL; +} +int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_EC; + pkey->ecc = key; + pkey->ownEcc = 1; + + /* try and populate public pkey_sz and pkey.ptr */ + ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ + +#ifndef NO_WOLFSSL_STUB +const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +{ + WOLFSSL_MSG("wolfSSL_ripemd160"); + WOLFSSL_STUB("EVP_ripemd160"); + return NULL; +} +#endif + + +int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_block_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_BLOCK_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return WC_SHA512_BLOCK_SIZE; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + return WC_SHA_BLOCK_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + +int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_DIGEST_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return WC_SHA512_DIGEST_SIZE; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + return WC_SHA_DIGEST_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + + +int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); + + switch (ctx->cipherType) { + +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + return AES_BLOCK_SIZE; +#endif +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + return GCM_NONCE_MID_SZ; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + return AES_BLOCK_SIZE; +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + return DES_BLOCK_SIZE; + + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + return DES_BLOCK_SIZE; +#endif +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + return IDEA_BLOCK_SIZE; +#endif +#ifndef NO_RC4 + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + return 0; +#endif +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + return AES_BLOCK_SIZE; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + return AES_BLOCK_SIZE; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_OFB */ +#ifdef WOLFSSL_AES_XTS + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_XTS */ + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + return 0; + + default: { + WOLFSSL_MSG("bad type"); + } + } + return 0; +} + +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); + +#ifndef NO_AES +#ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_CBC && XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_CBC && XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_CBC && XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_GCM && XSTRNCMP(name, EVP_AES_128_GCM, XSTRLEN(EVP_AES_128_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_GCM && XSTRNCMP(name, EVP_AES_192_GCM, XSTRLEN(EVP_AES_192_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_GCM && XSTRNCMP(name, EVP_AES_256_GCM, XSTRLEN(EVP_AES_256_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif +#endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_CTR && XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_CTR && XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_CTR && XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif +#ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_XTS && XSTRNCMP(name, EVP_AES_128_XTS, XSTRLEN(EVP_AES_128_XTS)) == 0) + return AES_BLOCK_SIZE; + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_XTS && XSTRNCMP(name, EVP_AES_256_XTS, XSTRLEN(EVP_AES_256_XTS)) == 0) + return AES_BLOCK_SIZE; + #endif /* WOLFSSL_AES_256 */ +#endif /* WOLFSSL_AES_XTS */ + +#endif + +#ifndef NO_DES3 + if ((EVP_DES_CBC && XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (EVP_DES_EDE3_CBC && XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (EVP_IDEA_CBC && XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + + +int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state size"); + return sizeof(Arc4); + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return 0; +} + + +/* return of pkey->type which will be EVP_PKEY_RSA for example. + * + * type type of EVP_PKEY + * + * returns type or if type is not found then NID_undef + */ +int wolfSSL_EVP_PKEY_type(int type) +{ + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type"); + + switch (type) { + case EVP_PKEY_RSA: + return EVP_PKEY_RSA; + case EVP_PKEY_DSA: + return EVP_PKEY_DSA; + case EVP_PKEY_EC: + return EVP_PKEY_EC; + case EVP_PKEY_DH: + return EVP_PKEY_DH; + default: + return NID_undef; + } +} + + +int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey) +{ + if (pkey != NULL) + return pkey->type; + return 0; +} + + +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + if (pkey == NULL) + return NID_undef; + return wolfSSL_EVP_PKEY_type(pkey->type); +} + + +/* increments ref count of WOLFSSL_EVP_PKEY. Return 1 on success, 0 on error */ +int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey) +{ + if (pkey) { + if (wc_LockMutex(&pkey->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock pkey mutex"); + } + pkey->references++; + wc_UnLockMutex(&pkey->refMutex); + + return 1; + } + + return 0; +} + +#ifndef NO_RSA +int wolfSSL_EVP_PKEY_assign_RSA(EVP_PKEY* pkey, WOLFSSL_RSA* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = key; + pkey->ownRsa = 1; + + /* try and populate public pkey_sz and pkey.ptr */ + if (key->internal) { + RsaKey* rsa = (RsaKey*)key->internal; + int ret = wc_RsaPublicKeyDerSize(rsa, 1); + if (ret > 0) { + int derSz = ret; + char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf) { + ret = wc_RsaKeyToPublicDer(rsa, (byte*)derBuf, derSz); + if (ret >= 0) { + pkey->pkey_sz = ret; + pkey->pkey.ptr = derBuf; + } + else { /* failure - okay to ignore */ + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + } + } + } + } + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#ifndef NO_DSA +int wolfSSL_EVP_PKEY_assign_DSA(EVP_PKEY* pkey, WOLFSSL_DSA* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_DSA; + pkey->dsa = key; + pkey->ownDsa = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DSA */ + +#ifndef NO_DH +int wolfSSL_EVP_PKEY_assign_DH(EVP_PKEY* pkey, WOLFSSL_DH* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_DH; + pkey->dh = key; + pkey->ownDh = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DH */ + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA_X509_SMALL) +/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the + * subset of X509 API */ + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new(void){ + return wolfSSL_EVP_PKEY_new_ex(NULL); +} + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) +{ + WOLFSSL_EVP_PKEY* pkey; + int ret; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_ex"); + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + pkey->heap = heap; + pkey->type = WOLFSSL_EVP_PKEY_DEFAULT; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); +#else + ret = wc_InitRng(&pkey->rng); +#endif + if (ret != 0){ + wolfSSL_EVP_PKEY_free(pkey); + WOLFSSL_MSG("memory failure"); + return NULL; + } + pkey->references = 1; + wc_InitMutex(&pkey->refMutex); + } + else { + WOLFSSL_MSG("memory failure"); + } + + return pkey; +} + +void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) +{ + int doFree = 0; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free"); + if (key != NULL) { + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock pkey mutex"); + } + + /* only free if all references to it are done */ + key->references--; + if (key->references == 0) { + doFree = 1; + } + wc_UnLockMutex(&key->refMutex); + + if (doFree) { + wc_FreeRng(&key->rng); + + if (key->pkey.ptr != NULL) { + XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key->pkey.ptr = NULL; + } + switch(key->type) + { + #ifndef NO_RSA + case EVP_PKEY_RSA: + if (key->rsa != NULL && key->ownRsa == 1) { + wolfSSL_RSA_free(key->rsa); + key->rsa = NULL; + } + break; + #endif /* NO_RSA */ + + #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) + case EVP_PKEY_EC: + if (key->ecc != NULL && key->ownEcc == 1) { + wolfSSL_EC_KEY_free(key->ecc); + key->ecc = NULL; + } + break; + #endif /* HAVE_ECC && OPENSSL_EXTRA */ + + #ifndef NO_DSA + case EVP_PKEY_DSA: + if (key->dsa != NULL && key->ownDsa == 1) { + wolfSSL_DSA_free(key->dsa); + key->dsa = NULL; + } + break; + #endif /* NO_DSA */ + + #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case EVP_PKEY_DH: + if (key->dh != NULL && key->ownDh == 1) { + wolfSSL_DH_free(key->dh); + key->dh = NULL; + } + break; + #endif /* ! NO_DH ... */ + + default: + break; + } + + if (wc_FreeMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Couldn't free pkey mutex"); + } + XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + } +} + +#endif /* OPENSSL_EXTRA_X509_SMALL */ + +#endif /* WOLFSSL_EVP_INCLUDED */ |