mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-31 02:09:15 +01:00
We have users who need to debug errors coming out of libwolfssl in production, where --enable-debug isn't an option. Our error queue implementation is the solution, but our usage of WOLFSSL_ERROR isn't consistent. This commit greatly expands our usage of WOLFSSL_ERROR. There are too many error cases to tackle all at once, and not all error cases are particularly meaningful or likely to be hit in regular operation of the library. I've tried to focus on errors that users are likely to hit, and I've chosen to ignore things like the mountain of BUFFER_E and BAD_FUNC_ARG cases (for the most part). I've also tried to expand WOLFSSL_ERROR usage in files where we haven't been using it historically (e.g. aes.c), so the pattern is now there for other developers to follow. In order to prevent these additions from exploding the size of libwolfssl, they're all behind a new macro, WOLFSSL_ERROR_VERBOSE. If WOLFSSL_VERBOSE_ERRORS is defined, WOLFSSL_ERROR_VERBOSE just maps to WOLFSSL_ERROR.
714 lines
20 KiB
C
714 lines
20 KiB
C
/* wc_encrypt.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 <config.h>
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#include <wolfssl/wolfcrypt/aes.h>
|
|
#include <wolfssl/wolfcrypt/des3.h>
|
|
#include <wolfssl/wolfcrypt/hash.h>
|
|
#include <wolfssl/wolfcrypt/rc2.h>
|
|
#include <wolfssl/wolfcrypt/arc4.h>
|
|
#include <wolfssl/wolfcrypt/wc_encrypt.h>
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
#include <wolfssl/wolfcrypt/asn.h>
|
|
#include <wolfssl/wolfcrypt/coding.h>
|
|
#include <wolfssl/wolfcrypt/pwdbased.h>
|
|
#include <wolfssl/wolfcrypt/logging.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#if !defined(NO_AES) && defined(HAVE_AES_CBC)
|
|
#ifdef HAVE_AES_DECRYPT
|
|
int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz,
|
|
const byte* key, word32 keySz, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Aes* aes = NULL;
|
|
#else
|
|
Aes aes[1];
|
|
#endif
|
|
|
|
if (out == NULL || in == NULL || key == NULL || iv == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (aes == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
|
if (ret == 0) {
|
|
ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_AesCbcDecrypt(aes, out, in, inSz);
|
|
|
|
wc_AesFree(aes);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
#endif /* HAVE_AES_DECRYPT */
|
|
|
|
int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz,
|
|
const byte* key, word32 keySz, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Aes* aes;
|
|
#else
|
|
Aes aes[1];
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (aes == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
|
if (ret == 0) {
|
|
ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_AesCbcEncrypt(aes, out, in, inSz);
|
|
|
|
wc_AesFree(aes);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
#endif /* !NO_AES && HAVE_AES_CBC */
|
|
|
|
|
|
#if !defined(NO_DES3) && !defined(WOLFSSL_TI_CRYPT)
|
|
int wc_Des_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
|
|
const byte* key, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Des* des;
|
|
#else
|
|
Des des[1];
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (des == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_Des_SetKey(des, key, iv, DES_ENCRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_Des_CbcEncrypt(des, out, in, sz);
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
|
|
const byte* key, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Des* des;
|
|
#else
|
|
Des des[1];
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (des == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_Des_CbcDecrypt(des, out, in, sz);
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
|
|
const byte* key, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Des3* des3;
|
|
#else
|
|
Des3 des3[1];
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (des3 == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
|
|
if (ret == 0) {
|
|
ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_Des3_CbcEncrypt(des3, out, in, sz);
|
|
wc_Des3Free(des3);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
|
|
const byte* key, const byte* iv)
|
|
{
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Des3* des3;
|
|
#else
|
|
Des3 des3[1];
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (des3 == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
|
|
if (ret == 0) {
|
|
ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION);
|
|
if (ret == 0)
|
|
ret = wc_Des3_CbcDecrypt(des3, out, in, sz);
|
|
wc_Des3Free(des3);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* !NO_DES3 */
|
|
|
|
|
|
#if !defined(NO_ASN) && defined(WOLFSSL_ENCRYPTED_KEYS)
|
|
|
|
int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz,
|
|
const byte* password, int passwordSz, int hashType)
|
|
{
|
|
int ret = NOT_COMPILED_IN;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
byte* key = NULL;
|
|
#else
|
|
byte key[WC_MAX_SYM_KEY_SIZE];
|
|
#endif
|
|
|
|
(void)derSz;
|
|
(void)passwordSz;
|
|
(void)hashType;
|
|
|
|
if (der == NULL || password == NULL || info == NULL || info->keySz == 0) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
/* use file's salt for key derivation, hex decode first */
|
|
if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) {
|
|
WOLFSSL_ERROR_VERBOSE(BUFFER_E);
|
|
return BUFFER_E;
|
|
}
|
|
if (info->ivSz < PKCS5_SALT_SZ) {
|
|
WOLFSSL_ERROR_VERBOSE(BUFFER_E);
|
|
return BUFFER_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
if (key == NULL) {
|
|
return MEMORY_E;
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
|
wc_MemZero_Add("wc_BufferKeyDecrypt key", key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
|
|
(void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE);
|
|
|
|
#ifndef NO_PWDBASED
|
|
if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
|
|
info->keySz, hashType)) != 0) {
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
|
|
wc_MemZero_Check(key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_DES3
|
|
if (info->cipherType == WC_CIPHER_DES)
|
|
ret = wc_Des_CbcDecryptWithKey(der, der, derSz, key, info->iv);
|
|
if (info->cipherType == WC_CIPHER_DES3)
|
|
ret = wc_Des3_CbcDecryptWithKey(der, der, derSz, key, info->iv);
|
|
#endif /* NO_DES3 */
|
|
#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT)
|
|
if (info->cipherType == WC_CIPHER_AES_CBC)
|
|
ret = wc_AesCbcDecryptWithKey(der, der, derSz, key, info->keySz,
|
|
info->iv);
|
|
#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */
|
|
|
|
ForceZero(key, WC_MAX_SYM_KEY_SIZE);
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
|
|
wc_MemZero_Check(key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz,
|
|
const byte* password, int passwordSz, int hashType)
|
|
{
|
|
int ret = NOT_COMPILED_IN;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
byte* key = NULL;
|
|
#else
|
|
byte key[WC_MAX_SYM_KEY_SIZE];
|
|
#endif
|
|
|
|
(void)derSz;
|
|
(void)passwordSz;
|
|
(void)hashType;
|
|
|
|
if (der == NULL || password == NULL || info == NULL || info->keySz == 0 ||
|
|
info->ivSz < PKCS5_SALT_SZ) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
if (key == NULL) {
|
|
return MEMORY_E;
|
|
}
|
|
#endif /* WOLFSSL_SMALL_STACK */
|
|
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
|
wc_MemZero_Add("wc_BufferKeyDecrypt key", key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
|
|
(void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE);
|
|
|
|
#ifndef NO_PWDBASED
|
|
if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
|
|
info->keySz, hashType)) != 0) {
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
|
|
wc_MemZero_Check(key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_DES3
|
|
if (info->cipherType == WC_CIPHER_DES)
|
|
ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv);
|
|
if (info->cipherType == WC_CIPHER_DES3)
|
|
ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv);
|
|
#endif /* NO_DES3 */
|
|
#if !defined(NO_AES) && defined(HAVE_AES_CBC)
|
|
if (info->cipherType == WC_CIPHER_AES_CBC)
|
|
ret = wc_AesCbcEncryptWithKey(der, der, derSz, key, info->keySz,
|
|
info->iv);
|
|
#endif /* !NO_AES && HAVE_AES_CBC */
|
|
|
|
ForceZero(key, WC_MAX_SYM_KEY_SIZE);
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
|
|
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
|
|
wc_MemZero_Check(key, WC_MAX_SYM_KEY_SIZE);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* !NO_ASN && WOLFSSL_ENCRYPTED_KEYS */
|
|
|
|
|
|
#if !defined(NO_PWDBASED) && !defined(NO_ASN)
|
|
|
|
#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
|
|
/* Decrypt/Encrypt input in place from parameters based on id
|
|
*
|
|
* returns a negative value on fail case
|
|
*/
|
|
int wc_CryptKey(const char* password, int passwordSz, byte* salt,
|
|
int saltSz, int iterations, int id, byte* input,
|
|
int length, int version, byte* cbcIv, int enc, int shaOid)
|
|
{
|
|
int typeH = WC_HASH_TYPE_NONE;
|
|
int derivedLen = 0;
|
|
int ret = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
byte* key = NULL;
|
|
#else
|
|
byte key[PKCS_MAX_KEY_SIZE];
|
|
#endif
|
|
|
|
(void)input;
|
|
(void)length;
|
|
(void)enc;
|
|
|
|
WOLFSSL_ENTER("wc_CryptKey");
|
|
|
|
switch (id) {
|
|
#ifndef NO_DES3
|
|
#ifndef NO_MD5
|
|
case PBE_MD5_DES:
|
|
typeH = WC_MD5;
|
|
derivedLen = 16; /* may need iv for v1.5 */
|
|
break;
|
|
#endif
|
|
#ifndef NO_SHA
|
|
case PBE_SHA1_DES:
|
|
typeH = WC_SHA;
|
|
derivedLen = 16; /* may need iv for v1.5 */
|
|
break;
|
|
|
|
case PBE_SHA1_DES3:
|
|
switch(shaOid) {
|
|
case HMAC_SHA256_OID:
|
|
typeH = WC_SHA256;
|
|
derivedLen = 32;
|
|
break;
|
|
default:
|
|
typeH = WC_SHA;
|
|
derivedLen = 32; /* may need iv for v1.5 */
|
|
break;
|
|
}
|
|
break;
|
|
#endif /* !NO_SHA */
|
|
#endif /* !NO_DES3 */
|
|
#if !defined(NO_SHA) && !defined(NO_RC4)
|
|
case PBE_SHA1_RC4_128:
|
|
typeH = WC_SHA;
|
|
derivedLen = 16;
|
|
break;
|
|
#endif
|
|
#if defined(WOLFSSL_AES_256)
|
|
case PBE_AES256_CBC:
|
|
switch(shaOid) {
|
|
case HMAC_SHA256_OID:
|
|
typeH = WC_SHA256;
|
|
derivedLen = 32;
|
|
break;
|
|
#ifndef NO_SHA
|
|
default:
|
|
typeH = WC_SHA;
|
|
derivedLen = 32;
|
|
break;
|
|
#endif
|
|
}
|
|
break;
|
|
#endif /* WOLFSSL_AES_256 && !NO_SHA */
|
|
#if defined(WOLFSSL_AES_128)
|
|
case PBE_AES128_CBC:
|
|
switch(shaOid) {
|
|
case HMAC_SHA256_OID:
|
|
typeH = WC_SHA256;
|
|
derivedLen = 16;
|
|
break;
|
|
#ifndef NO_SHA
|
|
default:
|
|
typeH = WC_SHA;
|
|
derivedLen = 16;
|
|
break;
|
|
#endif
|
|
}
|
|
break;
|
|
#endif /* WOLFSSL_AES_128 && !NO_SHA */
|
|
#ifdef WC_RC2
|
|
case PBE_SHA1_40RC2_CBC:
|
|
typeH = WC_SHA;
|
|
derivedLen = 5;
|
|
break;
|
|
#endif
|
|
default:
|
|
WOLFSSL_MSG("Unknown/Unsupported encrypt/decrypt id");
|
|
(void)shaOid;
|
|
ret = ALGO_ID_E;
|
|
WOLFSSL_ERROR_VERBOSE(ret);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
if (ret == 0) {
|
|
key = (byte*)XMALLOC(PKCS_MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (key == NULL)
|
|
ret = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (ret == 0) {
|
|
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
|
wc_MemZero_Add("wc_CryptKey key", key, PKCS_MAX_KEY_SIZE);
|
|
#endif
|
|
|
|
switch (version) {
|
|
#ifndef NO_HMAC
|
|
case PKCS5v2:
|
|
ret = wc_PBKDF2(key, (byte*)password, passwordSz,
|
|
salt, saltSz, iterations, derivedLen, typeH);
|
|
break;
|
|
#endif
|
|
#ifndef NO_SHA
|
|
case PKCS5:
|
|
ret = wc_PBKDF1(key, (byte*)password, passwordSz,
|
|
salt, saltSz, iterations, derivedLen, typeH);
|
|
break;
|
|
#endif
|
|
#ifdef HAVE_PKCS12
|
|
case PKCS12v1:
|
|
{
|
|
int i, idx = 0;
|
|
byte unicodePasswd[MAX_UNICODE_SZ];
|
|
|
|
if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
|
|
ret = UNICODE_SIZE_E;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < passwordSz; i++) {
|
|
unicodePasswd[idx++] = 0x00;
|
|
unicodePasswd[idx++] = (byte)password[i];
|
|
}
|
|
/* add trailing NULL */
|
|
unicodePasswd[idx++] = 0x00;
|
|
unicodePasswd[idx++] = 0x00;
|
|
|
|
ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
|
|
iterations, derivedLen, typeH, 1);
|
|
if (id != PBE_SHA1_RC4_128) {
|
|
ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt,
|
|
saltSz, iterations, 8, typeH, 2);
|
|
}
|
|
break;
|
|
}
|
|
#endif /* HAVE_PKCS12 */
|
|
default:
|
|
WOLFSSL_MSG("Unknown/Unsupported PKCS version");
|
|
ret = ALGO_ID_E;
|
|
WOLFSSL_ERROR_VERBOSE(ret);
|
|
} /* switch (version) */
|
|
}
|
|
|
|
if (ret == 0) {
|
|
switch (id) {
|
|
#ifndef NO_DES3
|
|
#if !defined(NO_SHA) || !defined(NO_MD5)
|
|
case PBE_MD5_DES:
|
|
case PBE_SHA1_DES:
|
|
{
|
|
Des des;
|
|
byte* desIv = key + 8;
|
|
|
|
if (version == PKCS5v2 || version == PKCS12v1)
|
|
desIv = cbcIv;
|
|
|
|
if (enc) {
|
|
ret = wc_Des_SetKey(&des, key, desIv, DES_ENCRYPTION);
|
|
}
|
|
else {
|
|
ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION);
|
|
}
|
|
if (ret == 0) {
|
|
if (enc) {
|
|
wc_Des_CbcEncrypt(&des, input, input, length);
|
|
}
|
|
else {
|
|
wc_Des_CbcDecrypt(&des, input, input, length);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif /* !NO_SHA || !NO_MD5 */
|
|
|
|
#ifndef NO_SHA
|
|
case PBE_SHA1_DES3:
|
|
{
|
|
Des3 des;
|
|
byte* desIv = key + 24;
|
|
|
|
if (version == PKCS5v2 || version == PKCS12v1)
|
|
desIv = cbcIv;
|
|
|
|
ret = wc_Des3Init(&des, NULL, INVALID_DEVID);
|
|
if (ret != 0) {
|
|
break;
|
|
}
|
|
if (enc) {
|
|
ret = wc_Des3_SetKey(&des, key, desIv, DES_ENCRYPTION);
|
|
}
|
|
else {
|
|
ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION);
|
|
}
|
|
if (ret == 0) {
|
|
if (enc) {
|
|
ret = wc_Des3_CbcEncrypt(&des, input, input, length);
|
|
}
|
|
else {
|
|
ret = wc_Des3_CbcDecrypt(&des, input, input, length);
|
|
}
|
|
}
|
|
wc_Des3Free(&des);
|
|
break;
|
|
}
|
|
#endif /* !NO_SHA */
|
|
#endif
|
|
#if !defined(NO_RC4) && !defined(NO_SHA)
|
|
case PBE_SHA1_RC4_128:
|
|
{
|
|
Arc4 dec;
|
|
|
|
wc_Arc4SetKey(&dec, key, derivedLen);
|
|
wc_Arc4Process(&dec, input, input, length);
|
|
break;
|
|
}
|
|
#endif
|
|
#if !defined(NO_AES) && defined(HAVE_AES_CBC)
|
|
#ifdef WOLFSSL_AES_256
|
|
case PBE_AES256_CBC:
|
|
case PBE_AES128_CBC:
|
|
{
|
|
int free_aes;
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
Aes *aes;
|
|
aes = (Aes *)XMALLOC(sizeof *aes, NULL, DYNAMIC_TYPE_AES);
|
|
if (aes == NULL) {
|
|
ret = MEMORY_E;
|
|
break;
|
|
}
|
|
#else
|
|
Aes aes[1];
|
|
#endif
|
|
free_aes = 0;
|
|
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
|
if (ret == 0) {
|
|
free_aes = 1;
|
|
if (enc) {
|
|
ret = wc_AesSetKey(aes, key, derivedLen, cbcIv,
|
|
AES_ENCRYPTION);
|
|
}
|
|
else {
|
|
ret = wc_AesSetKey(aes, key, derivedLen, cbcIv,
|
|
AES_DECRYPTION);
|
|
}
|
|
}
|
|
if (ret == 0) {
|
|
if (enc)
|
|
ret = wc_AesCbcEncrypt(aes, input, input, length);
|
|
else
|
|
ret = wc_AesCbcDecrypt(aes, input, input, length);
|
|
}
|
|
if (free_aes)
|
|
wc_AesFree(aes);
|
|
ForceZero(aes, sizeof(Aes));
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
|
|
#endif
|
|
break;
|
|
}
|
|
#endif /* WOLFSSL_AES_256 */
|
|
#endif /* !NO_AES && HAVE_AES_CBC */
|
|
#ifdef WC_RC2
|
|
case PBE_SHA1_40RC2_CBC:
|
|
{
|
|
Rc2 rc2;
|
|
/* effective key size for RC2-40-CBC is 40 bits */
|
|
ret = wc_Rc2SetKey(&rc2, key, derivedLen, cbcIv, 40);
|
|
if (ret == 0) {
|
|
if (enc)
|
|
ret = wc_Rc2CbcEncrypt(&rc2, input, input, length);
|
|
else
|
|
ret = wc_Rc2CbcDecrypt(&rc2, input, input, length);
|
|
}
|
|
if (ret == 0) {
|
|
ForceZero(&rc2, sizeof(Rc2));
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
default:
|
|
WOLFSSL_MSG("Unknown/Unsupported encrypt/decryption algorithm");
|
|
ret = ALGO_ID_E;
|
|
WOLFSSL_ERROR_VERBOSE(ret);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
if (key != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(key, PKCS_MAX_KEY_SIZE);
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
|
|
wc_MemZero_Check(key, PKCS_MAX_KEY_SIZE);
|
|
#endif
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
|
|
#endif /* !NO_PWDBASED && !NO_ASN */
|