/* evp.c * * Copyright (C) 2006-2022 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 */ #ifdef HAVE_CONFIG_H #include #endif #include #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 #if defined(OPENSSL_EXTRA) #if !defined(HAVE_PKCS7) && \ ((defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ (HAVE_FIPS_VERSION == 2)) || defined(HAVE_SELFTEST)) #include #endif #include #include #include #include #ifndef NO_AES #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_CBC[] = "AES-128-CBC"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_CBC[] = "AES-192-CBC"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_CBC[] = "AES-256-CBC"; #endif #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ #ifdef WOLFSSL_AES_OFB #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_OFB[] = "AES-128-OFB"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_OFB[] = "AES-192-OFB"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_OFB[] = "AES-256-OFB"; #endif #endif /* WOLFSSL_AES_OFB */ #ifdef WOLFSSL_AES_XTS #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_XTS[] = "AES-128-XTS"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_XTS[] = "AES-256-XTS"; #endif #endif /* WOLFSSL_AES_XTS */ #ifdef WOLFSSL_AES_CFB #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_CFB1[] = "AES-128-CFB1"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_CFB1[] = "AES-192-CFB1"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_CFB1[] = "AES-256-CFB1"; #endif #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_CFB8[] = "AES-128-CFB8"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_CFB8[] = "AES-192-CFB8"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_CFB8[] = "AES-256-CFB8"; #endif #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_CFB128[] = "AES-128-CFB128"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_CFB128[] = "AES-192-CFB128"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_CFB128[] = "AES-256-CFB128"; #endif #endif /* WOLFSSL_AES_CFB */ #ifdef HAVE_AESGCM #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_GCM[] = "AES-128-GCM"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_GCM[] = "AES-192-GCM"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_GCM[] = "AES-256-GCM"; #endif #endif /* HAVE_AESGCM */ #ifdef WOLFSSL_AES_COUNTER #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_CTR[] = "AES-128-CTR"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_CTR[] = "AES-192-CTR"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_CTR[] = "AES-256-CTR"; #endif #endif #ifdef HAVE_AES_ECB #ifdef WOLFSSL_AES_128 static const char EVP_AES_128_ECB[] = "AES-128-ECB"; #endif #ifdef WOLFSSL_AES_192 static const char EVP_AES_192_ECB[] = "AES-192-ECB"; #endif #ifdef WOLFSSL_AES_256 static const char EVP_AES_256_ECB[] = "AES-256-ECB"; #endif #endif #endif #ifndef NO_DES3 static const char EVP_DES_CBC[] = "DES-CBC"; static const char EVP_DES_ECB[] = "DES-ECB"; static const char EVP_DES_EDE3_CBC[] = "DES-EDE3-CBC"; static const char EVP_DES_EDE3_ECB[] = "DES-EDE3-ECB"; #endif #ifndef NO_RC4 static const char EVP_ARC4[] = "ARC4"; #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) static const char EVP_CHACHA20_POLY1305[] = "CHACHA20-POLY1305"; #endif static const char EVP_NULL[] = "NULL"; #define EVP_CIPHER_TYPE_MATCHES(x, y) (XSTRCMP(x,y) == 0) #define EVP_PKEY_PRINT_LINE_WIDTH_MAX 80 #define EVP_PKEY_PRINT_DIGITS_PER_LINE 15 static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); static enum wc_HashType EvpMd2MacType(const WOLFSSL_EVP_MD *md); /* 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) || defined(WOLFSSL_AES_DIRECT) 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) /* Two keys for XTS. */ case AES_128_XTS_TYPE: return 16 * 2; case AES_256_XTS_TYPE: return 32 * 2; #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 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: return 32; #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; } unsigned long wolfSSL_EVP_CIPHER_CTX_flags(const WOLFSSL_EVP_CIPHER_CTX *ctx) { if (ctx == NULL) return 0; return ctx->flags; } 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(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: ret = WOLFSSL_FAILURE; } (void)in; (void)inl; (void)out; return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } #if defined(HAVE_AESGCM) #ifndef WOLFSSL_AESGCM_STREAM static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { byte* tmp = (byte*)XREALLOC(ctx->gcmAuthIn, ctx->gcmAuthInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL); if (tmp) { ctx->gcmAuthIn = tmp; XMEMCPY(ctx->gcmAuthIn + ctx->gcmAuthInSz, in, inl); ctx->gcmAuthInSz += inl; } else { WOLFSSL_MSG("realloc error"); return MEMORY_E; } } return 0; } #endif /* WOLFSSL_AESGCM_STREAM */ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { #ifndef WOLFSSL_AESGCM_STREAM int ret = 0; *outl = inl; if (out) { /* Buffer input for one-shot API */ if (inl > 0) { byte* tmp; tmp = (byte*)XREALLOC(ctx->gcmBuffer, ctx->gcmBufferLen + inl, NULL, DYNAMIC_TYPE_OPENSSL); if (tmp) { XMEMCPY(tmp + ctx->gcmBufferLen, in, inl); ctx->gcmBufferLen += inl; ctx->gcmBuffer = tmp; *outl = 0; } else { ret = MEMORY_E; } } } else { ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, in, inl); } if (ret != 0) { *outl = 0; return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; #else int ret; /* When out is NULL then this is AAD. */ if (out == NULL) { if (ctx->enc) { ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in, inl); } else { ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in, inl); } } /* When out is not NULL then this is plaintext/cipher text. */ else { if (ctx->enc) { ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, out, in, inl, NULL, 0); } else { ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, out, in, inl, NULL, 0); } } *outl = inl; if (ret == 0) { ret = WOLFSSL_SUCCESS; } else { ret = WOLFSSL_FAILURE; } return ret; #endif /* WOLFSSL_AESGCM_STREAM */ } #endif /* HAVE_AESGCM */ /* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ 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 (inl == 0 && in == NULL ) { /* Nothing to do in this case. Just return. */ return WOLFSSL_SUCCESS; } if ((ctx == NULL) || (inl < 0) || (outl == NULL) || (in == NULL)) { WOLFSSL_MSG("Bad argument"); return WOLFSSL_FAILURE; } *outl = 0; switch (ctx->cipherType) { #if !defined(NO_AES) && defined(HAVE_AESGCM) 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); #endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: if (out == NULL) { if (wc_ChaCha20Poly1305_UpdateAad(&ctx->cipher.chachaPoly, in, inl) != 0) { WOLFSSL_MSG("wc_ChaCha20Poly1305_UpdateAad failed"); return WOLFSSL_FAILURE; } else { *outl = inl; return WOLFSSL_SUCCESS; } } else { if (wc_ChaCha20Poly1305_UpdateData(&ctx->cipher.chachaPoly, in, out, inl) != 0) { WOLFSSL_MSG("wc_ChaCha20Poly1305_UpdateData failed"); return WOLFSSL_FAILURE; } else { *outl = inl; return WOLFSSL_SUCCESS; } } #endif default: /* fall-through */ break; } if (out == NULL) { return WOLFSSL_FAILURE; } /* if(inl == 0)wolfSSL_EVP_CipherUpdate_GCM to get tag */ if (inl == 0) { return WOLFSSL_SUCCESS; } 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; } #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) { int i; for (i = ctrSz-1; i >= 0; i--) { if (++ctr[i]) break; } } #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) || * HAVE_FIPS_VERSION >= 2 */ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { int fl; int ret = WOLFSSL_SUCCESS; #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) byte tmp = 0; #endif if (!ctx || !outl) return WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); switch (ctx->cipherType) { #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) case AES_128_GCM_TYPE: case AES_192_GCM_TYPE: case AES_256_GCM_TYPE: #ifndef WOLFSSL_AESGCM_STREAM if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0) || (ctx->gcmBufferLen == 0)) { if (ctx->enc) ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, ctx->gcmBuffer, ctx->gcmBufferLen, ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); else ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, ctx->gcmBuffer, ctx->gcmBufferLen, ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); if (ret == 0) { ret = WOLFSSL_SUCCESS; *outl = ctx->gcmBufferLen; } else { ret = WOLFSSL_FAILURE; *outl = 0; } XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL); ctx->gcmBuffer = NULL; ctx->gcmBufferLen = 0; if (ctx->gcmIncIv) { IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz); ctx->gcmIncIv = 0; } } else { *outl = 0; } #else /* No data to return - all handled in Update. */ *outl = 0; if (ctx->enc) { ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes, ctx->authTag, ctx->authTagSz); } else { ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag, ctx->authTagSz); if (ctx->gcmIncIv) { IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz); } } if (ret == 0) { /* Reinitialize for subsequent wolfSSL_EVP_Cipher calls. */ if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, (byte*)ctx->cipher.aes.reg, ctx->ivSz) != 0) { WOLFSSL_MSG("wc_AesGcmInit failed"); ret = WOLFSSL_FAILURE; } else { ret = WOLFSSL_SUCCESS; } } else { ret = WOLFSSL_FAILURE; } #endif /* WOLFSSL_AESGCM_STREAM */ if (ret == WOLFSSL_SUCCESS) { if (ctx->gcmIncIv) { ctx->gcmIncIv = 0; } else { /* Clear IV, since IV reuse is not recommended for AES GCM. */ XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); } if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { ret = WOLFSSL_FAILURE; } } break; #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) || * HAVE_FIPS_VERSION >= 2 */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly, ctx->authTag) != 0) { WOLFSSL_MSG("wc_ChaCha20Poly1305_Final failed"); return WOLFSSL_FAILURE; } else { *outl = 0; return WOLFSSL_SUCCESS; } #endif default: 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; } } break; } if (ret == WOLFSSL_SUCCESS) { #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) /* * This flag needs to retain its value between wolfSSL_EVP_CipherFinal * calls. wolfSSL_EVP_CipherInit will clear it, so we save and restore * it here. */ if (ctx->cipherType == AES_128_GCM_TYPE || ctx->cipherType == AES_192_GCM_TYPE || ctx->cipherType == AES_256_GCM_TYPE) { tmp = ctx->gcmIvGenEnable; } #endif /* reset cipher state after final */ ret = wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1); #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) if (ctx->cipherType == AES_128_GCM_TYPE || ctx->cipherType == AES_192_GCM_TYPE || ctx->cipherType == AES_256_GCM_TYPE) { ctx->gcmIvGenEnable = tmp; } #endif } 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. */ 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) || defined(WOLFSSL_AES_DIRECT) 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_CIPHER_TYPE_MATCHES(cipher, EVP_DES_CBC)) return DES_CBC_TYPE; else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_DES_EDE3_CBC)) return DES_EDE3_CBC_TYPE; #if !defined(NO_DES3) else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_DES_ECB)) return DES_ECB_TYPE; else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_DES_EDE3_ECB)) return DES_EDE3_ECB_TYPE; #endif /* NO_DES3 && HAVE_AES_ECB */ #endif #if !defined(NO_AES) #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CBC)) return AES_128_CBC_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CBC)) return AES_192_CBC_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CBC)) return AES_256_CBC_TYPE; #endif #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ #if defined(HAVE_AESGCM) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_GCM)) return AES_128_GCM_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_GCM)) return AES_192_GCM_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_GCM)) return AES_256_GCM_TYPE; #endif #endif /* HAVE_AESGCM */ #if defined(WOLFSSL_AES_COUNTER) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CTR)) return AES_128_CTR_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CTR)) return AES_192_CTR_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CTR)) return AES_256_CTR_TYPE; #endif #endif /* HAVE_AES_CBC */ #if defined(HAVE_AES_ECB) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_ECB)) return AES_128_ECB_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_ECB)) return AES_192_ECB_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_ECB)) return AES_256_ECB_TYPE; #endif #endif /*HAVE_AES_CBC */ #if defined(WOLFSSL_AES_XTS) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_XTS)) return AES_128_XTS_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_XTS)) return AES_256_XTS_TYPE; #endif #endif /* WOLFSSL_AES_XTS */ #if defined(WOLFSSL_AES_CFB) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CFB1)) return AES_128_CFB1_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CFB1)) return AES_192_CFB1_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CFB1)) return AES_256_CFB1_TYPE; #endif #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CFB8)) return AES_128_CFB8_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CFB8)) return AES_192_CFB8_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CFB8)) return AES_256_CFB8_TYPE; #endif #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CFB128)) return AES_128_CFB128_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CFB128)) return AES_192_CFB128_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CFB128)) return AES_256_CFB128_TYPE; #endif #endif /*HAVE_AES_CBC */ #if defined(WOLFSSL_AES_OFB) #ifdef WOLFSSL_AES_128 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_OFB)) return AES_128_OFB_TYPE; #endif #ifdef WOLFSSL_AES_192 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_OFB)) return AES_192_OFB_TYPE; #endif #ifdef WOLFSSL_AES_256 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_OFB)) return AES_256_OFB_TYPE; #endif #endif #endif /* !NO_AES */ #ifndef NO_RC4 else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_ARC4)) return ARC4_TYPE; #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_CHACHA20_POLY1305)) return CHACHA20_POLY1305_TYPE; #endif 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) || defined(WOLFSSL_AES_DIRECT) 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 1; #endif #if defined(WOLFSSL_AES_COUNTER) case AES_128_CTR_TYPE: case AES_192_CTR_TYPE: case AES_256_CTR_TYPE: return 1; #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 #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: return 1; #endif #if defined(WOLFSSL_AES_OFB) case AES_128_OFB_TYPE: case AES_192_OFB_TYPE: case AES_256_OFB_TYPE: return 1; #endif #if defined(WOLFSSL_AES_XTS) case AES_128_XTS_TYPE: case AES_256_XTS_TYPE: return 1; #endif #endif /* NO_AES */ #ifndef NO_RC4 case ARC4_TYPE: return 1; #endif #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 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: return 1; #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) || defined(WOLFSSL_AES_DIRECT) 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 | WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER; #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 #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: return WOLFSSL_EVP_CIPH_CFB_MODE; #endif #if defined(WOLFSSL_AES_OFB) case AES_128_OFB_TYPE: case AES_192_OFB_TYPE: case AES_256_OFB_TYPE: return WOLFSSL_EVP_CIPH_OFB_MODE; #endif #if defined(WOLFSSL_AES_XTS) case AES_128_XTS_TYPE: case AES_256_XTS_TYPE: return WOLFSSL_EVP_CIPH_XTS_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_AES */ #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 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: return WOLFSSL_EVP_CIPH_STREAM_CIPHER | WOLFSSL_EVP_CIPH_FLAG_AEAD_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) & WOLFSSL_EVP_CIPH_MODE; } 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 */ #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L void wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) #else int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) #endif { if (ctx == NULL) #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L return; #else return 0; #endif 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); #if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L return WOLFSSL_SUCCESS; #endif } /* Creates a new WOLFSSL_EVP_PKEY_CTX structure. * * pkey key structure to use with new WOLFSSL_EVP_PKEY_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; 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; ctx->md = NULL; #endif #ifdef HAVE_ECC if (pkey->ecc && pkey->ecc->group) { /* set curve NID from pkey if available */ ctx->curveNID = pkey->ecc->group->curve_nid; } else { ctx->curveNID = ECC_CURVE_DEF; } #endif if (wolfSSL_EVP_PKEY_up_ref(pkey) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Couldn't increase key reference count"); } 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; } /* Sets the message digest type for RSA padding to use. * * ctx structure to set padding in. * md Message digest * * returns WOLFSSL_SUCCESS on success. */ int wolfSSL_EVP_PKEY_CTX_set_signature_md(WOLFSSL_EVP_PKEY_CTX *ctx, const EVP_MD* md) { if (ctx == NULL) return 0; WOLFSSL_ENTER("EVP_PKEY_CTX_set_signature_md"); #ifndef NO_RSA ctx->md = md; #else (void)md; #endif return WOLFSSL_SUCCESS; } /* create a PKEY context 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); /* wolfSSL_EVP_PKEY_CTX_new calls wolfSSL_EVP_PKEY_up_ref so we need * to always call wolfSSL_EVP_PKEY_free (either to free it if an * error occurred in the previous function or to decrease the reference * count so that pkey is actually free'd when wolfSSL_EVP_PKEY_CTX_free * is called) */ 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; } #ifndef NO_WOLFSSL_STUB int wolfSSL_EVP_PKEY_CTX_ctrl_str(WOLFSSL_EVP_PKEY_CTX *ctx, const char *name, const char *value) { WOLFSSL_STUB("wolfSSL_EVP_PKEY_CTX_ctrl_str"); (void)ctx; (void)name; (void)value; return WOLFSSL_FAILURE; } #endif /* NO_WOLFSSL_STUB */ #if (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || defined(HAVE_ECC) || \ defined(HAVE_HKDF) int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { int len; #ifdef HAVE_HKDF enum wc_HashType hkdfHashType; int hkdfHashSz; #endif WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive"); if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE || !ctx->pkey || (!ctx->peerKey && ctx->pkey->type != EVP_PKEY_HKDF) || !keylen || (ctx->pkey->type != EVP_PKEY_HKDF && 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) { return WOLFSSL_FAILURE; } /* set internal peer key if not done */ if (!ctx->peerKey->dh->inSet) { if (SetDhInternal(ctx->peerKey->dh) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDhInternal failed"); return WOLFSSL_FAILURE; } } if (!ctx->peerKey->dh->pub_key) { WOLFSSL_MSG("SetDhInternal failed, pub_key is NULL"); 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; } /* computed DH agreement can be less than DH size if leading zeros */ if (wolfSSL_DH_compute_key(key, ctx->peerKey->dh->pub_key, ctx->pkey->dh) <= 0) { return WOLFSSL_FAILURE; } } *keylen = (size_t)len; break; #endif #if defined(HAVE_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_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 defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) WC_RNG rng; if (wc_InitRng(&rng) != MP_OKAY) { WOLFSSL_MSG("Init RNG failed"); return WOLFSSL_FAILURE; } ((ecc_key*)ctx->pkey->ecc->internal)->rng = &rng; #endif if (*keylen < len32) { WOLFSSL_MSG("buffer too short"); #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL; wc_FreeRng(&rng); #endif 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"); #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL; wc_FreeRng(&rng); #endif return WOLFSSL_FAILURE; } #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL; wc_FreeRng(&rng); #endif len = (int)len32; } *keylen = (size_t)len; break; #endif #ifdef HAVE_HKDF case EVP_PKEY_HKDF: (void)len; hkdfHashType = EvpMd2MacType(ctx->pkey->hkdfMd); if (hkdfHashType == WC_HASH_TYPE_NONE) { WOLFSSL_MSG("Invalid hash type for HKDF."); return WOLFSSL_FAILURE; } if (ctx->pkey->hkdfMode == EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) { if (wc_HKDF(hkdfHashType, ctx->pkey->hkdfKey, ctx->pkey->hkdfKeySz, ctx->pkey->hkdfSalt, ctx->pkey->hkdfSaltSz, ctx->pkey->hkdfInfo, ctx->pkey->hkdfInfoSz, key, (word32)*keylen) != 0) { WOLFSSL_MSG("wc_HKDF failed."); return WOLFSSL_FAILURE; } } else if (ctx->pkey->hkdfMode == EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) { if (wc_HKDF_Extract(hkdfHashType, ctx->pkey->hkdfSalt, ctx->pkey->hkdfSaltSz, ctx->pkey->hkdfKey, ctx->pkey->hkdfKeySz, key) != 0) { WOLFSSL_MSG("wc_HKDF_Extract failed."); return WOLFSSL_FAILURE; } else { hkdfHashSz = wolfSSL_EVP_MD_size(ctx->pkey->hkdfMd); if (hkdfHashSz <= 0) { WOLFSSL_MSG("Failed to get block size for HKDF hash."); return WOLFSSL_FAILURE; } /* Length of extract only is always the length of the hash. */ *keylen = hkdfHashSz; } } else if (ctx->pkey->hkdfMode == EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) { if (wc_HKDF_Expand(hkdfHashType, ctx->pkey->hkdfKey, ctx->pkey->hkdfKeySz, ctx->pkey->hkdfInfo, ctx->pkey->hkdfInfoSz, key, (word32)*keylen) != 0) { WOLFSSL_MSG("wc_HKDF_Expand failed."); return WOLFSSL_FAILURE; } } else { WOLFSSL_MSG("Invalid HKDF mode."); return WOLFSSL_FAILURE; } break; #endif /* HAVE_HKDF */ default: WOLFSSL_MSG("Unknown key type"); return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; } #endif /* (!NO_DH && WOLFSSL_DH_EXTRA) || HAVE_ECC || HAVE_HKDF */ #ifdef HAVE_HKDF int wolfSSL_EVP_PKEY_CTX_set_hkdf_md(WOLFSSL_EVP_PKEY_CTX* ctx, const WOLFSSL_EVP_MD* md) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set_hkdf_md"); if (ctx == NULL || ctx->pkey == NULL || md == NULL) { WOLFSSL_MSG("Bad argument."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS) { ctx->pkey->hkdfMd = md; } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_CTX_set_hkdf_md", ret); return ret; } int wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt(WOLFSSL_EVP_PKEY_CTX* ctx, byte* salt, int saltSz) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt"); if (ctx == NULL || ctx->pkey == NULL || saltSz < 0) { WOLFSSL_MSG("Bad argument."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && ctx->pkey->type != EVP_PKEY_HKDF) { WOLFSSL_MSG("WOLFSSL_EVP_PKEY type is not HKDF."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && salt != NULL && saltSz > 0) { if (ctx->pkey->hkdfSalt != NULL) { XFREE(ctx->pkey->hkdfSalt, NULL, DYNAMIC_TYPE_SALT); } ctx->pkey->hkdfSalt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SALT); if (ctx->pkey->hkdfSalt == NULL) { WOLFSSL_MSG("Failed to allocate HKDF salt buffer."); ret = WOLFSSL_FAILURE; } else { XMEMCPY(ctx->pkey->hkdfSalt, salt, saltSz); ctx->pkey->hkdfSaltSz = saltSz; } } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt", ret); return ret; } int wolfSSL_EVP_PKEY_CTX_set1_hkdf_key(WOLFSSL_EVP_PKEY_CTX* ctx, byte* key, int keySz) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set1_hkdf_key"); if (ctx == NULL || ctx->pkey == NULL || key == NULL || keySz <= 0) { WOLFSSL_MSG("Bad argument."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && ctx->pkey->type != EVP_PKEY_HKDF) { WOLFSSL_MSG("WOLFSSL_EVP_PKEY type is not HKDF."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS) { if (ctx->pkey->hkdfKey != NULL) { XFREE(ctx->pkey->hkdfKey, NULL, DYNAMIC_TYPE_KEY); } ctx->pkey->hkdfKey = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_KEY); if (ctx->pkey->hkdfKey == NULL) { WOLFSSL_MSG("Failed to allocate HKDF key buffer."); ret = WOLFSSL_FAILURE; } else { XMEMCPY(ctx->pkey->hkdfKey, key, keySz); ctx->pkey->hkdfKeySz = keySz; } } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_CTX_set1_hkdf_key", ret); return ret; } int wolfSSL_EVP_PKEY_CTX_add1_hkdf_info(WOLFSSL_EVP_PKEY_CTX* ctx, byte* info, int infoSz) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_add1_hkdf_info"); if (ctx == NULL || ctx->pkey == NULL || infoSz < 0) { WOLFSSL_MSG("Bad argument."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && ctx->pkey->type != EVP_PKEY_HKDF) { WOLFSSL_MSG("WOLFSSL_EVP_PKEY type is not HKDF."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && info != NULL && infoSz > 0) { /* If there's already info in the buffer, append. */ ctx->pkey->hkdfInfo = (byte*)XREALLOC(ctx->pkey->hkdfInfo, ctx->pkey->hkdfInfoSz + infoSz, NULL, DYNAMIC_TYPE_INFO); if (ctx->pkey->hkdfInfo == NULL) { WOLFSSL_MSG("Failed to reallocate larger HKDF info buffer."); ret = WOLFSSL_FAILURE; } else { XMEMCPY(ctx->pkey->hkdfInfo + ctx->pkey->hkdfInfoSz, info, infoSz); ctx->pkey->hkdfInfoSz += infoSz; } } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_CTX_add1_hkdf_info", ret); return ret; } int wolfSSL_EVP_PKEY_CTX_hkdf_mode(WOLFSSL_EVP_PKEY_CTX* ctx, int mode) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_hkdf_mode"); if (ctx == NULL || ctx->pkey == NULL) { WOLFSSL_MSG("Bad argument."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && mode != EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND && mode != EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY && mode != EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) { WOLFSSL_MSG("Invalid HKDF mode."); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS) { ctx->pkey->hkdfMode = mode; } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_CTX_hkdf_mode", ret); return ret; } #endif /* HAVE_HKDF */ /* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. * * ctx EVP_PKEY context of operation. * out Decrypted output buffer. If NULL, puts the maximum output buffer size in outLen and returns success. * outLen If out is NULL, see above. If out is non-NULL, on input outLen holds * the size of out. On output holds the length of actual decryption. * in Encrypted input buffer. * inLen Length of encrypted data. * * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure. */ 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; WOLFSSL_ENTER("EVP_PKEY_decrypt"); if (ctx == NULL || ctx->pkey == NULL) { WOLFSSL_MSG("Bad parameter."); return 0; } (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: if (out == NULL) { if (ctx->pkey->rsa == NULL) { WOLFSSL_MSG("Internal wolfCrypt RSA object is NULL."); return WOLFSSL_FAILURE; } len = wolfSSL_RSA_size(ctx->pkey->rsa); if (len <= 0) { WOLFSSL_MSG("Error getting RSA size."); return WOLFSSL_FAILURE; } if (outLen == NULL) { WOLFSSL_MSG("outLen is NULL."); return WOLFSSL_FAILURE; } *outLen = len; return WOLFSSL_SUCCESS; } 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("EVP_PKEY_EC 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; } /* Uses the WOLFSSL_EVP_PKEY_CTX to encrypt a buffer. * * ctx EVP_PKEY context of operation. * out Encrypted output buffer. If NULL, puts the maximum output buffer size * in outlen and returns success. * outLen If out is NULL, see above. If out is non-NULL, on input outLen holds * the size of out. On output holds the length of actual encryption. * in Plaintext input buffer. * inLen Length of plaintext. * * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure. */ 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; WOLFSSL_ENTER("EVP_PKEY_encrypt"); if (ctx == NULL || ctx->pkey == NULL) { WOLFSSL_MSG("Bad parameter."); return 0; } if (ctx->op != EVP_PKEY_OP_ENCRYPT) { WOLFSSL_MSG("ctx->op must be set to EVP_PKEY_OP_ENCRYPT. Use " "wolfSSL_EVP_PKEY_encrypt_init."); 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: if (out == NULL) { if (ctx->pkey->rsa == NULL) { WOLFSSL_MSG("Internal wolfCrypt RSA object is NULL."); return WOLFSSL_FAILURE; } len = wolfSSL_RSA_size(ctx->pkey->rsa); if (len <= 0) { WOLFSSL_MSG("Error getting RSA size."); return WOLFSSL_FAILURE; } if (outLen == NULL) { WOLFSSL_MSG("outLen is NULL."); return WOLFSSL_FAILURE; } *outLen = len; return WOLFSSL_SUCCESS; } 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("EVP_PKEY_EC 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 */ 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) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: ctx->op = EVP_PKEY_OP_SIGN; ret = WOLFSSL_SUCCESS; break; #endif /* NO_RSA */ #ifndef NO_DSA case EVP_PKEY_DSA: ctx->op = EVP_PKEY_OP_SIGN; ret = WOLFSSL_SUCCESS; break; #endif /* NO_DSA */ #ifdef HAVE_ECC case EVP_PKEY_EC: ctx->op = EVP_PKEY_OP_SIGN; ret = WOLFSSL_SUCCESS; break; #endif /* HAVE_ECC */ 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 */ int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign"); if (!ctx || ctx->op != EVP_PKEY_OP_SIGN || !ctx->pkey || !siglen) return WOLFSSL_FAILURE; (void)sig; (void)siglen; (void)tbs; (void)tbslen; switch (ctx->pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { int len; unsigned int usiglen = (unsigned int)*siglen; if (!sig) { if (!ctx->pkey->rsa) return WOLFSSL_FAILURE; len = wc_RsaEncryptSize((RsaKey*)ctx->pkey->rsa->internal); if (len < 0) return WOLFSSL_FAILURE; *siglen = (size_t)len; return WOLFSSL_SUCCESS; } /* wolfSSL_RSA_sign_generic_padding performs a check that the output * sig buffer is large enough */ if (wolfSSL_RSA_sign_generic_padding(wolfSSL_EVP_MD_type(ctx->md), tbs, (unsigned int)tbslen, sig, &usiglen, ctx->pkey->rsa, 1, ctx->padding) != WOLFSSL_SUCCESS) { return WOLFSSL_FAILURE; } *siglen = (size_t)usiglen; return WOLFSSL_SUCCESS; } #endif /* NO_RSA */ #ifndef NO_DSA case EVP_PKEY_DSA: { int bytes; int ret; if (!ctx->pkey->dsa) return WOLFSSL_FAILURE; bytes = wolfSSL_BN_num_bytes(ctx->pkey->dsa->q); if (bytes == WOLFSSL_FAILURE) return WOLFSSL_FAILURE; bytes *= 2; if (!sig) { *siglen = bytes; return WOLFSSL_SUCCESS; } if ((int)*siglen < bytes) return WOLFSSL_FAILURE; ret = wolfSSL_DSA_do_sign(tbs, sig, ctx->pkey->dsa); /* wolfSSL_DSA_do_sign() can return WOLFSSL_FATAL_ERROR */ if (ret != WOLFSSL_SUCCESS) return ret; if (bytes == WOLFSSL_FAILURE) return WOLFSSL_FAILURE; *siglen = bytes; return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ #ifdef HAVE_ECC case EVP_PKEY_EC: { int ret; WOLFSSL_ECDSA_SIG *ecdsaSig; if (!sig) { WOLFSSL_EC_KEY *key = ctx->pkey->ecc; ecc_key* eckey; if (!key) return WOLFSSL_FAILURE; /* set internal key if not done */ if (key->inSet == 0 && SetECKeyInternal(key) != WOLFSSL_SUCCESS) return WOLFSSL_FAILURE; eckey = (ecc_key*)ctx->pkey->ecc->internal; if (!eckey) return WOLFSSL_FAILURE; ret = wc_ecc_sig_size(eckey); if (ret == 0) return WOLFSSL_FAILURE; *siglen = ret; return WOLFSSL_SUCCESS; } ecdsaSig = wolfSSL_ECDSA_do_sign(tbs, (int)tbslen, ctx->pkey->ecc); if (ecdsaSig == NULL) return WOLFSSL_FAILURE; ret = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, NULL); if (ret == 0 || ret > (int)*siglen) { wolfSSL_ECDSA_SIG_free(ecdsaSig); return WOLFSSL_FAILURE; } ret = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); wolfSSL_ECDSA_SIG_free(ecdsaSig); if (ret == 0) return WOLFSSL_FAILURE; *siglen = ret; return WOLFSSL_SUCCESS; } #endif /* HAVE_ECC */ default: break; } return WOLFSSL_FAILURE; } /****************************************************************************** * wolfSSL_EVP_PKEY_verify_init - initializes a public key algorithm context for * a verification operation. * * RETURNS: * returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. In particular * a return value of -2 indicates the operation is not supported by the public * key algorithm. */ int wolfSSL_EVP_PKEY_verify_init(WOLFSSL_EVP_PKEY_CTX *ctx) { WOLFSSL_MSG("wolfSSL_EVP_PKEY_verify_init"); if (!ctx || !ctx->pkey) return WOLFSSL_FAILURE; switch (ctx->pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: ctx->op = EVP_PKEY_OP_VERIFY; return WOLFSSL_SUCCESS; #endif /* NO_RSA */ #ifndef NO_DSA case EVP_PKEY_DSA: ctx->op = EVP_PKEY_OP_VERIFY; return WOLFSSL_SUCCESS; #endif /* NO_DSA */ #ifdef HAVE_ECC case EVP_PKEY_EC: ctx->op = EVP_PKEY_OP_VERIFY; return WOLFSSL_SUCCESS; #endif /* HAVE_ECC */ default: return -2; } } /****************************************************************************** * wolfSSL_EVP_PKEY_verify - verifies a signature using ctx * * RETURNS: * returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. In particular * a return value of -2 indicates the operation is not supported by the public * key algorithm. */ int wolfSSL_EVP_PKEY_verify(WOLFSSL_EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { WOLFSSL_MSG("wolfSSL_EVP_PKEY_verify"); if (!ctx || ctx->op != EVP_PKEY_OP_VERIFY || !ctx->pkey) return WOLFSSL_FAILURE; switch (ctx->pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: return wolfSSL_RSA_verify_ex(WC_HASH_TYPE_NONE, tbs, (unsigned int)tbslen, sig, (unsigned int)siglen, ctx->pkey->rsa, ctx->padding); #endif /* NO_RSA */ #ifndef NO_DSA case EVP_PKEY_DSA: { int dsacheck = 0; if (wolfSSL_DSA_do_verify(tbs, (unsigned char *)sig, ctx->pkey->dsa, &dsacheck) != WOLFSSL_SUCCESS || dsacheck != 1) return WOLFSSL_FAILURE; return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ #ifdef HAVE_ECC case EVP_PKEY_EC: { int ret; WOLFSSL_ECDSA_SIG *ecdsaSig = wolfSSL_d2i_ECDSA_SIG( NULL, (const unsigned char **)&sig, (long)siglen); if (ecdsaSig == NULL) return WOLFSSL_FAILURE; ret = wolfSSL_ECDSA_do_verify(tbs, (int)tbslen, ecdsaSig, ctx->pkey->ecc); wolfSSL_ECDSA_SIG_free(ecdsaSig); return ret; } #endif /* HAVE_ECC */ default: return -2; } } /* 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_paramgen_init(WOLFSSL_EVP_PKEY_CTX *ctx) { (void)ctx; return WOLFSSL_SUCCESS; } int wolfSSL_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(WOLFSSL_EVP_PKEY_CTX *ctx, int nid) { WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set_ec_paramgen_curve_nid"); #ifdef HAVE_ECC if (ctx != NULL && ctx->pkey != NULL && ctx->pkey->type == EVP_PKEY_EC) { ctx->curveNID = nid; return WOLFSSL_SUCCESS; } else #endif { #ifndef HAVE_ECC (void)ctx; (void)nid; WOLFSSL_MSG("Support not compiled in"); #else WOLFSSL_MSG("Bad parameter"); #endif return WOLFSSL_FAILURE; } } int wolfSSL_EVP_PKEY_paramgen(WOLFSSL_EVP_PKEY_CTX* ctx, WOLFSSL_EVP_PKEY** pkey) { int ret = WOLFSSL_SUCCESS; int ownPkey = 0; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_paramgen"); if (ctx == NULL || pkey == NULL) { WOLFSSL_MSG("Bad parameter"); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && *pkey == NULL) { /* Only ECC is supported currently. */ if (ctx->pkey == NULL || ctx->pkey->type != EVP_PKEY_EC) { WOLFSSL_MSG("Key not set or key type not supported."); ret = WOLFSSL_FAILURE; } else { *pkey = wolfSSL_EVP_PKEY_new(); if (*pkey == NULL) { WOLFSSL_MSG("Failed to create WOLFSSL_EVP_PKEY."); ret = WOLFSSL_FAILURE; } else { (*pkey)->type = ctx->pkey->type; ownPkey = 1; } } } if (ret == WOLFSSL_SUCCESS) { switch ((*pkey)->type) { #ifdef HAVE_ECC /* For ECC parameter generation we just need to set the group, which * wolfSSL_EC_KEY_new_by_curve_name will do. */ case EVP_PKEY_EC: (*pkey)->ecc = wolfSSL_EC_KEY_new_by_curve_name(ctx->curveNID); if ((*pkey)->ecc == NULL) { WOLFSSL_MSG("Failed to create WOLFSSL_EC_KEY."); ret = WOLFSSL_FAILURE; } else { (*pkey)->ownEcc = 1; } break; #endif default: ret = WOLFSSL_FAILURE; break; } } if (ret != WOLFSSL_SUCCESS && ownPkey) { wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; } WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_paramgen", ret); return ret; } /* wolfSSL only supports writing out named curves so no need to store the flag. * In short, it is preferred to write out the name of the curve chosen instead * of the explicit parameters. * The difference is nicely explained and illustrated in section * "ECDH and Named Curves" of * https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman */ int wolfSSL_EVP_PKEY_CTX_set_ec_param_enc(WOLFSSL_EVP_PKEY_CTX *ctx, int flag) { (void)ctx; (void)flag; return WOLFSSL_SUCCESS; } 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; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_keygen"); if (ctx == NULL || ppkey == NULL) { return BAD_FUNC_ARG; } pkey = *ppkey; if (pkey == NULL) { if (ctx->pkey == NULL || (ctx->pkey->type != EVP_PKEY_EC && ctx->pkey->type != EVP_PKEY_RSA && ctx->pkey->type != EVP_PKEY_DH)) { WOLFSSL_MSG("Key not set or key type not supported"); return BAD_FUNC_ARG; } pkey = wolfSSL_EVP_PKEY_new(); if (pkey == NULL) { return MEMORY_E; } ownPkey = 1; pkey->type = ctx->pkey->type; } 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 may not be NULL, if, for example, it was populated by a * prior call to wolfSSL_EVP_PKEY_paramgen. */ if (pkey->ecc == NULL) { pkey->ecc = wolfSSL_EC_KEY_new_by_curve_name(ctx->curveNID); } if (pkey->ecc) { ret = wolfSSL_EC_KEY_generate_key(pkey->ecc); if (ret == WOLFSSL_SUCCESS) { pkey->ownEcc = 1; } } break; #endif #if !defined(NO_DH) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) case EVP_PKEY_DH: pkey->dh = wolfSSL_DH_new(); if (pkey->dh) { pkey->ownDh = 1; /* load DH params from CTX */ ret = wolfSSL_DH_LoadDer(pkey->dh, (const unsigned char*)ctx->pkey->pkey.ptr, ctx->pkey->pkey_sz); if (ret == WOLFSSL_SUCCESS) { ret = wolfSSL_DH_generate_key(pkey->dh); } if (ret == WOLFSSL_SUCCESS) { /* copy private/public key from external to internal */ ret = SetDhInternal(pkey->dh); } } break; #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 */ #ifndef NO_DSA case EVP_PKEY_DSA: if (pkey->dsa == NULL || (!pkey->dsa->exSet && SetDsaExternal(pkey->dsa) != WOLFSSL_SUCCESS)) return WOLFSSL_FAILURE; return wolfSSL_BN_num_bytes(pkey->dsa->p); #endif #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; } int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, const WOLFSSL_EVP_PKEY *from) { WOLFSSL_ENTER("wolfSSL_EVP_PKEY_copy_parameters"); if (!to || !from) { WOLFSSL_MSG("Bad parameter"); return WOLFSSL_FAILURE; } if (to->type == EVP_PKEY_NONE) { to->type = from->type; } else if (to->type != from->type) { WOLFSSL_MSG("Different key types"); return WOLFSSL_FAILURE; } switch(from->type) { #ifdef HAVE_ECC case EVP_PKEY_EC: if (from->ecc) { if (!to->ecc) { if ((to->ecc = wolfSSL_EC_KEY_new()) == NULL) { WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); return WOLFSSL_FAILURE; } to->ownEcc = 1; } to->ecc->group->curve_idx = from->ecc->group->curve_idx; to->ecc->group->curve_nid = from->ecc->group->curve_nid; to->ecc->group->curve_oid = from->ecc->group->curve_oid; } else { WOLFSSL_MSG("Missing ECC struct"); return WOLFSSL_FAILURE; } break; #endif #ifndef NO_DSA case EVP_PKEY_DSA: if (from->dsa) { WOLFSSL_BIGNUM* cpy; if (!to->dsa) { if ((to->dsa = wolfSSL_DSA_new()) == NULL) { WOLFSSL_MSG("wolfSSL_DSA_new error"); return WOLFSSL_FAILURE; } to->ownDsa = 1; } /* free existing BIGNUMs if needed before copying over new */ wolfSSL_BN_free(to->dsa->p); wolfSSL_BN_free(to->dsa->g); wolfSSL_BN_free(to->dsa->q); to->dsa->p = NULL; to->dsa->g = NULL; to->dsa->q = NULL; if (!(cpy = wolfSSL_BN_dup(from->dsa->p))) { WOLFSSL_MSG("wolfSSL_BN_dup error"); return WOLFSSL_FAILURE; } to->dsa->p = cpy; if (!(cpy = wolfSSL_BN_dup(from->dsa->q))) { WOLFSSL_MSG("wolfSSL_BN_dup error"); return WOLFSSL_FAILURE; } to->dsa->q = cpy; if (!(cpy = wolfSSL_BN_dup(from->dsa->g))) { WOLFSSL_MSG("wolfSSL_BN_dup error"); return WOLFSSL_FAILURE; } to->dsa->g = cpy; } else { WOLFSSL_MSG("Missing DSA struct"); return WOLFSSL_FAILURE; } break; #endif #ifndef NO_DH case EVP_PKEY_DH: if (from->dh) { WOLFSSL_BIGNUM* cpy; if (!to->dh) { if ((to->dh = wolfSSL_DH_new()) == NULL) { WOLFSSL_MSG("wolfSSL_DH_new error"); return WOLFSSL_FAILURE; } to->ownDh = 1; } /* free existing BIGNUMs if needed before copying over new */ wolfSSL_BN_free(to->dh->p); wolfSSL_BN_free(to->dh->g); wolfSSL_BN_free(to->dh->q); to->dh->p = NULL; to->dh->g = NULL; to->dh->q = NULL; if (!(cpy = wolfSSL_BN_dup(from->dh->p))) { WOLFSSL_MSG("wolfSSL_BN_dup error, DH p"); return WOLFSSL_FAILURE; } to->dh->p = cpy; if (!(cpy = wolfSSL_BN_dup(from->dh->g))) { WOLFSSL_MSG("wolfSSL_BN_dup error, DH g"); return WOLFSSL_FAILURE; } to->dh->g = cpy; if (!(cpy = wolfSSL_BN_dup(from->dh->q))) { WOLFSSL_MSG("wolfSSL_BN_dup error, DH q"); return WOLFSSL_FAILURE; } to->dh->q = cpy; } else { WOLFSSL_MSG("Missing DH struct"); return WOLFSSL_FAILURE; } break; #endif #ifndef NO_RSA case EVP_PKEY_RSA: #endif default: WOLFSSL_MSG("Copy parameters not available for this key type"); return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; } #ifndef NO_WOLFSSL_STUB 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_EVP_PKEY_cmp * returns 0 on success, -1 on failure. * * This behavior is different from openssl. * EVP_PKEY_cmp returns: * 1 : two keys match * 0 : do not match * -1: key types are different * -2: the operation is not supported * If you want this function behave the same as openSSL, * define WOLFSSL_ERROR_CODE_OPENSSL so that WS_RETURN_CODE translates return * codes to match OpenSSL equivalent behavior. */ 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 WS_RETURN_CODE(ret, WOLFSSL_FAILURE); /* check its the same type of key */ if (a->type != b->type) return WS_RETURN_CODE(ret, -1); /* 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: return WS_RETURN_CODE(ret, -2); } /* switch (a->type) */ /* check size */ if (a_sz <= 0 || b_sz <= 0 || a_sz != b_sz) { return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } /* check public key size */ if (a->pkey_sz > 0 && b->pkey_sz > 0 && a->pkey_sz != b->pkey_sz) { return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } /* check public key */ if (a->pkey.ptr && b->pkey.ptr) { if (XMEMCMP(a->pkey.ptr, b->pkey.ptr, a->pkey_sz) != 0) { return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } } #if defined(WOLFSSL_ERROR_CODE_OPENSSL) ret = 1; /* the keys match */ #else ret = 0; /* success */ #endif return ret; } /** * validate DH algorithm parameters * @param dh_key a pointer to WOLFSSL_EVP_PKEY_CTX structure * @return WOLFSSL_SUCCESS on success, otherwise failure */ static int DH_param_check(WOLFSSL_DH* dh_key) { int ret = WOLFSSL_SUCCESS; WOLFSSL_BN_CTX* ctx = NULL; WOLFSSL_BIGNUM *num1 = NULL; WOLFSSL_BIGNUM *num2 = NULL; WOLFSSL_ENTER("DH_param_check"); ctx = wolfSSL_BN_CTX_new(); if (ctx == NULL) { WOLFSSL_MSG("failed to allocate memory"); return WOLFSSL_FAILURE; } num1 = wolfSSL_BN_new(); num2 = wolfSSL_BN_new(); if (num1 == NULL || num2 == NULL) { WOLFSSL_MSG("failed to assign big number"); ret = WOLFSSL_FAILURE; } /* prime check */ if (ret == WOLFSSL_SUCCESS && wolfSSL_BN_is_odd(dh_key->p) == 0){ WOLFSSL_MSG("dh_key->p is not prime"); ret = WOLFSSL_FAILURE; } /* TODO safe prime check. need BN_rshift1 */ /* generator check */ if (ret == WOLFSSL_SUCCESS && (wolfSSL_BN_is_one(dh_key->g) || wolfSSL_BN_is_negative(dh_key->g) || wolfSSL_BN_is_zero(dh_key->g))) { WOLFSSL_MSG("dh_key->g is not suitable generator"); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && wolfSSL_BN_cmp(dh_key->p, dh_key->g) <= 0) { WOLFSSL_MSG("dh_key->g is not suitable generator"); ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS && dh_key->q != NULL) { if (ret == WOLFSSL_SUCCESS && wolfSSL_BN_mod_exp(num1, dh_key->g, dh_key->q, dh_key->p, ctx) == WOLFSSL_FAILURE) { WOLFSSL_MSG("BN_mod_exp failed"); ret = WOLFSSL_FAILURE; } else if (ret == WOLFSSL_SUCCESS && wolfSSL_BN_is_one(num1) == WOLFSSL_FAILURE) { WOLFSSL_MSG("dh_key->g is not suitable generator"); ret = WOLFSSL_FAILURE; } #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* test if the number q is prime. */ if (ret == WOLFSSL_SUCCESS && (wolfSSL_BN_is_prime_ex(dh_key->q, 64, ctx, NULL) <= 0)) { WOLFSSL_MSG("dh_key->q is not prime or error during check."); ret = WOLFSSL_FAILURE; } /* else TODO check q div q - 1. need BN_div */ #endif } /* clean up */ wolfSSL_BN_CTX_free(ctx); wolfSSL_BN_free(num1); wolfSSL_BN_free(num2); WOLFSSL_LEAVE("DH_param_check", WOLFSSL_SUCCESS); return ret; } /** * validate the algorithm parameters * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure * @return WOLFSSL_SUCCESS on success, otherwise failure */ int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) { int type; int ret; WOLFSSL_DH* dh_key = NULL; /* sanity check */ if (ctx == NULL) { return WOLFSSL_FAILURE; } type = wolfSSL_EVP_PKEY_type(wolfSSL_EVP_PKEY_base_id(ctx->pkey)); switch (type) { #if !defined(NO_RSA) case EVP_PKEY_RSA: WOLFSSL_MSG("EVP_PKEY_RSA not yet implemented"); return WOLFSSL_FAILURE; #endif #if defined(HAVE_ECC) case EVP_PKEY_EC: WOLFSSL_MSG("EVP_PKEY_EC not yet implemented"); return WOLFSSL_FAILURE; #endif #if !defined(NO_DSA) case EVP_PKEY_DSA: WOLFSSL_MSG("EVP_PKEY_DSA not yet implemented"); return WOLFSSL_FAILURE; #endif #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) case EVP_PKEY_DH: dh_key = wolfSSL_EVP_PKEY_get1_DH(ctx->pkey); if (dh_key != NULL) { ret = DH_param_check(dh_key); wolfSSL_DH_free(dh_key); } else ret = WOLFSSL_FAILURE; return ret; #endif #endif default: WOLFSSL_MSG("Unknown PKEY type"); break; } (void)ret; (void)DH_param_check; (void)dh_key; return WOLFSSL_FAILURE; } /* 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); } 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 enum wc_HashType 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, "SHA1"}, {WC_HASH_TYPE_SHA, NID_sha1, "SHA"}, /* Leave for backwards compatibility */ #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 */ #if defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_224) {WC_HASH_TYPE_SHA512_224, NID_sha512_224, "SHA512_224"}, #endif /* WOLFSSL_SHA512 && !WOLFSSL_NOSHA512_224 */ #if defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_256) {WC_HASH_TYPE_SHA512_256, NID_sha512_256, "SHA512_256"}, #endif /* WOLFSSL_SHA512 && !WOLFSSL_NOSHA512_256 */ #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 #ifndef WOLFSSL_NOSHA3_384 {WC_HASH_TYPE_SHA3_384, NID_sha3_384, "SHA3_384"}, #endif #ifndef WOLFSSL_NOSHA3_512 {WC_HASH_TYPE_SHA3_512, NID_sha3_512, "SHA3_512"}, #endif #ifdef HAVE_BLAKE2 {WC_HASH_TYPE_BLAKE2B, NID_blake2b512, "BLAKE2B512"}, #endif #ifdef HAVE_BLAKE2S {WC_HASH_TYPE_BLAKE2S, NID_blake2s256, "BLAKE2S256"}, #endif #ifdef WOLFSSL_SHAKE128 {WC_HASH_TYPE_SHAKE128, NID_shake128, "SHAKE128"}, #endif #ifdef WOLFSSL_SHAKE256 {WC_HASH_TYPE_SHAKE256, NID_shake256, "SHAKE256"}, #endif {WC_HASH_TYPE_NONE, 0, NULL} }; static enum wc_HashType EvpMd2MacType(const WOLFSSL_EVP_MD *md) { const struct s_ent *ent ; if (md != NULL) { for (ent = md_tbl; ent->name != NULL; ent++) { if (XSTRCMP((const char *)md, ent->name) == 0) { return ent->macType; } } } return WC_HASH_TYPE_NONE; } static const WOLFSSL_EVP_MD* wolfSSL_macType2EVP_md(enum wc_HashType type) { const struct s_ent *ent ; for (ent = md_tbl; ent->name != NULL; ent++) { if (ent->macType == type) { return ent->name; } } return NULL; } /* 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; (void)sigret; (void)siglen; WOLFSSL_ENTER("EVP_SignFinal"); if (ctx == NULL) return WOLFSSL_FAILURE; ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); if (ret <= 0) return ret; switch (pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { int nid; const WOLFSSL_EVP_MD *ctxmd; ctxmd = wolfSSL_EVP_MD_CTX_md(ctx); if (ctxmd == NULL) return WOLFSSL_FAILURE; nid = wolfSSL_EVP_MD_type(ctxmd); if (nid < 0) return WOLFSSL_FAILURE; return wolfSSL_RSA_sign(nid, md, mdsize, sigret, siglen, pkey->rsa); } #endif /* NO_RSA */ #ifndef NO_DSA case EVP_PKEY_DSA: { int bytes; ret = wolfSSL_DSA_do_sign(md, sigret, pkey->dsa); /* wolfSSL_DSA_do_sign() can return WOLFSSL_FATAL_ERROR */ if (ret != WOLFSSL_SUCCESS) return ret; bytes = wolfSSL_BN_num_bytes(pkey->dsa->q); if (bytes == WOLFSSL_FAILURE || (int)*siglen < bytes * 2) return WOLFSSL_FAILURE; *siglen = bytes * 2; return WOLFSSL_SUCCESS; } #endif 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, const 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; const WOLFSSL_EVP_MD *ctxmd = wolfSSL_EVP_MD_CTX_md(ctx); if (ctxmd == NULL) break; nid = wolfSSL_EVP_MD_type(ctxmd); 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, WOLFSSL_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 { if (keylen) { 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 (!type) { int default_digest; if (wolfSSL_EVP_PKEY_get_default_digest_nid(pkey, &default_digest) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Could not get default digest"); return WOLFSSL_FAILURE; } type = wolfSSL_EVP_get_digestbynid(default_digest); if (!type) { return BAD_FUNC_ARG; } } if (pkey->type == EVP_PKEY_HMAC) { int hashType; const unsigned char* key; #ifndef NO_SHA256 if (XSTRCMP(type, "SHA256") == 0) { hashType = WC_SHA256; } else #endif #ifndef NO_SHA if ((XSTRCMP(type, "SHA") == 0) || (XSTRCMP(type, "SHA1") == 0)) { hashType = WC_SHA; } else #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 if (XSTRCMP(type, "SHA224") == 0) { hashType = WC_SHA224; } else #endif #ifdef WOLFSSL_SHA384 if (XSTRCMP(type, "SHA384") == 0) { hashType = WC_SHA384; } else #endif #ifdef WOLFSSL_SHA512 if (XSTRCMP(type, "SHA512") == 0) { hashType = WC_SHA512; } else #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 if (XSTRCMP(type, "SHA3_224") == 0) { hashType = WC_SHA3_224; } else #endif #ifndef WOLFSSL_NOSHA3_256 if (XSTRCMP(type, "SHA3_256") == 0) { hashType = WC_SHA3_256; } else #endif #ifndef WOLFSSL_NOSHA3_384 if (XSTRCMP(type, "SHA3_384") == 0) { hashType = WC_SHA3_384; } else #endif #ifndef WOLFSSL_NOSHA3_512 if (XSTRCMP(type, "SHA3_512") == 0) { hashType = WC_SHA3_512; } else #endif #endif #ifndef NO_MD5 if (XSTRCMP(type, "MD5") == 0) { hashType = WC_MD5; } else #endif return BAD_FUNC_ARG; { size_t keySz = 0; 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->isHMAC = 1; } else if (wolfSSL_EVP_DigestInit(ctx, type) != 1) return WOLFSSL_FAILURE; if (ctx->pctx == NULL) { ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); if (ctx->pctx == NULL) return WOLFSSL_FAILURE; } if (pctx != NULL) *pctx = ctx->pctx; 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->isHMAC) { 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->isHMAC) { Hmac hmacCopy; 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 */ #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 case WC_SHA3_224: hashLen = WC_SHA3_224_DIGEST_SIZE; break; #endif #ifndef WOLFSSL_NOSHA3_256 case WC_SHA3_256: hashLen = WC_SHA3_256_DIGEST_SIZE; break; #endif #ifndef WOLFSSL_NOSHA3_384 case WC_SHA3_384: hashLen = WC_SHA3_384_DIGEST_SIZE; break; #endif #ifndef WOLFSSL_NOSHA3_512 case WC_SHA3_512: hashLen = WC_SHA3_512_DIGEST_SIZE; break; #endif #endif 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 || 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 signature when sig is NULL. */ if (ctx->isHMAC) { 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->isHMAC) { /* 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 = (unsigned int)*siglen; int nid; const WOLFSSL_EVP_MD *md = wolfSSL_EVP_MD_CTX_md(ctx); if (md == NULL) break; nid = wolfSSL_EVP_MD_type(md); if (nid < 0) break; ret = wolfSSL_RSA_sign_generic_padding(nid, digest, hashLen, sig, &sigSz, ctx->pctx->pkey->rsa, 1, ctx->pctx->padding); if (ret >= 0) *siglen = sigSz; break; } #endif /* NO_RSA */ #ifdef HAVE_ECC case EVP_PKEY_EC: { int len; WOLFSSL_ECDSA_SIG *ecdsaSig; ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen, ctx->pctx->pkey->ecc); if (ecdsaSig == NULL) break; len = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); wolfSSL_ECDSA_SIG_free(ecdsaSig); if (len == 0) break; *siglen = len; 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->isHMAC) { 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->isHMAC) { /* 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; const WOLFSSL_EVP_MD *md = wolfSSL_EVP_MD_CTX_md(ctx); if (md == NULL) return WOLFSSL_FAILURE; nid = wolfSSL_EVP_MD_type(md); if (nid < 0) return WOLFSSL_FAILURE; return wolfSSL_RSA_verify_ex(nid, digest, hashLen, sig, (unsigned int)siglen, ctx->pctx->pkey->rsa, ctx->pctx->padding); } #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 #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) 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, EvpMd2MacType(digest)); if (ret == 0) return WOLFSSL_SUCCESS; else return WOLFSSL_FAILURE; } #endif /* !NO_PWDBASED */ #if defined(HAVE_SCRYPT) && defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && \ !defined(NO_SHA256) /** * Derives a key from the specified password and the salt using SCRYPT * algorithm. * * Parameters: * - pass :password data. no need to be null-terminated. NULL is accepted. * - passlen :length of the password. Must be 0 when pass is NULL. * - salt :salt. NULL is accepted. * - saltlen :length of the salt. Must be 0 when salt is NULL. * - N :cost parameter. Must be grater or equal to 2 and be a power of 2. * - r :block size. Must 1 or greater. * - p :parallelism * - maxmem :maximum size of buffer used for calculation in definition, * Not referred in this implementation. * - key :derived key. * - keylen :length of the derived key * * Returns: * 1 on success, otherwise 0. */ int wolfSSL_EVP_PBE_scrypt(const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, word64 N, word64 r, word64 p, word64 maxmem, unsigned char *key, size_t keylen) { int ret; int exp = 0; (void)maxmem; WOLFSSL_ENTER("wolfSSL_EVP_PBE_scrypt"); if (r > INT32_MAX || p > INT32_MAX) { WOLFSSL_MSG("Doesn't support greater than 32 bit values of r and p"); return WOLFSSL_FAILURE; } /* N must be a power of 2 and > 2. if (N & (N-1)) is zero, it means N is a power of 2. */ if (N < 2 || (N & (N-1)) || r <= 0 || p <= 0) return WOLFSSL_FAILURE; if (key == NULL) return WOLFSSL_SUCCESS; /* get exponent of power of 2. Confirmed N is power of 2. */ while (N != 1) { N >>= 1; exp++; } ret = wc_scrypt(key, (const byte*)pass, (int)passlen, salt, (int)saltlen, exp, (int)r, (int)p, (int)keylen); WOLFSSL_LEAVE("wolfSSL_EVP_PBE_scrypt", ret); if (ret == 0) return WOLFSSL_SUCCESS; else return WOLFSSL_FAILURE; } #endif /* HAVE_SCRYPT && HAVE_PBKDF2 && !NO_PWDBASED && !NO_SHA */ static const struct cipher{ unsigned char type; const char *name; int nid; } cipher_tbl[] = { #ifndef NO_AES #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 {AES_128_CBC_TYPE, EVP_AES_128_CBC, NID_aes_128_cbc}, #endif #ifdef WOLFSSL_AES_192 {AES_192_CBC_TYPE, EVP_AES_192_CBC, NID_aes_192_cbc}, #endif #ifdef WOLFSSL_AES_256 {AES_256_CBC_TYPE, EVP_AES_256_CBC, NID_aes_256_cbc}, #endif #endif #ifdef WOLFSSL_AES_CFB #ifdef WOLFSSL_AES_128 {AES_128_CFB1_TYPE, EVP_AES_128_CFB1, NID_aes_128_cfb1}, #endif #ifdef WOLFSSL_AES_192 {AES_192_CFB1_TYPE, EVP_AES_192_CFB1, NID_aes_192_cfb1}, #endif #ifdef WOLFSSL_AES_256 {AES_256_CFB1_TYPE, EVP_AES_256_CFB1, NID_aes_256_cfb1}, #endif #ifdef WOLFSSL_AES_128 {AES_128_CFB8_TYPE, EVP_AES_128_CFB8, NID_aes_128_cfb8}, #endif #ifdef WOLFSSL_AES_192 {AES_192_CFB8_TYPE, EVP_AES_192_CFB8, NID_aes_192_cfb8}, #endif #ifdef WOLFSSL_AES_256 {AES_256_CFB8_TYPE, EVP_AES_256_CFB8, NID_aes_256_cfb8}, #endif #ifdef WOLFSSL_AES_128 {AES_128_CFB128_TYPE, EVP_AES_128_CFB128, NID_aes_128_cfb128}, #endif #ifdef WOLFSSL_AES_192 {AES_192_CFB128_TYPE, EVP_AES_192_CFB128, NID_aes_192_cfb128}, #endif #ifdef WOLFSSL_AES_256 {AES_256_CFB128_TYPE, EVP_AES_256_CFB128, NID_aes_256_cfb128}, #endif #endif #ifdef HAVE_AES_OFB #ifdef WOLFSSL_AES_128 {AES_128_OFB_TYPE, EVP_AES_128_OFB, NID_aes_128_ofb}, #endif #ifdef WOLFSSL_AES_192 {AES_192_OFB_TYPE, EVP_AES_192_OFB, NID_aes_192_ofb}, #endif #ifdef WOLFSSL_AES_256 {AES_256_OFB_TYPE, EVP_AES_256_OFB, NID_aes_256_ofb}, #endif #endif #ifdef HAVE_AES_XTS #ifdef WOLFSSL_AES_128 {AES_128_XTS_TYPE, EVP_AES_128_XTS, NID_aes_128_xts}, #endif #ifdef WOLFSSL_AES_256 {AES_256_XTS_TYPE, EVP_AES_256_XTS, NID_aes_256_xts}, #endif #endif #ifdef HAVE_AESGCM #ifdef WOLFSSL_AES_128 {AES_128_GCM_TYPE, EVP_AES_128_GCM, NID_aes_128_gcm}, #endif #ifdef WOLFSSL_AES_192 {AES_192_GCM_TYPE, EVP_AES_192_GCM, NID_aes_192_gcm}, #endif #ifdef WOLFSSL_AES_256 {AES_256_GCM_TYPE, EVP_AES_256_GCM, NID_aes_256_gcm}, #endif #endif #ifdef WOLFSSL_AES_COUNTER #ifdef WOLFSSL_AES_128 {AES_128_CTR_TYPE, EVP_AES_128_CTR, NID_aes_128_ctr}, #endif #ifdef WOLFSSL_AES_192 {AES_192_CTR_TYPE, EVP_AES_192_CTR, NID_aes_192_ctr}, #endif #ifdef WOLFSSL_AES_256 {AES_256_CTR_TYPE, EVP_AES_256_CTR, NID_aes_256_ctr}, #endif #endif #ifdef HAVE_AES_ECB #ifdef WOLFSSL_AES_128 {AES_128_ECB_TYPE, EVP_AES_128_ECB, NID_aes_128_ecb}, #endif #ifdef WOLFSSL_AES_192 {AES_192_ECB_TYPE, EVP_AES_192_ECB, NID_aes_192_ecb}, #endif #ifdef WOLFSSL_AES_256 {AES_256_ECB_TYPE, EVP_AES_256_ECB, NID_aes_256_ecb}, #endif #endif #endif #ifndef NO_DES3 {DES_CBC_TYPE, EVP_DES_CBC, NID_des_cbc}, {DES_ECB_TYPE, EVP_DES_ECB, NID_des_ecb}, {DES_EDE3_CBC_TYPE, EVP_DES_EDE3_CBC, NID_des_ede3_cbc}, {DES_EDE3_ECB_TYPE, EVP_DES_EDE3_ECB, NID_des_ede3_ecb}, #endif #ifndef NO_RC4 {ARC4_TYPE, EVP_ARC4, NID_undef}, #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) {CHACHA20_POLY1305_TYPE, EVP_CHACHA20_POLY1305, NID_chacha20_poly1305}, #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 (XSTRCMP(cipher, c->name) == 0) { return c->nid; } } return 0; } const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) { const struct alias { const char *name; const char *alias; } cipher_alias_tbl[] = { #ifndef NO_DES3 {EVP_DES_CBC, "des"}, {EVP_DES_ECB, "des-ecb"}, {EVP_DES_EDE3_CBC, "des3"}, {EVP_DES_EDE3_CBC, "3des"}, {EVP_DES_EDE3_ECB, "des-ede3"}, {EVP_DES_EDE3_ECB, "des-ede3-ecb"}, #endif #ifndef NO_AES #ifdef HAVE_AES_CBC #ifdef WOLFSSL_AES_128 {EVP_AES_128_CBC, "aes128-cbc"}, {EVP_AES_128_CBC, "aes128"}, #endif #ifdef WOLFSSL_AES_192 {EVP_AES_192_CBC, "aes192-cbc"}, {EVP_AES_192_CBC, "aes192"}, #endif #ifdef WOLFSSL_AES_256 {EVP_AES_256_CBC, "aes256-cbc"}, {EVP_AES_256_CBC, "aes256"}, #endif #endif #ifdef HAVE_AES_ECB #ifdef WOLFSSL_AES_128 {EVP_AES_128_ECB, "aes128-ecb"}, #endif #ifdef WOLFSSL_AES_192 {EVP_AES_192_ECB, "aes192-ecb"}, #endif #ifdef WOLFSSL_AES_256 {EVP_AES_256_ECB, "aes256-ecb"}, #endif #endif #ifdef HAVE_AESGCM #ifdef WOLFSSL_AES_128 {EVP_AES_128_GCM, "aes-128-gcm"}, {EVP_AES_128_GCM, "id-aes128-GCM"}, #endif #ifdef WOLFSSL_AES_192 {EVP_AES_192_GCM, "aes-192-gcm"}, {EVP_AES_192_GCM, "id-aes192-GCM"}, #endif #ifdef WOLFSSL_AES_256 {EVP_AES_256_GCM, "aes-256-gcm"}, {EVP_AES_256_GCM, "id-aes256-GCM"}, #endif #endif #endif #ifndef NO_RC4 {EVP_ARC4, "RC4"}, #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) {EVP_CHACHA20_POLY1305, "chacha20-poly1305"}, #endif { NULL, NULL} }; const struct cipher *ent; const struct alias *al; WOLFSSL_ENTER("EVP_get_cipherbyname"); for (al = cipher_alias_tbl; al->name != NULL; al++) { /* Accept any case alternative version of an alias. */ if (XSTRCASECMP(name, al->alias) == 0) { name = al->name; break; } } for (ent = cipher_tbl; ent->name != NULL; ent++) { /* Accept any case alternative version of name. */ if (XSTRCASECMP(name, ent->name) == 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 #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #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*/ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case NID_chacha20_poly1305: return wolfSSL_EVP_chacha20_poly1305(); #endif default: WOLFSSL_MSG("Bad cipher id value"); } return NULL; } void wolfSSL_EVP_init(void) { /* Does nothing. */ } /* 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; } static const struct alias { const char *name; const char *alias; } digest_alias_tbl[] = { {"MD4", "ssl3-md4"}, {"MD5", "ssl3-md5"}, {"SHA1", "ssl3-sha1"}, {"SHA1", "SHA"}, { NULL, NULL} }; const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) { char nameUpper[15]; /* 15 bytes should be enough for any name */ size_t i; const struct alias *al; const struct s_ent *ent; for (i = 0; i < sizeof(nameUpper) && name[i] != '\0'; i++) { nameUpper[i] = (char)XTOUPPER((unsigned char) name[i]); } if (i < sizeof(nameUpper)) nameUpper[i] = '\0'; else return NULL; name = nameUpper; for (al = digest_alias_tbl; al->name != NULL; al++) if(XSTRCMP(name, al->alias) == 0) { name = al->name; break; } for (ent = md_tbl; ent->name != NULL; ent++) if(XSTRCMP(name, ent->name) == 0) { return (EVP_MD *)ent->name; } return NULL; } /* Returns the NID of the WOLFSSL_EVP_MD passed in. * * type - pointer to WOLFSSL_EVP_MD for which to return NID value * * Returns NID on success, or NID_undef if none exists. */ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) { const struct s_ent *ent ; WOLFSSL_ENTER("EVP_MD_type"); if (type == NULL) { WOLFSSL_MSG("MD type arg is NULL"); return NID_undef; } for( ent = md_tbl; ent->name != NULL; ent++){ if(XSTRCMP((const char *)type, ent->name) == 0) { return ent->nid; } } return NID_undef; } #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 */ #ifdef HAVE_BLAKE2 /* return EVP_MD * @param none * @return "blake2b512" */ const WOLFSSL_EVP_MD* wolfSSL_EVP_blake2b512(void) { WOLFSSL_ENTER("EVP_blake2b512"); return EVP_get_digestbyname("BLAKE2b512"); } #endif #ifdef HAVE_BLAKE2S /* return EVP_MD * @param none * @return "blake2s256" */ const WOLFSSL_EVP_MD* wolfSSL_EVP_blake2s256(void) { WOLFSSL_ENTER("EVP_blake2s256"); return EVP_get_digestbyname("BLAKE2s256"); } #endif #ifndef NO_WOLFSSL_STUB void wolfSSL_EVP_set_pw_prompt(const char *prompt) { (void)prompt; WOLFSSL_STUB("EVP_set_pw_prompt"); } #endif #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("SHA1"); } #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"); } #ifndef WOLFSSL_NOSHA512_224 const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512_224(void) { WOLFSSL_ENTER("EVP_sha512_224"); return EVP_get_digestbyname("SHA512_224"); } #endif /* !WOLFSSL_NOSHA512_224 */ #ifndef WOLFSSL_NOSHA512_224 const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512_256(void) { WOLFSSL_ENTER("EVP_sha512_256"); return EVP_get_digestbyname("SHA512_256"); } #endif /* !WOLFSSL_NOSHA512_224 */ #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 */ #ifndef WOLFSSL_NOSHA3_384 const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void) { WOLFSSL_ENTER("EVP_sha3_384"); return EVP_get_digestbyname("SHA3_384"); } #endif /* WOLFSSL_NOSHA3_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 */ #ifdef WOLFSSL_SHAKE128 const WOLFSSL_EVP_MD* wolfSSL_EVP_shake128(void) { WOLFSSL_ENTER("EVP_shake128"); return EVP_get_digestbyname("SHAKE128"); } #endif /* WOLFSSL_SHAKE128 */ #ifdef WOLFSSL_SHAKE256 const WOLFSSL_EVP_MD* wolfSSL_EVP_shake256(void) { WOLFSSL_ENTER("EVP_shake256"); return EVP_get_digestbyname("SHAKE256"); } #endif /* WOLFSSL_SHAKE256 */ #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; } 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) { if (ctx->isHMAC) { return NID_hmac; } 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) { int ret; if (src->isHMAC) { return wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); } else { switch (src->macType) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 ret = wc_Md5Copy((wc_Md5*)&src->hash.digest, (wc_Md5*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* !NO_MD5 */ break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaCopy((wc_Sha*)&src->hash.digest, (wc_Sha*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* !NO_SHA */ break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Copy((wc_Sha224*)&src->hash.digest, (wc_Sha224*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* WOLFSSL_SHA224 */ break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Copy((wc_Sha256*)&src->hash.digest, (wc_Sha256*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* !NO_SHA256 */ break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Copy((wc_Sha384*)&src->hash.digest, (wc_Sha384*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* WOLFSSL_SHA384 */ break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Copy((wc_Sha512*)&src->hash.digest, (wc_Sha512*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif /* WOLFSSL_SHA512 */ break; #ifndef WOLFSSL_NOSHA512_224 case WC_HASH_TYPE_SHA512_224: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wc_Sha512_224Copy((wc_Sha512*)&src->hash.digest, (wc_Sha512*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; #endif /* !WOLFSSL_NOSHA512_224 */ #ifndef WOLFSSL_NOSHA512_256 case WC_HASH_TYPE_SHA512_256: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wc_Sha512_256Copy((wc_Sha512*)&src->hash.digest, (wc_Sha512*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; #endif /* !WOLFSSL_NOSHA512_256 */ case WC_HASH_TYPE_SHA3_224: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) ret = wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest, (wc_Sha3*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; case WC_HASH_TYPE_SHA3_256: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) ret = wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest, (wc_Sha3*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; case WC_HASH_TYPE_SHA3_384: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) ret = wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest, (wc_Sha3*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; case WC_HASH_TYPE_SHA3_512: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) ret = wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest, (wc_Sha3*)&des->hash.digest); #else ret = NOT_COMPILED_IN; #endif break; case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_BLAKE2B: case WC_HASH_TYPE_BLAKE2S: #ifndef WOLFSSL_NO_SHAKE256 case WC_HASH_TYPE_SHAKE128: case WC_HASH_TYPE_SHAKE256: #endif default: ret = BAD_FUNC_ARG; break; } return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } } /* 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"); if (ctx->isHMAC) { return "HMAC"; } 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; } /* return alias name if has * @param n message digest type name * @return alias name, otherwise NULL */ static const char* hasAliasName(const char* n) { const char* aliasnm = NULL; const struct alias *al; for (al = digest_alias_tbl; al->name != NULL; al++) if(XSTRCMP(n, al->name) == 0) { aliasnm = al->alias; break; } return aliasnm; } struct do_all_md { void *arg; void (*fn) (const WOLFSSL_EVP_MD *m, const char* from, const char* to, void *arg); }; /* do all md algorithm * @param nm a pointer to WOLFSSL_OBJ_NAME * @param arg arguments to pass to the callback * @return none */ static void md_do_all_func(const WOLFSSL_OBJ_NAME* nm, void* arg) { struct do_all_md *md = (struct do_all_md*)arg; const struct s_ent *ent; /* sanity check */ if (md == NULL || nm == NULL || md->fn == NULL || nm->type != WOLFSSL_OBJ_NAME_TYPE_MD_METH) return; /* loop all md */ for (ent = md_tbl; ent->name != NULL; ent++){ /* check if the md has alias */ if(hasAliasName(ent->name) != NULL) { md->fn(NULL, ent->name, ent->name, md->arg); } else { md->fn(ent->name, ent->name, NULL, md->arg); } } } /* call md_do_all function to do all md algorithm via a callback function * @param fn a callback function to be called with all 'md' * @param args arguments to pass to the callback * @return none */ void wolfSSL_EVP_MD_do_all(void (*fn) (const WOLFSSL_EVP_MD *m, const char* from, const char* to, void* xx), void* args) { struct do_all_md md; md.fn = fn; md.arg = args; wolfSSL_OBJ_NAME_do_all(WOLFSSL_OBJ_NAME_TYPE_MD_METH, md_do_all_func, &md); } /* call "fn" based on OBJ_NAME type * @param type OBJ_NAME type * @param fn a callback function * @param args arguments to pass to the callback * @return none */ void wolfSSL_OBJ_NAME_do_all(int type, void (*fn)(const WOLFSSL_OBJ_NAME*, void* arg), void* arg) { WOLFSSL_OBJ_NAME objnm; /* sanity check */ if (!fn) return; objnm.type = type; switch(type) { case WOLFSSL_OBJ_NAME_TYPE_MD_METH: fn(&objnm, arg); break; case WOLFSSL_OBJ_NAME_TYPE_CIPHER_METH: case WOLFSSL_OBJ_NAME_TYPE_PKEY_METH: case WOLFSSL_OBJ_NAME_TYPE_COMP_METH: case WOLFSSL_OBJ_NAME_TYPE_NUM: WOLFSSL_MSG("not implemented"); FALL_THROUGH; case WOLFSSL_OBJ_NAME_TYPE_UNDEF: default: break; } } #ifndef NO_AES #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); return EVP_AES_256_GCM; } #endif /* WOLFSSL_AES_256 */ #endif /* HAVE_AESGCM */ #ifdef WOLFSSL_AES_COUNTER #ifdef WOLFSSL_AES_128 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); 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"); 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"); return EVP_AES_256_CTR; } #endif /* WOLFSSL_AES_256 */ #endif /* WOLFSSL_AES_COUNTER */ #ifdef HAVE_AES_ECB #ifdef WOLFSSL_AES_128 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); 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"); 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"); return EVP_AES_256_ECB; } #endif /* WOLFSSL_AES_256 */ #endif /* HAVE_AES_ECB */ #endif /* NO_AES */ #ifndef NO_DES3 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); return EVP_DES_CBC; } #ifdef WOLFSSL_DES_ECB const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); return EVP_DES_ECB; } #endif const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); 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"); return EVP_DES_EDE3_ECB; } #endif #endif /* NO_DES3 */ #ifndef NO_RC4 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) { WOLFSSL_ENTER("wolfSSL_EVP_rc4"); return EVP_ARC4; } #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20_poly1305(void) { WOLFSSL_ENTER("wolfSSL_EVP_chacha20_poly1305"); return EVP_CHACHA20_POLY1305; } #endif const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void) { WOLFSSL_ENTER("wolfSSL_EVP_enc_null"); return EVP_NULL; } int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) { int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); if (ctx->pctx != NULL) wolfSSL_EVP_PKEY_CTX_free(ctx->pctx); if (ctx->isHMAC) { wc_HmacFree(&ctx->hash.hmac); } else { switch (ctx->macType) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Free((wc_Md5*)&ctx->hash.digest); #endif /* !NO_MD5 */ break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA wc_ShaFree((wc_Sha*)&ctx->hash.digest); #endif /* !NO_SHA */ break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 wc_Sha224Free((wc_Sha224*)&ctx->hash.digest); #endif /* WOLFSSL_SHA224 */ break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 wc_Sha256Free((wc_Sha256*)&ctx->hash.digest); #endif /* !NO_SHA256 */ break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 wc_Sha384Free((wc_Sha384*)&ctx->hash.digest); #endif /* WOLFSSL_SHA384 */ break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 wc_Sha512Free((wc_Sha512*)&ctx->hash.digest); #endif /* WOLFSSL_SHA512 */ break; #ifndef WOLFSSL_NOSHA512_224 case WC_HASH_TYPE_SHA512_224: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) wc_Sha512_224Free((wc_Sha512*)&ctx->hash.digest); #endif break; #endif /* !WOLFSSL_NOSHA512_224 */ #ifndef WOLFSSL_NOSHA512_256 case WC_HASH_TYPE_SHA512_256: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) wc_Sha512_256Free((wc_Sha512*)&ctx->hash.digest); #endif break; #endif /* !WOLFSSL_NOSHA512_256 */ case WC_HASH_TYPE_SHA3_224: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) wc_Sha3_224_Free((wc_Sha3*)&ctx->hash.digest); #endif break; case WC_HASH_TYPE_SHA3_256: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest); #endif break; case WC_HASH_TYPE_SHA3_384: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest); #endif break; case WC_HASH_TYPE_SHA3_512: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) wc_Sha3_512_Free((wc_Sha3*)&ctx->hash.digest); #endif break; case WC_HASH_TYPE_NONE: /* Not an error since an unused struct could be free'd or * reset. */ break; case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_BLAKE2B: case WC_HASH_TYPE_BLAKE2S: #ifndef WOLFSSL_NO_SHAKE256 case WC_HASH_TYPE_SHAKE128: case WC_HASH_TYPE_SHAKE256: #endif default: ret = WOLFSSL_FAILURE; break; } } ForceZero(ctx, sizeof(*ctx)); ctx->macType = WC_HASH_TYPE_NONE; return ret; } 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 */ } } /* 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; #ifndef 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_CHACHA) && defined(HAVE_POLY1305)) case EVP_CTRL_AEAD_SET_IVLEN: if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0) break; #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (ctx->cipherType == CHACHA20_POLY1305_TYPE) { if (arg != CHACHA20_POLY1305_AEAD_IV_SIZE) { break; } } else #endif /* HAVE_CHACHA && HAVE_POLY1305 */ { if (arg <= 0 || arg > AES_BLOCK_SIZE) break; } ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg); break; case EVP_CTRL_AEAD_SET_IV_FIXED: if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0) break; if (arg == -1) { /* arg == -1 copies ctx->ivSz from ptr */ ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, (byte*)ptr, ctx->ivSz); } #ifndef WC_NO_RNG 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"); break; } /* arg is 4...(ctx->ivSz - 8) */ XMEMCPY(ctx->iv, ptr, arg); if (wc_InitRng(&rng) != 0) { WOLFSSL_MSG("wc_InitRng failed"); break; } if (wc_RNG_GenerateBlock(&rng, ctx->iv + arg, ctx->ivSz - arg) == 0) { ret = WOLFSSL_SUCCESS; } else { /* rng is freed immediately after if block so no need * to do it here */ WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); } if (wc_FreeRng(&rng) != 0) { WOLFSSL_MSG("wc_FreeRng failed"); ret = WOLFSSL_FAILURE; break; } } #ifdef HAVE_AESGCM if (ret == WOLFSSL_SUCCESS) { /* * OpenSSL requires that a EVP_CTRL_AEAD_SET_IV_FIXED * command be issued before a EVP_CTRL_GCM_IV_GEN command. * This flag is used to enforce that. */ ctx->gcmIvGenEnable = 1; } #endif #endif /* !WC_NO_RNG */ break; #if defined(HAVE_AESGCM) && !defined(_WIN32) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(2,0)) /* * Using EVP_CTRL_GCM_IV_GEN is a way to do AES-GCM encrypt/decrypt * multiple times with EVP_Cipher without having to call * EVP_CipherInit between each iteration. The IV is incremented for * each subsequent EVP_Cipher call to prevent IV reuse. */ case EVP_CTRL_GCM_IV_GEN: if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0) break; if (!ctx->gcmIvGenEnable) { WOLFSSL_MSG("Must use EVP_CTRL_AEAD_SET_IV_FIXED before " "EVP_CTRL_GCM_IV_GEN"); break; } if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) { WOLFSSL_MSG("Key or IV not set"); break; } if (ptr == NULL) { WOLFSSL_MSG("Destination buffer for IV bytes NULL."); break; } if (arg <= 0 || arg > ctx->ivSz) { XMEMCPY(ptr, ctx->iv, ctx->ivSz); } else { /* * Copy the last "arg" bytes of ctx->iv into the buffer at * "ptr." Not sure why OpenSSL does this, but it does. */ XMEMCPY(ptr, ctx->iv + ctx->ivSz - arg, arg); } /* * The gcmIncIV flag indicates that the IV should be incremented * after the next cipher operation. */ ctx->gcmIncIv = 1; ret = WOLFSSL_SUCCESS; break; #endif /* HAVE_AESGCM && !_WIN32 && !HAVE_SELFTEST && (!HAVE_FIPS || * FIPS_VERSION >= 2)*/ case EVP_CTRL_AEAD_SET_TAG: if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0) break; #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (ctx->cipherType == CHACHA20_POLY1305_TYPE) { if (arg != CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) { break; } ctx->authTagSz = arg; ret = WOLFSSL_SUCCESS; if (ptr != NULL) { XMEMCPY(ctx->authTag, ptr, arg); } break; } else #endif /* HAVE_CHACHA && HAVE_POLY1305 */ { if(arg <= 0 || arg > 16 || (ptr == NULL)) break; XMEMCPY(ctx->authTag, ptr, arg); ctx->authTagSz = arg; ret = WOLFSSL_SUCCESS; break; } case EVP_CTRL_AEAD_GET_TAG: if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0) break; #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (ctx->cipherType == CHACHA20_POLY1305_TYPE) { if (arg != CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) { break; } } else #endif /* HAVE_CHACHA && HAVE_POLY1305 */ { if (arg <= 0 || arg > AES_BLOCK_SIZE) break; } if (ptr != NULL) { XMEMCPY(ptr, ctx->authTag, arg); ret = WOLFSSL_SUCCESS; } break; #endif /* HAVE_AESGCM || (HAVE_CHACHA && HAVE_POLY1305) */ default: WOLFSSL_MSG("EVP_CIPHER_CTX_ctrl operation not yet handled"); break; } 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) { #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) #if defined(HAVE_AESGCM) && defined(WOLFSSL_AESGCM_STREAM) if ((ctx->cipherType == AES_128_GCM_TYPE) || (ctx->cipherType == AES_192_GCM_TYPE) || (ctx->cipherType == AES_256_GCM_TYPE)) { wc_AesFree(&ctx->cipher.aes); } #endif /* HAVE_AESGCM && WOLFSSL_AESGCM_STREAM */ #endif /* not FIPS or FIPS v2+ */ ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ ctx->keyLen = 0; #ifdef HAVE_AESGCM if (ctx->gcmBuffer) { XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL); ctx->gcmBuffer = NULL; } ctx->gcmBufferLen = 0; if (ctx->gcmAuthIn) { XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL); ctx->gcmAuthIn = NULL; } ctx->gcmAuthInSz = 0; ctx->gcmIvGenEnable = 0; ctx->gcmIncIv = 0; #endif } 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 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ defined(WOLFSSL_AES_256) #define AES_SIZE_ANY #endif #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \ defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_DIRECT) #define AES_SET_KEY #endif #if defined(AES_SIZE_ANY) && defined(AES_SET_KEY) 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 /* AES_ANY_SIZE && AES_SET_KEY */ #endif /* NO_AES */ #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) static int EvpCipherInitAesGCM(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, const byte* key, const byte* iv, int enc) { int ret = WOLFSSL_SUCCESS; if (ctx->gcmAuthIn) { XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL); ctx->gcmAuthIn = NULL; } ctx->gcmAuthInSz = 0; ctx->block_size = AES_BLOCK_SIZE; ctx->authTagSz = AES_BLOCK_SIZE; if (ctx->ivSz == 0) { ctx->ivSz = GCM_NONCE_MID_SZ; } ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE | WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER; if (enc == 0 || enc == 1) { ctx->enc = enc ? 1 : 0; } #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM))) { WOLFSSL_MSG("EVP_AES_128_GCM"); ctx->cipherType = AES_128_GCM_TYPE; ctx->keyLen = AES_128_KEY_SIZE; } #endif #ifdef WOLFSSL_AES_192 if (ctx->cipherType == AES_192_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_GCM))) { WOLFSSL_MSG("EVP_AES_192_GCM"); ctx->cipherType = AES_192_GCM_TYPE; ctx->keyLen = AES_192_KEY_SIZE; } #endif #ifdef WOLFSSL_AES_256 if (ctx->cipherType == AES_256_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_GCM))) { WOLFSSL_MSG("EVP_AES_256_GCM"); ctx->cipherType = AES_256_GCM_TYPE; ctx->keyLen = AES_256_KEY_SIZE; } #endif #ifndef WOLFSSL_AESGCM_STREAM if (ret == WOLFSSL_SUCCESS && key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { WOLFSSL_MSG("wc_AesGcmSetKey() failed"); ret = WOLFSSL_FAILURE; } #endif /* !WOLFSSL_AESGCM_STREAM */ if (ret == WOLFSSL_SUCCESS && iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, ctx->ivSz)) { WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); ret = WOLFSSL_FAILURE; } #ifdef WOLFSSL_AESGCM_STREAM /* * Initialize with key and IV if available. wc_AesGcmInit will fail * if called with IV only and no key has been set. */ if (ret == WOLFSSL_SUCCESS && (key || (iv && ctx->cipher.aes.gcmKeySet)) && wc_AesGcmInit(&ctx->cipher.aes, key, (key == NULL) ? 0 : ctx->keyLen, iv, (iv == NULL) ? 0 : ctx->ivSz) != 0) { WOLFSSL_MSG("wc_AesGcmInit() failed"); ret = WOLFSSL_FAILURE; } #endif /* WOLFSSL_AESGCM_STREAM */ /* * OpenSSL clears this flag, which permits subsequent use of * EVP_CTRL_GCM_IV_GEN, when EVP_CipherInit is called with no key. * If a key is provided, the flag retains its value. */ if (ret == WOLFSSL_SUCCESS && key == NULL) { ctx->gcmIvGenEnable = 0; } return ret; } static int EvpCipherAesGCM(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, word32 len) { int ret = WOLFSSL_FAILURE; #ifndef WOLFSSL_AESGCM_STREAM /* No destination means only AAD. */ if (src != NULL && dst == NULL) { ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len); } else if (src != NULL && dst != NULL) { if (ctx->enc) { ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src, len, ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); } else { ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src, len, ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); } if (ctx->gcmIncIv) { IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz); ctx->gcmIncIv = 0; } } #else /* * No need to call wc_AesGcmInit. Should have been called by * wolfSSL_EVP_CipherInit. */ /* NULL dst and non-NULL src means only AAD. */ if (src != NULL && dst == NULL) { if (ctx->enc) { ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, src, len); } else { ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, src, len); } } /* Only plain/cipher text. */ else if (src != NULL && dst != NULL) { if (ctx->enc) { ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, dst, src, len, NULL, 0); } else { ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, dst, src, len, NULL, 0); } } /* * src == NULL is analogous to other "final"-type functions * (e.g. EVP_CipherFinal). Calculates tag on encrypt * and checks tag on decrypt. */ else { if (ctx->enc) { /* Calculate authentication tag. */ ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes, ctx->authTag, ctx->authTagSz); /* * wc_AesGcmEncryptFinal increments the IV in * ctx->cipher.aes.reg, so we don't call IncCtr here. */ } else { /* Calculate authentication tag and compare. */ ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag, ctx->authTagSz); if (ctx->gcmIncIv) { IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz); } } /* Reinitialize for subsequent wolfSSL_EVP_Cipher calls. */ if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, (byte*)ctx->cipher.aes.reg, ctx->ivSz) != 0) { WOLFSSL_MSG("wc_AesGcmInit failed"); return WOLFSSL_FATAL_ERROR; } ctx->gcmIncIv = 0; } #endif /* WOLFSSL_AESGCM_STREAM */ if (src == NULL) { /* * Clear any leftover AAD on final (final is when src is * NULL). */ if (ctx->gcmAuthIn != NULL) { XMEMSET(ctx->gcmAuthIn, 0, ctx->gcmAuthInSz); } ctx->gcmAuthInSz = 0; } if (ret == 0) { ret = len; } return ret; } #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) || * HAVE_FIPS_VERSION >= 2 */ /* 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 #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_CBC_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CBC))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CBC))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CBC))) { 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 || WOLFSSL_AES_DIRECT */ #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) if ( #ifdef WOLFSSL_AES_128 ctx->cipherType == AES_128_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM)) #endif #ifdef WOLFSSL_AES_192 || ctx->cipherType == AES_192_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_GCM)) #endif #ifdef WOLFSSL_AES_256 || ctx->cipherType == AES_256_GCM_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_GCM)) #endif ) { if (EvpCipherInitAesGCM(ctx, type, key, iv, enc) != WOLFSSL_SUCCESS) { return WOLFSSL_FAILURE; } } #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) || * HAVE_FIPS_VERSION >= 2 */ #ifdef WOLFSSL_AES_COUNTER #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_CTR_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CTR))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CTR))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CTR))) { 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 HAVE_AES_ECB #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_ECB_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_ECB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_ECB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_ECB))) { 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 */ #endif /* HAVE_AES_ECB */ #ifdef WOLFSSL_AES_CFB #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_CFB1_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CFB1))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CFB1))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CFB1))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CFB8))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CFB8))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CFB8))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CFB128))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CFB128))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CFB128))) { 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 /* WOLFSSL_AES_CFB */ #ifdef WOLFSSL_AES_OFB #ifdef WOLFSSL_AES_128 if (ctx->cipherType == AES_128_OFB_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_OFB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_OFB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_OFB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_XTS))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_XTS))) { 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 */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (ctx->cipherType == CHACHA20_POLY1305_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_CHACHA20_POLY1305))) { WOLFSSL_MSG("EVP_CHACHA20_POLY1305"); ctx->cipherType = CHACHA20_POLY1305_TYPE; ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; ctx->flags |= WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER; ctx->keyLen = CHACHA20_POLY1305_AEAD_KEYSIZE; ctx->block_size = CHACHA_CHUNK_BYTES; ctx->authTagSz = CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE; ctx->ivSz = CHACHA20_POLY1305_AEAD_IV_SIZE; if (enc == 0 || enc == 1) { ctx->enc = (byte) enc; } if (key != NULL && iv != NULL && wc_ChaCha20Poly1305_Init( &ctx->cipher.chachaPoly, key, iv, enc) != 0) { WOLFSSL_MSG("wc_ChaCha20Poly1305_Init() failed"); return WOLFSSL_FAILURE; } } #endif #ifndef NO_DES3 if (ctx->cipherType == DES_CBC_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_DES_CBC))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_DES_ECB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_DES_EDE3_CBC))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_DES_EDE3_ECB))) { 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 && EVP_CIPHER_TYPE_MATCHES(type, EVP_ARC4))) { 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 */ if (ctx->cipherType == NULL_CIPHER_TYPE || (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_NULL))) { 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; else return WOLFSSL_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 WOLFSSL_FAILURE; return WOLFSSL_SUCCESS; } #ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV /* 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; } #endif #if defined(HAVE_AESGCM) || (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) /* 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"); 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 #if !defined(NO_AES) || !defined(NO_DES3) /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ int wolfSSL_EVP_CIPHER_CTX_get_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv, int ivLen) { int expectedIvLen; WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_get_iv"); if (ctx == NULL || iv == NULL || ivLen == 0) { WOLFSSL_MSG("Bad parameter"); return WOLFSSL_FAILURE; } expectedIvLen = wolfSSL_EVP_CIPHER_CTX_iv_length(ctx); if (expectedIvLen == 0 || expectedIvLen != ivLen) { WOLFSSL_MSG("Wrong ivLen value"); return WOLFSSL_FAILURE; } XMEMCPY(iv, ctx->iv, ivLen); return WOLFSSL_SUCCESS; } #endif /* !NO_AES || !NO_DES3 */ /* Return length on ok */ int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, word32 len) { int ret = WOLFSSL_FAILURE; 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 argument."); return WOLFSSL_FATAL_ERROR; } if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) { WOLFSSL_MSG("Cipher operation not initialized. Call " "wolfSSL_EVP_CipherInit."); return WOLFSSL_FATAL_ERROR; } 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); if (ret == 0) ret = (len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 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); if (ret == 0) ret = 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); if (ret == 0) ret = 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); if (ret == 0) ret = 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); if (ret == 0) ret = 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); if (ret == 0) ret = len; break; #endif /* WOLFSSL_AES_XTS */ #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \ || FIPS_VERSION_GE(2,0)) case AES_128_GCM_TYPE : case AES_192_GCM_TYPE : case AES_256_GCM_TYPE : WOLFSSL_MSG("AES GCM"); ret = EvpCipherAesGCM(ctx, dst, src, len); break; #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) || * HAVE_FIPS_VERSION >= 2 */ #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); if (ret == 0) ret = (len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 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); if (ret == 0) ret = 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); if (ret == 0) ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE; 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); if (ret == 0) ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE; break; #ifdef WOLFSSL_DES_ECB case DES_ECB_TYPE : WOLFSSL_MSG("DES ECB"); ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); if (ret == 0) ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE; break; case DES_EDE3_ECB_TYPE : WOLFSSL_MSG("DES3 ECB"); ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); if (ret == 0) ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE; break; #endif #endif /* !NO_DES3 */ #ifndef NO_RC4 case ARC4_TYPE : WOLFSSL_MSG("ARC4"); wc_Arc4Process(&ctx->cipher.arc4, dst, src, len); if (ret == 0) ret = len; break; #endif case NULL_CIPHER_TYPE : WOLFSSL_MSG("NULL CIPHER"); XMEMCPY(dst, src, len); ret = len; break; default: { WOLFSSL_MSG("bad type"); return WOLFSSL_FATAL_ERROR; } } if (ret < 0) { if (ret == AES_GCM_AUTH_E) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure: bad AES-GCM tag."); } WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); return WOLFSSL_FATAL_ERROR; } if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); return ret; } /* 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) { 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 = EvpMd2MacType(md); if (md == NULL) { XMEMSET(&ctx->hash.digest, 0, sizeof(WOLFSSL_Hasher)); } else #ifndef NO_SHA if ((XSTRCMP(md, "SHA") == 0) || (XSTRCMP(md, "SHA1") == 0)) { ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); } else #endif #ifndef NO_SHA256 if (XSTRCMP(md, "SHA256") == 0) { ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); } else #endif #ifdef WOLFSSL_SHA224 if (XSTRCMP(md, "SHA224") == 0) { ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); } else #endif #ifdef WOLFSSL_SHA384 if (XSTRCMP(md, "SHA384") == 0) { ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); } else #endif #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_224) if (XSTRCMP(md, "SHA512_224") == 0) { ret = wolfSSL_SHA512_224_Init(&(ctx->hash.digest.sha512)); } else #endif #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_256) if (XSTRCMP(md, "SHA512_256") == 0) { ret = wolfSSL_SHA512_256_Init(&(ctx->hash.digest.sha512)); } else #endif #ifdef WOLFSSL_SHA512 if (XSTRCMP(md, "SHA512") == 0) { ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); } else #endif #ifndef NO_MD4 if (XSTRCMP(md, "MD4") == 0) { wolfSSL_MD4_Init(&(ctx->hash.digest.md4)); } else #endif #ifndef NO_MD5 if (XSTRCMP(md, "MD5") == 0) { ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5)); } else #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 if (XSTRCMP(md, "SHA3_224") == 0) { ret = wolfSSL_SHA3_224_Init(&(ctx->hash.digest.sha3_224)); } else #endif #ifndef WOLFSSL_NOSHA3_256 if (XSTRCMP(md, "SHA3_256") == 0) { ret = wolfSSL_SHA3_256_Init(&(ctx->hash.digest.sha3_256)); } else #endif #ifndef WOLFSSL_NOSHA3_384 if (XSTRCMP(md, "SHA3_384") == 0) { ret = wolfSSL_SHA3_384_Init(&(ctx->hash.digest.sha3_384)); } else #endif #ifndef WOLFSSL_NOSHA3_512 if (XSTRCMP(md, "SHA3_512") == 0) { ret = wolfSSL_SHA3_512_Init(&(ctx->hash.digest.sha3_512)); } else #endif #endif { 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 ret = WOLFSSL_FAILURE; enum wc_HashType macType; WOLFSSL_ENTER("EVP_DigestUpdate"); macType = EvpMd2MacType(EVP_MD_CTX_md(ctx)); switch (macType) { case WC_HASH_TYPE_MD4: #ifndef NO_MD4 wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data, (unsigned long)sz); ret = WOLFSSL_SUCCESS; #endif break; case WC_HASH_TYPE_MD5: #ifndef NO_MD5 ret = wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, (unsigned long)sz); #endif /* !NO_SHA256 */ break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, (unsigned long)sz); #endif /* WOLFSSL_SHA512 */ break; #ifndef WOLFSSL_NOSHA512_224 case WC_HASH_TYPE_SHA512_224: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wolfSSL_SHA512_224_Update((SHA512_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; #endif /* !WOLFSSL_NOSHA512_224 */ #ifndef WOLFSSL_NOSHA512_256 case WC_HASH_TYPE_SHA512_256: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wolfSSL_SHA512_256_Update((SHA512_CTX*)&ctx->hash, data, (unsigned long)sz); #endif /* WOLFSSL_SHA512 */ break; #endif /* !WOLFSSL_NOSHA512_256 */ case WC_HASH_TYPE_SHA3_224: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) ret = wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA3_256: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) ret = wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA3_384: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) ret = wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_SHA3_512: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) ret = wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data, (unsigned long)sz); #endif break; case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_BLAKE2B: case WC_HASH_TYPE_BLAKE2S: #ifndef WOLFSSL_NO_SHAKE256 case WC_HASH_TYPE_SHAKE128: case WC_HASH_TYPE_SHAKE256: #endif default: return WOLFSSL_FAILURE; } return ret; } /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s) { int ret = WOLFSSL_FAILURE; enum wc_HashType macType; WOLFSSL_ENTER("EVP_DigestFinal"); macType = EvpMd2MacType(EVP_MD_CTX_md(ctx)); switch (macType) { case WC_HASH_TYPE_MD4: #ifndef NO_MD4 wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash); if (s) *s = MD4_DIGEST_SIZE; ret = WOLFSSL_SUCCESS; #endif break; case WC_HASH_TYPE_MD5: #ifndef NO_MD5 ret = wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); if (s) *s = WC_MD5_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); if (s) *s = WC_SHA_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash); if (s) *s = WC_SHA224_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); if (s) *s = WC_SHA256_DIGEST_SIZE; #endif /* !NO_SHA256 */ break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); if (s) *s = WC_SHA384_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); if (s) *s = WC_SHA512_DIGEST_SIZE; #endif /* WOLFSSL_SHA512 */ break; #ifndef WOLFSSL_NOSHA512_224 case WC_HASH_TYPE_SHA512_224: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wolfSSL_SHA512_224_Final(md, (SHA512_CTX*)&ctx->hash); if (s) *s = WC_SHA512_224_DIGEST_SIZE; #endif break; #endif /* !WOLFSSL_NOSHA512_224 */ #ifndef WOLFSSL_NOSHA512_256 case WC_HASH_TYPE_SHA512_256: #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ defined(WOLFSSL_SHA512) ret = wolfSSL_SHA512_256_Final(md, (SHA512_CTX*)&ctx->hash); if (s) *s = WC_SHA512_256_DIGEST_SIZE; #endif break; #endif /* !WOLFSSL_NOSHA512_256 */ case WC_HASH_TYPE_SHA3_224: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) ret = wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash); if (s) *s = WC_SHA3_224_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA3_256: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) ret = wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash); if (s) *s = WC_SHA3_256_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA3_384: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) ret = wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash); if (s) *s = WC_SHA3_384_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA3_512: #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) ret = wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash); if (s) *s = WC_SHA3_512_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_BLAKE2B: case WC_HASH_TYPE_BLAKE2S: #ifndef WOLFSSL_NO_SHAKE256 case WC_HASH_TYPE_SHAKE128: case WC_HASH_TYPE_SHAKE256: #endif default: return WOLFSSL_FAILURE; } return ret; } /* 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 #ifdef WOLFSSL_SHA224 case NID_sha224: return wolfSSL_EVP_sha224(); #endif #ifndef NO_SHA256 case NID_sha256: return wolfSSL_EVP_sha256(); #endif #ifdef WOLFSSL_SHA384 case NID_sha384: return wolfSSL_EVP_sha384(); #endif #ifdef WOLFSSL_SHA512 case NID_sha512: return wolfSSL_EVP_sha512(); #endif default: WOLFSSL_MSG("Bad digest id value"); } return NULL; } static void clearEVPPkeyKeys(WOLFSSL_EVP_PKEY *pkey) { if(pkey == NULL) return; WOLFSSL_ENTER("clearEVPPkeyKeys"); #ifndef NO_RSA if (pkey->rsa != NULL && pkey->ownRsa == 1) { wolfSSL_RSA_free(pkey->rsa); pkey->rsa = NULL; } pkey->ownRsa = 0; #endif #ifndef NO_DSA if (pkey->dsa != NULL && pkey->ownDsa == 1) { wolfSSL_DSA_free(pkey->dsa); pkey->dsa = NULL; } pkey->ownDsa = 0; #endif #ifndef NO_DH if (pkey->dh != NULL && pkey->ownDh == 1) { wolfSSL_DH_free(pkey->dh); pkey->dh = NULL; } pkey->ownDh = 0; #endif #ifdef HAVE_ECC if (pkey->ecc != NULL && pkey->ownEcc == 1) { wolfSSL_EC_KEY_free(pkey->ecc); pkey->ecc = NULL; } pkey->ownEcc = 0; #endif } #ifndef NO_RSA #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) static int PopulateRSAEvpPkeyDer(WOLFSSL_EVP_PKEY *pkey) { int ret = 0; int derSz = 0; word32 pkcs8Sz = 0; byte* derBuf = NULL; RsaKey* rsa = NULL; WOLFSSL_RSA *key = NULL; if (pkey == NULL || pkey->rsa == NULL || pkey->rsa->internal == NULL) { WOLFSSL_MSG("bad parameter"); return WOLFSSL_FAILURE; } key = pkey->rsa; rsa = (RsaKey*)pkey->rsa->internal; /* Get DER size */ if (rsa->type == RSA_PRIVATE) { ret = wc_RsaKeyToDer(rsa, NULL, 0); if (ret > 0) { derSz = ret; #ifdef HAVE_PKCS8 if (key->pkcs8HeaderSz) { ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, NULL, derSz, RSAk, NULL, 0); if (ret == LENGTH_ONLY_E) ret = 0; } #endif } } else { ret = wc_RsaKeyToPublicDer(rsa, NULL, 0); if (ret > 0) derSz = ret; } if (derSz == 0 || ret < 0) { WOLFSSL_MSG("Error getting RSA DER size"); return WOLFSSL_FAILURE; } derBuf = (byte*)XREALLOC(pkey->pkey.ptr, derSz, pkey->heap, DYNAMIC_TYPE_DER); if (derBuf == NULL) { WOLFSSL_MSG("PopulateRSAEvpPkeyDer malloc failed"); return WOLFSSL_FAILURE; } /* Old pointer is invalid from this point on */ pkey->pkey.ptr = (char*)derBuf; if (rsa->type == RSA_PRIVATE) { ret = wc_RsaKeyToDer(rsa, derBuf, derSz); if (ret > 0) { derSz = ret; #ifdef HAVE_PKCS8 if (key->pkcs8HeaderSz) { byte* keyBuf = derBuf; int keySz = derSz; derSz = pkcs8Sz; /* Need new buffer for PKCS8 since we can't * do this in-place */ derBuf = (byte*)XMALLOC(pkcs8Sz, pkey->heap, DYNAMIC_TYPE_DER); if (derBuf != NULL) { ret = wc_CreatePKCS8Key(derBuf, (word32*)&derSz, keyBuf, keySz, RSAk, NULL, 0); XFREE(keyBuf, pkey->heap, DYNAMIC_TYPE_DER); pkey->pkey.ptr = (char*)derBuf; } else ret = MEMORY_E; } #endif } } else { /* Public key to DER */ ret = wc_RsaKeyToPublicDer(rsa, derBuf, derSz); if (ret > 0) derSz = ret; } if (ret < 0) { WOLFSSL_MSG("PopulateRSAEvpPkeyDer failed"); return WOLFSSL_FAILURE; } else { pkey->pkey_sz = derSz; return WOLFSSL_SUCCESS; } } #endif WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(WOLFSSL_EVP_PKEY *pkey) { WOLFSSL_MSG("wolfSSL_EVP_PKEY_get0_RSA"); if (pkey == NULL) return NULL; return pkey->rsa; } WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* pkey) { WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA"); if (pkey == NULL || pkey->rsa == NULL) return NULL; if (wolfSSL_RSA_up_ref(pkey->rsa) != WOLFSSL_SUCCESS) return NULL; return pkey->rsa; } /* 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) { WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA"); if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; if (wolfSSL_RSA_up_ref(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_RSA_up_ref failed"); return WOLFSSL_FAILURE; } clearEVPPkeyKeys(pkey); pkey->rsa = key; pkey->ownRsa = 1; /* pkey does not own RSA but needs to call free on it */ pkey->type = EVP_PKEY_RSA; pkey->pkcs8HeaderSz = key->pkcs8HeaderSz; 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) if (PopulateRSAEvpPkeyDer(pkey) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("PopulateRSAEvpPkeyDer failed"); return WOLFSSL_FAILURE; } #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; clearEVPPkeyKeys(pkey); 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_get0_DSA(struct WOLFSSL_EVP_PKEY *pkey) { if (!pkey) { return NULL; } return pkey->dsa; } 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 && pkey->type == EVP_PKEY_EC) { #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 = NULL; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_EC_KEY"); if (key == NULL || key->type != EVP_PKEY_EC) { return NULL; } if (key->type == EVP_PKEY_EC) { if (key->ecc != NULL) { if (wolfSSL_EC_KEY_up_ref(key->ecc) != WOLFSSL_SUCCESS) { return NULL; } local = key->ecc; } else { key->ecc = local = wolfSSL_EC_KEY_new(); if (local == NULL) { WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure"); return NULL; } if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr, key->pkey_sz) != WOLFSSL_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) != WOLFSSL_SUCCESS) { wolfSSL_EC_KEY_free(local); local = NULL; } } } } else { WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an EC key"); } return local; } #endif /* HAVE_ECC */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !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; clearEVPPkeyKeys(pkey); if (wolfSSL_DH_up_ref(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Failed to increase dh key ref count"); return WOLFSSL_FAILURE; } pkey->dh = key; pkey->ownDh = 1; /* pkey does not own DH but needs to call free on it */ 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) { /* if key->dh already exists copy instead of re-importing from DER */ if (key->dh != NULL) { if (wolfSSL_DH_up_ref(key->dh) != WOLFSSL_SUCCESS) { return NULL; } local = key->dh; } else { #if !defined(NO_DH) && (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ (HAVE_FIPS_VERSION>2))) 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("EVP_PKEY does not hold DH struct"); return NULL; #endif } } else { WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DH key"); wolfSSL_DH_free(local); return NULL; } return local; } #endif /* NO_DH && WOLFSSL_DH_EXTRA && 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 #ifndef 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 int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) { int derSz = 0; byte* derBuf = NULL; ecc_key* ecc; if (pkey == NULL || key == NULL || key->internal == NULL) return WOLFSSL_FAILURE; ecc = (ecc_key*)key->internal; if (ecc->type == ECC_PRIVATEKEY || ecc->type == ECC_PRIVATEKEY_ONLY) { #ifdef HAVE_PKCS8 if (key->pkcs8HeaderSz) { /* when key has pkcs8 header the pkey should too */ if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == LENGTH_ONLY_E) { derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); if (derBuf) { if (wc_EccKeyToPKCS8(ecc, derBuf, (word32*)&derSz) >= 0) { if (pkey->pkey.ptr) { XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); } pkey->pkey_sz = (int)derSz; pkey->pkey.ptr = (char*)derBuf; pkey->pkcs8HeaderSz = key->pkcs8HeaderSz; return WOLFSSL_SUCCESS; } else { XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_OPENSSL); derBuf = NULL; } } } } else #endif /* HAVE_PKCS8 */ { if (ecc->type == ECC_PRIVATEKEY_ONLY) { if (wc_ecc_make_pub(ecc, NULL) != MP_OKAY) { return WOLFSSL_FAILURE; } } /* if not, the pkey will be traditional ecc key */ if ((derSz = wc_EccKeyDerSize(ecc, 1)) > 0) { derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); if (derBuf) { if (wc_EccKeyToDer(ecc, derBuf, derSz) >= 0) { if (pkey->pkey.ptr) { XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); } pkey->pkey_sz = (int)derSz; pkey->pkey.ptr = (char*)derBuf; return WOLFSSL_SUCCESS; } else { XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_OPENSSL); derBuf = NULL; } } } } } else if (ecc->type == ECC_PUBLICKEY) { if ((derSz = (word32)wc_EccPublicKeyDerSize(ecc, 1)) > 0) { derBuf = (byte*)XREALLOC(pkey->pkey.ptr, derSz, NULL, DYNAMIC_TYPE_OPENSSL); if (derBuf != NULL) { pkey->pkey.ptr = (char*)derBuf; if ((derSz = wc_EccPublicKeyToDer(ecc, derBuf, derSz, 1)) < 0) { XFREE(derBuf, NULL, DYNAMIC_TYPE_OPENSSL); derBuf = NULL; } } } } if (derBuf != NULL) { pkey->pkey_sz = (int)derSz; return WOLFSSL_SUCCESS; } else { return WOLFSSL_FAILURE; } } int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) { #ifdef HAVE_ECC WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_EC_KEY"); if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; clearEVPPkeyKeys(pkey); if (wolfSSL_EC_KEY_up_ref(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_EC_KEY_up_ref failed"); return WOLFSSL_FAILURE; } pkey->ecc = key; pkey->ownEcc = 1; /* pkey needs to call free on key */ pkey->type = EVP_PKEY_EC; return ECC_populate_EVP_PKEY(pkey, key); #else (void)pkey; (void)key; return WOLFSSL_FAILURE; #endif /* HAVE_ECC */ } 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) { int ret; if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; /* try and populate public pkey_sz and pkey.ptr */ ret = ECC_populate_EVP_PKEY(pkey, key); if (ret == WOLFSSL_SUCCESS) { /* take ownership of key if can be used */ clearEVPPkeyKeys(pkey); /* clear out any previous keys */ pkey->type = EVP_PKEY_EC; pkey->ecc = key; pkey->ownEcc = 1; } return ret; } #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; } #ifndef NO_SHA if ((XSTRCMP(type, "SHA") == 0) || (XSTRCMP(type, "SHA1") == 0)) { return WC_SHA_BLOCK_SIZE; } else #endif #ifndef NO_SHA256 if (XSTRCMP(type, "SHA256") == 0) { return WC_SHA256_BLOCK_SIZE; } else #endif #ifndef NO_MD4 if (XSTRCMP(type, "MD4") == 0) { return MD4_BLOCK_SIZE; } else #endif #ifndef NO_MD5 if (XSTRCMP(type, "MD5") == 0) { return WC_MD5_BLOCK_SIZE; } else #endif #ifdef WOLFSSL_SHA224 if (XSTRCMP(type, "SHA224") == 0) { return WC_SHA224_BLOCK_SIZE; } else #endif #ifdef WOLFSSL_SHA384 if (XSTRCMP(type, "SHA384") == 0) { return WC_SHA384_BLOCK_SIZE; } else #endif #ifdef WOLFSSL_SHA512 if (XSTRCMP(type, "SHA512") == 0) { return WC_SHA512_BLOCK_SIZE; } else #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 if (XSTRCMP(type, "SHA3_224") == 0) { return WC_SHA3_224_BLOCK_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_256 if (XSTRCMP(type, "SHA3_256") == 0) { return WC_SHA3_256_BLOCK_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_384 if (XSTRCMP(type, "SHA3_384") == 0) { return WC_SHA3_384_BLOCK_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_512 if (XSTRCMP(type, "SHA3_512") == 0) { return WC_SHA3_512_BLOCK_SIZE; } #endif #endif /* WOLFSSL_SHA3 */ 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; } #ifndef NO_SHA if ((XSTRCMP(type, "SHA") == 0) || (XSTRCMP(type, "SHA1") == 0)) { return WC_SHA_DIGEST_SIZE; } else #endif #ifndef NO_SHA256 if (XSTRCMP(type, "SHA256") == 0) { return WC_SHA256_DIGEST_SIZE; } else #endif #ifndef NO_MD4 if (XSTRCMP(type, "MD4") == 0) { return MD4_DIGEST_SIZE; } else #endif #ifndef NO_MD5 if (XSTRCMP(type, "MD5") == 0) { return WC_MD5_DIGEST_SIZE; } else #endif #ifdef WOLFSSL_SHA224 if (XSTRCMP(type, "SHA224") == 0) { return WC_SHA224_DIGEST_SIZE; } else #endif #ifdef WOLFSSL_SHA384 if (XSTRCMP(type, "SHA384") == 0) { return WC_SHA384_DIGEST_SIZE; } else #endif #ifdef WOLFSSL_SHA512 if (XSTRCMP(type, "SHA512") == 0) { return WC_SHA512_DIGEST_SIZE; } else #ifndef WOLFSSL_NOSHA512_224 if (XSTRCMP(type, "SHA512_224") == 0) { return WC_SHA512_224_DIGEST_SIZE; } else #endif #ifndef WOLFSSL_NOSHA512_256 if (XSTRCMP(type, "SHA512_256") == 0) { return WC_SHA512_256_DIGEST_SIZE; } else #endif #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 if (XSTRCMP(type, "SHA3_224") == 0) { return WC_SHA3_224_DIGEST_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_256 if (XSTRCMP(type, "SHA3_256") == 0) { return WC_SHA3_256_DIGEST_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_384 if (XSTRCMP(type, "SHA3_384") == 0) { return WC_SHA3_384_DIGEST_SIZE; } else #endif #ifndef WOLFSSL_NOSHA3_512 if (XSTRCMP(type, "SHA3_512") == 0) { return WC_SHA3_512_DIGEST_SIZE; } #endif #endif /* WOLFSSL_SHA3 */ return BAD_FUNC_ARG; } int wolfSSL_EVP_MD_pkey_type(const WOLFSSL_EVP_MD* type) { int ret = BAD_FUNC_ARG; WOLFSSL_ENTER("wolfSSL_EVP_MD_pkey_type"); if (type != NULL) { if (XSTRCMP(type, "MD5") == 0) { ret = NID_md5WithRSAEncryption; } else if (XSTRCMP(type, "SHA1") == 0) { ret = NID_sha1WithRSAEncryption; } else if (XSTRCMP(type, "SHA224") == 0) { ret = NID_sha224WithRSAEncryption; } else if (XSTRCMP(type, "SHA256") == 0) { ret = NID_sha256WithRSAEncryption; } else if (XSTRCMP(type, "SHA384") == 0) { ret = NID_sha384WithRSAEncryption; } else if (XSTRCMP(type, "SHA512") == 0) { ret = NID_sha512WithRSAEncryption; } } WOLFSSL_LEAVE("wolfSSL_EVP_MD_pkey_type", ret); return ret; } int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) { WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); switch (ctx->cipherType) { #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) case AES_128_CBC_TYPE : case AES_192_CBC_TYPE : case AES_256_CBC_TYPE : WOLFSSL_MSG("AES CBC"); return AES_BLOCK_SIZE; #endif #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) #ifdef HAVE_AESGCM case AES_128_GCM_TYPE : case AES_192_GCM_TYPE : case AES_256_GCM_TYPE : WOLFSSL_MSG("AES GCM"); if (ctx->ivSz != 0) { return ctx->ivSz; } return GCM_NONCE_MID_SZ; #endif #endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION >= 2 */ #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 #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 */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case CHACHA20_POLY1305_TYPE: WOLFSSL_MSG("CHACHA20 POLY1305"); return CHACHA20_POLY1305_AEAD_IV_SIZE; #endif /* HAVE_CHACHA HAVE_POLY1305 */ 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 #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) #ifdef WOLFSSL_AES_128 if (XSTRCMP(name, EVP_AES_128_CBC) == 0) return AES_BLOCK_SIZE; #endif #ifdef WOLFSSL_AES_192 if (XSTRCMP(name, EVP_AES_192_CBC) == 0) return AES_BLOCK_SIZE; #endif #ifdef WOLFSSL_AES_256 if (XSTRCMP(name, EVP_AES_256_CBC) == 0) return AES_BLOCK_SIZE; #endif #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) #ifdef HAVE_AESGCM #ifdef WOLFSSL_AES_128 if (XSTRCMP(name, EVP_AES_128_GCM) == 0) return GCM_NONCE_MID_SZ; #endif #ifdef WOLFSSL_AES_192 if (XSTRCMP(name, EVP_AES_192_GCM) == 0) return GCM_NONCE_MID_SZ; #endif #ifdef WOLFSSL_AES_256 if (XSTRCMP(name, EVP_AES_256_GCM) == 0) return GCM_NONCE_MID_SZ; #endif #endif /* HAVE_AESGCM */ #endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION >= 2 */ #ifdef WOLFSSL_AES_COUNTER #ifdef WOLFSSL_AES_128 if (XSTRCMP(name, EVP_AES_128_CTR) == 0) return AES_BLOCK_SIZE; #endif #ifdef WOLFSSL_AES_192 if (XSTRCMP(name, EVP_AES_192_CTR) == 0) return AES_BLOCK_SIZE; #endif #ifdef WOLFSSL_AES_256 if (XSTRCMP(name, EVP_AES_256_CTR) == 0) return AES_BLOCK_SIZE; #endif #endif #ifdef WOLFSSL_AES_XTS #ifdef WOLFSSL_AES_128 if (XSTRCMP(name, EVP_AES_128_XTS) == 0) return AES_BLOCK_SIZE; #endif /* WOLFSSL_AES_128 */ #ifdef WOLFSSL_AES_256 if (XSTRCMP(name, EVP_AES_256_XTS) == 0) return AES_BLOCK_SIZE; #endif /* WOLFSSL_AES_256 */ #endif /* WOLFSSL_AES_XTS */ #endif #ifndef NO_DES3 if ((XSTRCMP(name, EVP_DES_CBC) == 0) || (XSTRCMP(name, EVP_DES_EDE3_CBC) == 0)) { return DES_BLOCK_SIZE; } #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (XSTRCMP(name, EVP_CHACHA20_POLY1305) == 0) return CHACHA20_POLY1305_AEAD_IV_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 WOLFSSL_EVP_PKEY *pkey) { if (pkey != NULL) return pkey->type; return 0; } int wolfSSL_EVP_PKEY_base_id(const WOLFSSL_EVP_PKEY *pkey) { if (pkey == NULL) return NID_undef; return wolfSSL_EVP_PKEY_type(pkey->type); } int wolfSSL_EVP_PKEY_get_default_digest_nid(WOLFSSL_EVP_PKEY *pkey, int *pnid) { WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get_default_digest_nid"); if (!pkey || !pnid) { WOLFSSL_MSG("Bad parameter"); return WOLFSSL_FAILURE; } switch (pkey->type) { case EVP_PKEY_HMAC: #ifndef NO_DSA case EVP_PKEY_DSA: #endif #ifndef NO_RSA case EVP_PKEY_RSA: #endif #ifdef HAVE_ECC case EVP_PKEY_EC: #endif *pnid = NID_sha256; return WOLFSSL_SUCCESS; default: return WOLFSSL_FAILURE; } } #if defined(OPENSSL_ALL) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKCS82PKEY(const WOLFSSL_PKCS8_PRIV_KEY_INFO* p8) { if (p8 == NULL || p8->pkey.ptr == NULL) { return NULL; } return wolfSSL_d2i_PrivateKey_EVP(NULL, (unsigned char**)&p8->pkey.ptr, p8->pkey_sz); } /* in wolf PKCS8_PRIV_KEY_INFO and WOLFSSL_EVP_PKEY are same type */ /* this function just casts and returns pointer */ WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_EVP_PKEY2PKCS8(const WOLFSSL_EVP_PKEY* pkey) { return (WOLFSSL_PKCS8_PRIV_KEY_INFO*)pkey; } #endif /* 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) { #ifndef SINGLE_THREADED if (wc_LockMutex(&pkey->refMutex) != 0) { WOLFSSL_MSG("Failed to lock pkey mutex"); } #endif pkey->references++; #ifndef SINGLE_THREADED wc_UnLockMutex(&pkey->refMutex); #endif return WOLFSSL_SUCCESS; } return WOLFSSL_FAILURE; } #ifndef NO_RSA int wolfSSL_EVP_PKEY_assign_RSA(EVP_PKEY* pkey, WOLFSSL_RSA* key) { if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; clearEVPPkeyKeys(pkey); pkey->type = EVP_PKEY_RSA; pkey->rsa = key; pkey->ownRsa = 1; /* try and populate pkey_sz and pkey.ptr */ if (key->internal) { RsaKey* rsa = (RsaKey*)key->internal; int ret = wc_RsaKeyToDer(rsa, NULL, 0); if (ret > 0) { int derSz = ret; byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (derBuf) { ret = wc_RsaKeyToDer(rsa, derBuf, derSz); if (ret >= 0) { pkey->pkey_sz = ret; pkey->pkey.ptr = (char*)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; clearEVPPkeyKeys(pkey); 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; clearEVPPkeyKeys(pkey); pkey->type = EVP_PKEY_DH; pkey->dh = key; pkey->ownDh = 1; return WOLFSSL_SUCCESS; } #endif /* !NO_DH */ #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || 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 SINGLE_THREADED /* init of mutex needs to come before wolfSSL_EVP_PKEY_free */ ret = wc_InitMutex(&pkey->refMutex); if (ret != 0){ XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); WOLFSSL_MSG("Issue initializing mutex"); return NULL; } #endif #ifndef HAVE_FIPS ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); #else ret = wc_InitRng(&pkey->rng); #endif pkey->references = 1; if (ret != 0){ wolfSSL_EVP_PKEY_free(pkey); WOLFSSL_MSG("Issue initializing RNG"); return NULL; } } 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) { #ifndef SINGLE_THREADED if (wc_LockMutex(&key->refMutex) != 0) { WOLFSSL_MSG("Couldn't lock pkey mutex"); } #endif /* only free if all references to it are done */ key->references--; if (key->references == 0) { doFree = 1; } #ifndef SINGLE_THREADED wc_UnLockMutex(&key->refMutex); #endif 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 ... */ #ifdef HAVE_HKDF case EVP_PKEY_HKDF: if (key->hkdfSalt != NULL) { XFREE(key->hkdfSalt, NULL, DYNAMIC_TYPE_SALT); key->hkdfSalt = NULL; } if (key->hkdfKey != NULL) { XFREE(key->hkdfKey, NULL, DYNAMIC_TYPE_KEY); key->hkdfKey = NULL; } if (key->hkdfInfo != NULL) { XFREE(key->hkdfInfo, NULL, DYNAMIC_TYPE_INFO); key->hkdfInfo = NULL; } key->hkdfSaltSz = 0; key->hkdfKeySz = 0; key->hkdfInfoSz = 0; break; #endif /* HAVE_HKDF */ default: break; } #ifndef SINGLE_THREADED if (wc_FreeMutex(&key->refMutex) != 0) { WOLFSSL_MSG("Couldn't free pkey mutex"); } #endif XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); } } } #if defined(OPENSSL_EXTRA) && !defined(NO_BIO) /* Indent writes white spaces of the number specified by "indents" * to the BIO. The number of white spaces is limited from 0 to * EVP_PKEY_PRINT_INDENT_MAX. * returns the amount written to BIO. */ static int Indent(WOLFSSL_BIO* out, int indents) { int i; char space = ' '; if (out == NULL) { return 0; } if (indents > EVP_PKEY_PRINT_INDENT_MAX) { indents = EVP_PKEY_PRINT_INDENT_MAX; } for (i = 0; i < indents; i++) { if (wolfSSL_BIO_write(out, &space, 1) < 0) { break; } } return indents -i; } /* PrintHexWithColon dump byte-data specified by "input" to the "out". * Each line has leading white spaces( "indent" gives the number ) plus * four spaces, then hex coded 15 byte data with separator ":" follow. * Each line looks like: * " 00:e6:ab: --- 9f:ef:" * Parameters: * out bio to output dump data * input buffer holding data to dump * inlen input data size * indent the number of spaces for indent * Returns 1 on success, 0 on failure. */ static int PrintHexWithColon(WOLFSSL_BIO* out, const byte* input, int inlen, int indent) { #ifdef WOLFSSL_SMALL_STACK byte* buff = NULL; #else byte buff[EVP_PKEY_PRINT_LINE_WIDTH_MAX] = { 0 }; #endif /* WOLFSSL_SMALL_STACK */ int ret = WOLFSSL_SUCCESS; word32 in = 0; word32 i; int idx; const byte* data; word32 outSz; byte outHex[3]; if (!out || !input || inlen <= 0) { return WOLFSSL_FAILURE; } if (indent < 0) { indent = 0; } if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } data = input; #ifdef WOLFSSL_SMALL_STACK buff = (byte*)XMALLOC(EVP_PKEY_PRINT_LINE_WIDTH_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!buff) { return WOLFSSL_FAILURE; } #endif /* print pub element */ idx = 0; for (in = 0; in < (word32)inlen && ret == WOLFSSL_SUCCESS; in += EVP_PKEY_PRINT_DIGITS_PER_LINE ) { Indent(out, indent); for (i = 0; (i < EVP_PKEY_PRINT_DIGITS_PER_LINE) && (in + i < (word32)inlen); i++) { if (ret == WOLFSSL_SUCCESS) { outSz = sizeof(outHex); ret = Base16_Encode((const byte*)&data[in + i], 1, outHex, &outSz) == 0; } if (ret == WOLFSSL_SUCCESS) { XMEMCPY(buff + idx, outHex, 2); idx += 2; if (in + i != (word32)inlen -1) { XMEMSET(buff + idx, ':', 1); idx += 1; } } } if (ret == WOLFSSL_SUCCESS) { ret = wolfSSL_BIO_write(out, buff, idx) > 0; } if (ret == WOLFSSL_SUCCESS) { ret = wolfSSL_BIO_write(out, "\n", 1) > 0; } if (ret == WOLFSSL_SUCCESS) { XMEMSET(buff, 0, EVP_PKEY_PRINT_LINE_WIDTH_MAX); idx = 0; } } #ifdef WOLFSSL_SMALL_STACK XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } #if !defined(NO_RSA) /* PrintPubKeyRSA is a helper function for wolfSSL_EVP_PKEY_print_public * to parse a DER format RSA public key specified in the second parameter. * Parameters: * out bio to output dump data * pkey buffer holding public key data * pkeySz public key data size * indent the number of spaces for indent * bitlen bit size of the given key * pctx context(not used) * Returns 1 on success, 0 on failure. */ static int PrintPubKeyRSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, int indent, int bitlen, ASN1_PCTX* pctx) { byte buff[8] = { 0 }; int res = WOLFSSL_FAILURE; word32 inOutIdx = 0; word32 nSz; /* size of modulus */ word32 eSz; /* size of public exponent */ const byte* n = NULL; const byte* e = NULL; /* pointer to modulus/exponent */ int idx; int wsz; word32 i; unsigned long exponent = 0; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; #else mp_int a[1]; #endif char line[32] = { 0 }; (void)pctx; #ifdef WOLFSSL_SMALL_STACK a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (a == NULL) { return WOLFSSL_FAILURE; } #endif if( mp_init(a) != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return WOLFSSL_FAILURE; } if (indent < 0) { indent = 0; } if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } do { /* parse key to get modulus and exponent */ if (wc_RsaPublicKeyDecode_ex(pkey, &inOutIdx, pkeySz, &n, &nSz, &e, &eSz) != 0) { break; } /* print out public key elements */ idx = 0; XMEMSET(buff, 0, sizeof(buff)); Indent(out, indent); XSTRNCPY(line, "RSA Public-Key: (", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (mp_set_int(a, bitlen) != 0) { break; } if (mp_todecimal(a, (char*)buff) != 0) { break; } wsz = (int)XSTRLEN((const char*)buff); if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { break; } XSTRNCPY(line, " bit)\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } /* print Modulus */ Indent(out, indent); XSTRNCPY(line, "Modulus:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } /* print modulus with leading zero if exists */ if (*n & 0x80 && *(n-1) == 0) { n--; nSz++; } if (PrintHexWithColon(out, n, nSz, indent + 4) != WOLFSSL_SUCCESS) { break; } /* print public Exponent */ idx = 0; Indent(out, indent); XSTRNCPY(line, "Exponent: ", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } for (i = 0; i < eSz; i++) { exponent <<= 8; exponent += e[i]; } XMEMSET(buff, 0, sizeof(buff)); if (mp_set_int(a, exponent) != 0) { break; } if (mp_todecimal(a, (char*)buff) != 0) { break; } wsz = (int)XSTRLEN((const char*)buff); if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { break; } XSTRNCPY(line, " (0x", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } XMEMSET(buff, 0, sizeof(buff)); if (mp_tohex(a, (char*)buff) != 0) { break; } if (wolfSSL_BIO_write(out, buff, (int)XSTRLEN((char*)buff)) <= 0) { break; } XSTRNCPY(line, ")\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } res = WOLFSSL_SUCCESS; } while (0); mp_free(a); #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return res; } #endif /* !NO_RSA */ #if defined(HAVE_ECC) /* PrintPubKeyEC is a helper function for wolfSSL_EVP_PKEY_print_public * to parse a DER format ECC public key specified in the second parameter. * Parameters: * out bio to output dump data * pkey buffer holding public key data * pkeySz public key data size * indent the number of spaces for indent * bitlen bit size of the given key * pctx context(not used) * Returns 1 on success, 0 on failure. */ static int PrintPubKeyEC(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, int indent, int bitlen, ASN1_PCTX* pctx) { byte* pub = NULL; word32 pubSz = 0; byte buff[8] = { 0 }; int res = WOLFSSL_SUCCESS; word32 inOutIdx = 0; int curveId = 0; const byte* curveOID = NULL; word32 oidSz = 0; const char* OIDName = NULL; const char* nistCurveName = NULL; int nid; int idx = 0; int wsz = 0; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; ecc_key* key = NULL; #else mp_int a[1]; ecc_key key[1]; #endif char line[32] = { 0 }; (void)pctx; #ifdef WOLFSSL_SMALL_STACK a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (a == NULL) { WOLFSSL_MSG("Failed to allocate memory for mp_int"); return WOLFSSL_FAILURE; } XMEMSET(a, 0, sizeof(mp_int)); key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); if (key == NULL) { WOLFSSL_MSG("Failed to allocate memory for ecc_key"); XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); return WOLFSSL_FAILURE; } #endif if (mp_init(a) != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_ECC); XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return WOLFSSL_FAILURE; } if (wc_ecc_init(key) != 0) { /* Return early so we don't have to remember if init succeeded * or not. */ mp_free(a); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_ECC); XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return WOLFSSL_FAILURE; } if (indent < 0) { indent = 0; } else if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } if (res == WOLFSSL_SUCCESS) { res = wc_EccPublicKeyDecode(pkey, &inOutIdx, key, pkeySz) == 0; } if (res == WOLFSSL_SUCCESS) { curveId = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz); res = curveId > 0 && oidSz > 0; } /* get NIST curve name */ if (res == WOLFSSL_SUCCESS) { nid = EccEnumToNID(curveId); if (nid != -1) { /* look up object name and nist curve name*/ OIDName = wolfSSL_OBJ_nid2sn(nid); nistCurveName = wolfSSL_EC_curve_nid2nist(nid); res = (nistCurveName != NULL) && (OIDName != NULL); } else { res = WOLFSSL_FAILURE; } } if (res == WOLFSSL_SUCCESS) { pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (pub != NULL) { pubSz = ECC_BUFSIZE; XMEMSET(pub, 0, ECC_BUFSIZE); PRIVATE_KEY_UNLOCK(); res = wc_ecc_export_x963(key, pub, &pubSz) == 0; PRIVATE_KEY_LOCK(); } else { res = WOLFSSL_FAILURE; } } if (res == WOLFSSL_SUCCESS) { idx = 0; res = Indent(out, indent) >= 0; } if (res == WOLFSSL_SUCCESS) { XSTRNCPY(line, "Public-Key: (", sizeof(line)); res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; } if (res == WOLFSSL_SUCCESS) { res = mp_set_int(a, bitlen) == 0; } if (res == WOLFSSL_SUCCESS) { res = mp_todecimal(a, (char*)buff) == 0; } if (res == WOLFSSL_SUCCESS) { wsz = (int)XSTRLEN((const char*)buff); } if (res == WOLFSSL_SUCCESS) { res = wolfSSL_BIO_write(out, buff + idx, wsz) >= 0; } if (res == WOLFSSL_SUCCESS) { XSTRNCPY(line, " bit)\n", sizeof(line)); res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; } if (res == WOLFSSL_SUCCESS) { res = Indent(out, indent) >= 0; } if (res == WOLFSSL_SUCCESS) { /* print pub element */ XSTRNCPY(line, "pub:\n", sizeof(line)); res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; } if (res == WOLFSSL_SUCCESS) { res = PrintHexWithColon(out, pub, pubSz, indent + 4); } if (res == WOLFSSL_SUCCESS) { res = Indent(out, indent) >= 0; } if (res == WOLFSSL_SUCCESS) { /* print OID in name */ XSTRNCPY(line, "ASN1 OID: ", sizeof(line)); res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; } if (res == WOLFSSL_SUCCESS) { res = wolfSSL_BIO_write(out, OIDName, (int)XSTRLEN(OIDName)) > 0; } if (res == WOLFSSL_SUCCESS) { res = wolfSSL_BIO_write(out, "\n", 1) > 0; } if (res == WOLFSSL_SUCCESS) { res = Indent(out, indent) >= 0; } if (res == WOLFSSL_SUCCESS) { /* print NIST curve name */ XSTRNCPY(line, "NIST CURVE: ", sizeof(line)); res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; } if (res == WOLFSSL_SUCCESS) { res = wolfSSL_BIO_write(out, nistCurveName, (int)XSTRLEN(nistCurveName)) > 0; } if (res == WOLFSSL_SUCCESS) { res = wolfSSL_BIO_write(out, "\n", 1) > 0; } if (pub != NULL) { XFREE(pub, NULL, DYNAMIC_TYPE_ECC_BUFFER); pub = NULL; } wc_ecc_free(key); mp_free(a); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_ECC); XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return res; } #endif /* HAVE_ECC */ #if !defined(NO_DSA) /* PrintPubKeyDSA is a helper function for wolfSSL_EVP_PKEY_print_public * to parse a DER format DSA public key specified in the second parameter. * Parameters: * out bio to output dump data * pkey buffer holding public key data * pkeySz public key data size * indent the number of spaces for indent * bitlen bit size of the given key * pctx context(not used) * Returns 1 on success, 0 on failure. */ static int PrintPubKeyDSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, int indent, int bitlen, ASN1_PCTX* pctx) { byte buff[8] = { 0 }; int length; int res = WOLFSSL_FAILURE; word32 inOutIdx = 0; word32 oid; byte tagFound; byte *p = NULL, * q = NULL, * g = NULL, * y = NULL; int pSz, qSz, gSz, ySz; int idx; int wsz; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; #else mp_int a[1]; #endif char line[32] = { 0 }; #ifdef WOLFSSL_SMALL_STACK a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (a == NULL) { return WOLFSSL_FAILURE; } #endif if( mp_init(a) != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return WOLFSSL_FAILURE; } inOutIdx = 0; (void)pctx; if (indent < 0) { indent = 0; } if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } do { if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { break; } if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { break; } if (GetObjectId(pkey, &inOutIdx, &oid, oidIgnoreType, pkeySz) != 0) { break; } if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { break; } /* find P */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { break; } p = (byte*)(pkey + inOutIdx); pSz = length; if (bitlen == 0) { if (*p == 0) { bitlen = (pSz - 1) * 8; /* remove leading zero */ } else { bitlen = pSz * 8; } } inOutIdx += length; /* find Q */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { break; } q = (byte*)(pkey + inOutIdx); qSz = length; inOutIdx += length; /* find G */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { break; } g = (byte*)(pkey + inOutIdx); gSz = length; inOutIdx += length; /* find Y */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_BIT_STRING) { break; } if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { break; } inOutIdx++; /* skip the first byte( unused byte number)*/ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { break; } y = (byte*)(pkey + inOutIdx); ySz = length; idx = 0; XMEMSET(buff, 0, sizeof(buff)); Indent(out, indent); XSTRNCPY(line, "DSA Public-Key: (", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (mp_set_int(a, bitlen) != 0) { break; } if (mp_todecimal(a, (char*)buff) != 0) { break; } wsz = (int)XSTRLEN((const char*)buff); if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { break; } XSTRNCPY(line, " bit)\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } /* print pub element */ Indent(out, indent); XSTRNCPY(line, "pub:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, y, ySz, indent + 4) != WOLFSSL_SUCCESS) { break; } /* print P element */ Indent(out, indent); XSTRNCPY(line, "P:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, p, pSz, indent + 4) != WOLFSSL_SUCCESS) { break; } /* print Q element */ Indent(out, indent); XSTRNCPY(line, "Q:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, q, qSz, indent + 4) != WOLFSSL_SUCCESS) { break; } /* print G element */ Indent(out, indent); XSTRNCPY(line, "G:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, g, gSz, indent + 4) != WOLFSSL_SUCCESS) { break; } res = WOLFSSL_SUCCESS; } while (0); mp_free(a); #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return res; } #endif /* !NO_DSA */ #if defined(WOLFSSL_DH_EXTRA) /* PrintPubKeyDH is a helper function for wolfSSL_EVP_PKEY_print_public * to parse a DER format DH public key specified in the second parameter. * Parameters: * out bio to output dump data * pkey buffer holding public key data * pkeySz public key data size * indent the number of spaces for indent * bitlen bit size of the given key * pctx context(not used) * Returns 1 on success, 0 on failure. */ static int PrintPubKeyDH(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, int indent, int bitlen, ASN1_PCTX* pctx) { byte buff[8] = { 0 }; int res = WOLFSSL_FAILURE; word32 length; word32 inOutIdx; word32 oid; byte tagFound; byte* prime = NULL; int primeSz; byte generator; byte* publicKey = NULL; int publicKeySz; int idx; int wsz; word32 outSz; byte outHex[3]; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; #else mp_int a[1]; #endif char line[32] = { 0 }; #ifdef WOLFSSL_SMALL_STACK a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (a == NULL) { return WOLFSSL_FAILURE; } #endif if( mp_init(a) != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return WOLFSSL_FAILURE; } inOutIdx = 0; (void)pctx; if (indent < 0) { indent = 0; } if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } do { if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { break; } if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { break; } if (GetObjectId(pkey, &inOutIdx, &oid, oidIgnoreType, pkeySz) < 0) { break; } if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { break; } /* get prime element */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { break; } prime = (byte*)(pkey + inOutIdx); primeSz = length; inOutIdx += length; /* get generator element */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { break; } if (length != 1) { break; } generator = *(pkey + inOutIdx); inOutIdx += length; /* get public-key element */ if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_BIT_STRING) { break; } if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { break; } inOutIdx ++; if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { break; } if (tagFound != ASN_INTEGER) { break; } if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { break; } publicKeySz = length; publicKey = (byte*)(pkey + inOutIdx); if (bitlen == 0) { if (*publicKey == 0) { bitlen = (publicKeySz - 1) * 8; } else { bitlen = publicKeySz * 8; } } /* print elements */ idx = 0; Indent(out, indent); XSTRNCPY(line, "DH Public-Key: (", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (mp_set_int(a, bitlen) != 0) { break; } if (mp_todecimal(a, (char*)buff) != 0) { break; } wsz = (int)XSTRLEN((const char*)buff); if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { break; } XSTRNCPY(line, " bit)\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } Indent(out, indent); XSTRNCPY(line, "public-key:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, publicKey, publicKeySz, indent + 4) != WOLFSSL_SUCCESS) { break; } Indent(out, indent); XSTRNCPY(line, "prime:\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (PrintHexWithColon(out, prime, primeSz, indent + 4) != WOLFSSL_SUCCESS) { break; } idx = 0; XMEMSET(buff, 0, sizeof(buff)); Indent(out, indent); XSTRNCPY(line, "generator: ", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } if (mp_set_int(a, generator) != 0) { break; } if (mp_todecimal(a, (char*)buff) != 0) { break; } wsz = (int)XSTRLEN((const char*)buff); if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { break; } XSTRNCPY(line, " (0x", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } idx = 0; XMEMSET(buff, 0, sizeof(buff)); outSz = sizeof(outHex); if (Base16_Encode((const byte*)&generator, 1, outHex, &outSz ) != 0) { break; } if (idx + 2 < (int)sizeof(buff) ) { XMEMCPY(buff + idx, outHex, 2); idx += 2; } if (wolfSSL_BIO_write(out, buff, idx) <= 0 ) { break; } XSTRNCPY(line, ")\n", sizeof(line)); if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { break; } res = WOLFSSL_SUCCESS; } while (0); mp_free(a); #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); #endif return res; } #endif /* WOLFSSL_DH_EXTRA */ /* wolfSSL_EVP_PKEY_print_public parses the specified key then * outputs public key info in human readable format to the specified BIO. * White spaces of the same number which 'indent" gives, will be added to * each line to output and ignores pctx parameter. * Parameters: * out bio to output dump data * pkey buffer holding public key data * indent the number of spaces for indent * pctx context(not used) * Returns 1 on success, 0 or negative on error, -2 means specified key * algo is not supported. * Can handle RSA, ECC, DSA and DH public keys. */ int wolfSSL_EVP_PKEY_print_public(WOLFSSL_BIO* out, const WOLFSSL_EVP_PKEY* pkey, int indent, ASN1_PCTX* pctx) { int res; #if !defined(NO_RSA) || defined(HAVE_ECC) || !defined(NO_DSA) || \ defined(WOLFSSL_DH_EXTRA) int keybits; /* bit length of the key */ #endif WOLFSSL_ENTER("wolfSSL_EVP_PKEY_print_public"); if (pkey == NULL || out == NULL) { return 0; } #if !defined(NO_RSA) || defined(HAVE_ECC) || !defined(NO_DSA) || \ defined(WOLFSSL_DH_EXTRA) if (indent < 0) { indent = 0; } if (indent > EVP_PKEY_PRINT_INDENT_MAX) { indent = EVP_PKEY_PRINT_INDENT_MAX; } #endif switch (pkey->type) { case EVP_PKEY_RSA: #if !defined(NO_RSA) keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; res = PrintPubKeyRSA( out, (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ pkey->pkey_sz, /* raw pkey size */ indent, /* indent size */ keybits, /* bit length of the key */ pctx); /* not used */ #else res = WOLFSSL_UNKNOWN; /* not supported algo */ #endif break; case EVP_PKEY_EC: #if defined(HAVE_ECC) keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; res = PrintPubKeyEC( out, (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ pkey->pkey_sz, /* raw pkey size */ indent, /* indent size */ keybits, /* bit length of the key */ pctx); /* not used */ #else res = WOLFSSL_UNKNOWN; /* not supported algo */ #endif break; case EVP_PKEY_DSA: #if !defined(NO_DSA) keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; res = PrintPubKeyDSA( out, (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ pkey->pkey_sz, /* raw pkey size */ indent, /* indent size */ keybits, /* bit length of the key */ pctx); /* not used */ #else res = WOLFSSL_UNKNOWN; /* not supported algo */ #endif break; case EVP_PKEY_DH: #if defined(WOLFSSL_DH_EXTRA) keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; res = PrintPubKeyDH( out, (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ pkey->pkey_sz, /* raw pkey size */ indent, /* indent size */ keybits, /* bit length of the key */ pctx); /* not used */ #else res = WOLFSSL_UNKNOWN; /* not supported algo */ #endif break; default: res = WOLFSSL_UNKNOWN; /* not supported algo */ break; } return res; } #endif /* OPENSSL_EXTRA && !NO_BIO */ 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; } #ifndef NO_SHA if ((XSTRCMP("SHA", evp) == 0) || (XSTRCMP("SHA1", evp) == 0)) { hash = WC_HASH_TYPE_SHA; } else #endif #ifdef WOLFSSL_SHA224 if (XSTRCMP("SHA224", evp) == 0) { hash = WC_HASH_TYPE_SHA224; } else #endif #ifndef NO_SHA256 if (XSTRCMP("SHA256", evp) == 0) { hash = WC_HASH_TYPE_SHA256; } else #endif #ifdef WOLFSSL_SHA384 if (XSTRCMP("SHA384", evp) == 0) { hash = WC_HASH_TYPE_SHA384; } else #endif #ifdef WOLFSSL_SHA512 if (XSTRCMP("SHA512", evp) == 0) { hash = WC_HASH_TYPE_SHA512; } else #ifndef WOLFSSL_NOSHA512_224 if (XSTRCMP("SHA512_224", evp) == 0) { hash = WC_HASH_TYPE_SHA512_224; } else #endif #ifndef WOLFSSL_NOSHA512_256 if (XSTRCMP("SHA512_256", evp) == 0) { hash = WC_HASH_TYPE_SHA512_256; } else #endif #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 if (XSTRCMP("SHA3_224", evp) == 0) { hash = WC_HASH_TYPE_SHA3_224; } else #endif #ifndef WOLFSSL_NOSHA3_256 if (XSTRCMP("SHA3_256", evp) == 0) { hash = WC_HASH_TYPE_SHA3_256; } else #endif #ifndef WOLFSSL_NOSHA3_384 if (XSTRCMP("SHA3_384", evp) == 0) { hash = WC_HASH_TYPE_SHA3_384; } else #endif #ifndef WOLFSSL_NOSHA3_512 if (XSTRCMP("SHA3_512", evp) == 0) { hash = WC_HASH_TYPE_SHA3_512; } else #endif #endif /* WOLFSSL_SHA3 */ #ifdef WOLFSSL_MD2 if (XSTRCMP("MD2", evp) == 0) { hash = WC_HASH_TYPE_MD2; } else #endif #ifndef NO_MD4 if (XSTRCMP("MD4", evp) == 0) { hash = WC_HASH_TYPE_MD4; } else #endif #ifndef NO_MD5 if (XSTRCMP("MD5", evp) == 0) { hash = WC_HASH_TYPE_MD5; } else #endif { if (XSTRNCMP("SHA", evp, 3) == 0) { WOLFSSL_MSG("Unknown SHA hash"); } return WOLFSSL_FAILURE; } if (pHash) *pHash = hash; hashSz = wc_HashGetDigestSize(hash); if (pHashSz) *pHashSz = hashSz; if (hashSz < 0) { return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; } /* Base64 encoding APIs */ #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) /* wolfSSL_EVP_ENCODE_CTX_new allocates WOLFSSL_EVP_ENCODE_CTX * Returns WOLFSSL_EVP_ENCODE_CTX structure on success, NULL on failure. */ struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void) { WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_new"); ctx = (WOLFSSL_EVP_ENCODE_CTX*)XMALLOC( sizeof(WOLFSSL_EVP_ENCODE_CTX), NULL, DYNAMIC_TYPE_OPENSSL ); if (ctx != NULL) { XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_ENCODE_CTX) ); ctx->heap = NULL; return ctx; } return NULL; } /* wolfSSL_EVP_ENCODE_CTX_free frees specified WOLFSSL_EVP_ENCODE_CTX struct. */ void wolfSSL_EVP_ENCODE_CTX_free(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_free"); if (ctx != NULL) { XFREE(ctx, ctx->heap, DYNAMIC_TYPE_OPENSSL); } } #endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE */ #if defined(WOLFSSL_BASE64_ENCODE) /* Assume that out has enough space */ int wolfSSL_EVP_EncodeBlock(unsigned char *out, const unsigned char *in, int inLen) { word32 ret = (word32)-1; WOLFSSL_ENTER("wolfSSL_EVP_EncodeBlock"); if (out == NULL || in == NULL) return WOLFSSL_FATAL_ERROR; if (Base64_Encode(in, inLen, out, &ret) == 0) return (int)ret; else return WOLFSSL_FATAL_ERROR; } /* Assume that out has enough space */ int wolfSSL_EVP_DecodeBlock(unsigned char *out, const unsigned char *in, int inLen) { word32 ret = (word32)-1; WOLFSSL_ENTER("wolfSSL_EVP_DecodeBlock"); if (out == NULL || in == NULL) return WOLFSSL_FATAL_ERROR; if (Base64_Decode(in, inLen, out, &ret) == 0) return (int)ret; else return WOLFSSL_FATAL_ERROR; } /* wolfSSL_EVP_EncodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX object * for the subsequent wolfSSL_EVP_EncodeUpdate. */ void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_EncodeInit"); /* clean up ctx */ if (ctx != NULL) { ctx->remaining = 0; XMEMSET(ctx->data, 0, sizeof(ctx->data)); } } /* wolfSSL_EVP_EncodeUpdate encodes the input data in 48-byte units * and outputs it to out. If less than 48 bytes of data remain, save it in * ctx. The data given in the subsequent wolfSSL_EVP_EncodeUpdate * is combined with the data stored in CTX and used for encoding. * Returns 1 on success, 0 on error. */ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char* out, int* outl, const unsigned char* in, int inl) { int cpysz; int res; word32 outsz = 0; WOLFSSL_ENTER("wolfSSL_EVP_EncodeUpdate"); if (ctx == NULL || out == NULL || in == NULL || outl == NULL) return 0; *outl = 0; /* if the remaining data exists in the ctx, add input data to them * to create a block(48bytes) for encoding */ if (ctx->remaining > 0 && inl > 0) { cpysz = min((BASE64_ENCODE_BLOCK_SIZE - ctx->remaining), inl); XMEMCPY(ctx->data + ctx->remaining, in, cpysz); ctx->remaining += cpysz; in += cpysz; inl -= cpysz; /* check if a block for encoding exists in ctx.data, if so encode it */ if (ctx->remaining >= BASE64_ENCODE_BLOCK_SIZE) { /* Base64_Encode asks the out buff size via the 4th param*/ outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, &outsz); if (res == 0) { ctx->remaining = 0; *outl = outsz; } else return 0; /* return with error */ } else { /* could not create a block */ *outl = 0; return 1; } } /* Here, there is no data left in ctx, so try processing the data of * the specified input data. */ while (inl >= BASE64_ENCODE_BLOCK_SIZE) { outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1;/* 64 byte and one for LF*/ res = Base64_Encode(in, BASE64_ENCODE_BLOCK_SIZE,out,&outsz); if (res == 0) { in += BASE64_ENCODE_BLOCK_SIZE; inl -= BASE64_ENCODE_BLOCK_SIZE; out += outsz; *outl += outsz; } else { *outl = 0; return 0; } } /* if remaining data exists, copy them into ctx for the next call*/ if (inl > 0) { XMEMSET(ctx->data, 0, sizeof(ctx->data)); XMEMCPY(ctx->data, in, inl); ctx->remaining = inl; } return 1; /* returns 1 on success, 0 on error */ } /* wolfSSL_EVP_EncodeFinal encodes data in ctx and outputs to out. */ void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char* out, int* outl) { word32 outsz = 0; int res; WOLFSSL_ENTER("wolfSSL_EVP_EncodeFinal"); if (outl == NULL) return; if (ctx == NULL || out == NULL) { *outl = 0; return; } if (ctx->remaining >= BASE64_ENCODE_RESULT_BLOCK_SIZE) { *outl = 0; return; } /* process remaining data in ctx */ outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; /* 64 byte and one for LF*/ res = Base64_Encode(ctx->data, ctx->remaining ,out, &outsz); if (res == 0) *outl = outsz; else *outl = 0; ctx->remaining = 0; XMEMSET(ctx->data, 0, sizeof(ctx->data)); return; } #endif /* WOLFSSL_BASE64_ENCODE */ #if defined(WOLFSSL_BASE64_DECODE) /* wolfSSL_EVP_DecodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX struct * for subsequent wolfSSL_EVP_DecodeUpdate. */ void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_DecodeInit"); /* clean up ctx */ if (ctx != NULL) { ctx->remaining = 0; XMEMSET(ctx->data, 0, sizeof(ctx->data)); } } /* wolfSSL_EVP_DecodeUpdate encodes the input data in 4-byte units * and outputs it to out. If less than 4 bytes of data remain, save it in * ctx. The data given in the subsequent wolfSSL_EVP_DecodeUpdate * is combined with the data stored in CTX and used for decoding. * Returns 1 or 0 on success, -1 on error. Return value 0 indicates that * clients should call wolfSSL_EVP_DecodeFinal as next call. */ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char* out, int* outl, const unsigned char* in, int inl) { word32 outsz = 0; word32 j = 0; word32 inLen; int res; int pad = 0; int i; int cpySz; unsigned char c; int pad3 = 0; int pad4 = 0; byte e[4]; WOLFSSL_ENTER("wolfSSL_EVP_DecodeUpdate"); if (outl == NULL) return -1; if (ctx == NULL || out == NULL || in == NULL) { *outl = 0; return -1; } if (inl == 0) { *outl = 0; return 1; } inLen = inl; *outl = 0; /* if the remaining data exist in the ctx, add input data to them to create a block(4bytes) for decoding*/ if ( ctx->remaining > 0 && inl > 0) { cpySz = min((BASE64_DECODE_BLOCK_SIZE - ctx->remaining), inl); for ( i = 0; cpySz > 0 && inLen > 0; i++) { if (Base64_SkipNewline(in, &inLen, &j) == ASN_INPUT_E) { return -1; /* detected an illegal char in input */ } c = in[j++]; if (c == '=') pad = 1; *(ctx->data + ctx->remaining + i) = c; inLen--; cpySz--; } outsz = sizeof(ctx->data); res = Base64_Decode( ctx->data, BASE64_DECODE_BLOCK_SIZE, out, &outsz); if (res == 0) { *outl += outsz; out += outsz; ctx->remaining = 0; XMEMSET(ctx->data, 0, sizeof(ctx->data)); } else { *outl = 0; return -1; /* return with error */ } } /* Base64_Decode is not a streaming process, so it processes * the input data and exits. If a line break or whitespace * character is found in the input data, it will be skipped, * but if the end point of the input data is reached as a result, * Base64_Decode will stop processing there. The data cleansing is * required before Base64_Decode so that the processing does not * stop within 4 bytes, which is the unit of Base64 decoding processing. * The logic that exists before calling Base64_Decode in a While Loop is * a data cleansing process that removes line breaks and whitespace. */ while (inLen > 3) { if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { if (res == BUFFER_E) { break; } else { *outl = 0; return -1; } } e[0] = in[j++]; if (e[0] == '\0') { break; } inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { if (res == BUFFER_E) { break; } else { *outl = 0; return -1; } } e[1] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { if (res == BUFFER_E) { break; } else { *outl = 0; return -1; } } e[2] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { if (res == BUFFER_E) { break; } else { *outl = 0; return -1; } } e[3] = in[j++]; inLen--; if (e[0] == '=') pad = 1; if (e[1] == '=') pad = 1; if (e[2] == '=') { pad = 1; pad3 = 1; } if (e[3] == '=') { pad = 1; pad4 = 1; } if (pad3 && !pad4) { *outl = 0; return -1; } /* decode four bytes */ outsz = sizeof(ctx->data); res = Base64_Decode( e, BASE64_DECODE_BLOCK_SIZE, out, &outsz); if (res < 0) { *outl = 0; return -1; } *outl += outsz; out += outsz; } /* copy left data to ctx */ if (inLen > 0) { XMEMSET(ctx->data, 0, sizeof(ctx->data)); i = 0; while (inLen > 0) { c = in[j++]; if (c== '\n' || c == '\r' || c == ' ') { inLen--; continue; } if (c == '=') { pad = 1; } ctx->data[i++] = c; ctx->remaining++; inLen--; } if (pad) return 0; /* indicates that clients should call DecodeFinal */ else return 1; } /* if the last data is '\n', remove it */ c = in[j - 1]; if (c == '\n') { c = (in[j - 2]); if (c == '=') return 0; else return 1; } if (c == '=') return 0; else return 1; } /* wolfSSL_EVP_DecodeFinal decode remaining data in ctx * to outputs to out. * Returns 1 on success, -1 on failure. */ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char* out, int* outl) { word32 outsz = 0; word32 inLen; word32 j = 0; int res; WOLFSSL_ENTER("wolfSSL_EVP_DecodeFinal"); if (outl == NULL) return -1; if (ctx == NULL || out == NULL ) { *outl = 0; return -1; } if (ctx->remaining > 0) { inLen = ctx->remaining; if ((res = Base64_SkipNewline(ctx->data, &inLen, &j)) != 0) { *outl = 0; if (res == BUFFER_E) /* means no valid data to decode in buffer */ return 1; /* returns as success with no output */ else return -1; } outsz = ctx->remaining; res = Base64_Decode(ctx->data, ctx->remaining, out, &outsz); if (res == 0) { *outl = outsz; return 1; } else { *outl = 0; return -1; } } else { *outl = 0; return 1; } } #endif /* WOLFSSL_BASE64_DECODE */ #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #endif /* WOLFSSL_EVP_INCLUDED */