#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#ifndef WOLFSSL_SSL_CRYPTO_INCLUDED
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning ssl_crypto.c does not need to be compiled separately from ssl.c
#endif
#else
#ifdef OPENSSL_EXTRA
#ifndef NO_MD4
void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4)
{
WOLFSSL_ASSERT_SIZEOF_GE(md4->buffer, wc_Md4);
WOLFSSL_ENTER("MD4_Init");
wc_InitMd4((wc_Md4*)md4);
}
void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data,
unsigned long len)
{
WOLFSSL_ENTER("MD4_Update");
wc_Md4Update((wc_Md4*)md4, (const byte*)data, (word32)len);
}
void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
{
WOLFSSL_ENTER("MD4_Final");
wc_Md4Final((wc_Md4*)md4, digest);
}
#endif
#endif
#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL)
#ifndef NO_MD5
int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_MD5_CTX, wc_Md5);
WOLFSSL_ENTER("MD5_Init");
return wc_InitMd5((wc_Md5*)md5) == 0;
}
int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("MD5_Update");
return wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz) == 0;
}
int wolfSSL_MD5_Final(byte* output, WOLFSSL_MD5_CTX* md5)
{
int ret;
WOLFSSL_ENTER("MD5_Final");
ret = (wc_Md5Final((wc_Md5*)md5, output) == 0);
wc_Md5Free((wc_Md5*)md5);
return ret;
}
int wolfSSL_MD5_Transform(WOLFSSL_MD5_CTX* md5, const unsigned char* data)
{
WOLFSSL_ENTER("MD5_Transform");
#if defined(BIG_ENDIAN_ORDER)
if ((md5 != NULL) && (data != NULL)) {
ByteReverseWords((word32*)data, (word32*)data, WC_MD5_BLOCK_SIZE);
}
#endif
return wc_Md5Transform((wc_Md5*)md5, data) == 0;
}
unsigned char* wolfSSL_MD5(const unsigned char* data, size_t len,
unsigned char* hash)
{
static unsigned char dgst[WC_MD5_DIGEST_SIZE];
WOLFSSL_ENTER("wolfSSL_MD5");
if (hash == NULL) {
hash = dgst;
}
if (wc_Md5Hash(data, (word32)len, hash) != 0) {
WOLFSSL_MSG("wc_Md5Hash error");
hash = NULL;
}
return hash;
}
#endif
#ifndef NO_SHA
int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA_CTX, wc_Sha);
WOLFSSL_ENTER("SHA_Init");
return wc_InitSha((wc_Sha*)sha) == 0;
}
int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA_Update");
return wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz) == 0;
}
int wolfSSL_SHA_Final(byte* output, WOLFSSL_SHA_CTX* sha)
{
int ret;
WOLFSSL_ENTER("SHA_Final");
ret = (wc_ShaFinal((wc_Sha*)sha, output) == 0);
wc_ShaFree((wc_Sha*)sha);
return ret;
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
int wolfSSL_SHA_Transform(WOLFSSL_SHA_CTX* sha, const unsigned char* data)
{
WOLFSSL_ENTER("SHA_Transform");
#if defined(LITTLE_ENDIAN_ORDER)
if ((sha != NULL) && (data != NULL)) {
ByteReverseWords((word32*)data, (word32*)data, WC_SHA_BLOCK_SIZE);
}
#endif
return wc_ShaTransform((wc_Sha*)sha, data) == 0;
}
#endif
int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
{
WOLFSSL_ENTER("SHA1_Init");
return wolfSSL_SHA_Init(sha);
}
int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA1_Update");
return wolfSSL_SHA_Update(sha, input, sz);
}
int wolfSSL_SHA1_Final(byte* output, WOLFSSL_SHA_CTX* sha)
{
WOLFSSL_ENTER("SHA1_Final");
return wolfSSL_SHA_Final(output, sha);
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
int wolfSSL_SHA1_Transform(WOLFSSL_SHA_CTX* sha, const unsigned char* data)
{
WOLFSSL_ENTER("SHA1_Transform");
return wolfSSL_SHA_Transform(sha, data);
}
#endif
#endif
#ifndef NO_SHA256
#ifdef WOLFSSL_SHA224
int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha224)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA224_CTX, wc_Sha224);
WOLFSSL_ENTER("SHA224_Init");
return wc_InitSha224((wc_Sha224*)sha224) == 0;
}
int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha224, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA224_Update");
return wc_Sha224Update((wc_Sha224*)sha224, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA224_Final(byte* output, WOLFSSL_SHA224_CTX* sha224)
{
int ret;
WOLFSSL_ENTER("SHA224_Final");
ret = (wc_Sha224Final((wc_Sha224*)sha224, output) == 0);
wc_Sha224Free((wc_Sha224*)sha224);
return ret;
}
#endif
int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA256_CTX, wc_Sha256);
WOLFSSL_ENTER("SHA256_Init");
return wc_InitSha256((wc_Sha256*)sha256) == 0;
}
int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha256, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA256_Update");
return wc_Sha256Update((wc_Sha256*)sha256, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA256_Final(byte* output, WOLFSSL_SHA256_CTX* sha256)
{
int ret;
WOLFSSL_ENTER("SHA256_Final");
ret = (wc_Sha256Final((wc_Sha256*)sha256, output) == 0);
wc_Sha256Free((wc_Sha256*)sha256);
return ret;
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
!defined(WOLFSSL_DEVCRYPTO_HASH) && !defined(WOLFSSL_AFALG_HASH) && \
!defined(WOLFSSL_KCAPI_HASH)
int wolfSSL_SHA256_Transform(WOLFSSL_SHA256_CTX* sha256,
const unsigned char* data)
{
WOLFSSL_ENTER("SHA256_Transform");
#if defined(LITTLE_ENDIAN_ORDER)
if ((sha256 != NULL) && (data != NULL)) {
ByteReverseWords((word32*)data, (word32*)data, WC_SHA256_BLOCK_SIZE);
}
#endif
return wc_Sha256Transform((wc_Sha256*)sha256, data) == 0;
}
#endif
#endif
#ifdef WOLFSSL_SHA384
int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha384)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA384_CTX, wc_Sha384);
WOLFSSL_ENTER("SHA384_Init");
return wc_InitSha384((wc_Sha384*)sha384) == 0;
}
int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha384, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA384_Update");
return wc_Sha384Update((wc_Sha384*)sha384, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA384_Final(byte* output, WOLFSSL_SHA384_CTX* sha384)
{
int ret;
WOLFSSL_ENTER("SHA384_Final");
ret = (wc_Sha384Final((wc_Sha384*)sha384, output) == 0);
wc_Sha384Free((wc_Sha384*)sha384);
return ret;
}
#endif
#ifdef WOLFSSL_SHA512
int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha512)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA512_CTX, wc_Sha512);
WOLFSSL_ENTER("SHA512_Init");
return wc_InitSha512((wc_Sha512*)sha512) == 0;
}
int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha512, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA512_Update");
return wc_Sha512Update((wc_Sha512*)sha512, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA512_Final(byte* output, WOLFSSL_SHA512_CTX* sha512)
{
int ret;
WOLFSSL_ENTER("SHA512_Final");
ret = (wc_Sha512Final((wc_Sha512*)sha512, output) == 0);
wc_Sha512Free((wc_Sha512*)sha512);
return ret;
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
!defined(WOLFSSL_KCAPI_HASH)
int wolfSSL_SHA512_Transform(WOLFSSL_SHA512_CTX* sha512,
const unsigned char* data)
{
WOLFSSL_ENTER("SHA512_Transform");
return wc_Sha512Transform((wc_Sha512*)sha512, data) == 0;
}
#endif
#if !defined(WOLFSSL_NOSHA512_224) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
int wolfSSL_SHA512_224_Init(WOLFSSL_SHA512_224_CTX* sha512)
{
WOLFSSL_ENTER("SHA512_224_Init");
return wc_InitSha512_224((wc_Sha512*)sha512) == 0;
}
int wolfSSL_SHA512_224_Update(WOLFSSL_SHA512_224_CTX* sha512, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA512_224_Update");
return wc_Sha512_224Update((wc_Sha512*)sha512, (const byte*)input,
(word32)sz) == 0;
}
int wolfSSL_SHA512_224_Final(byte* output, WOLFSSL_SHA512_224_CTX* sha512)
{
int ret;
WOLFSSL_ENTER("SHA512_224_Final");
ret = (wc_Sha512_224Final((wc_Sha512*)sha512, output) == 0);
wc_Sha512_224Free((wc_Sha512*)sha512);
return ret;
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
int wolfSSL_SHA512_224_Transform(WOLFSSL_SHA512_CTX* sha512,
const unsigned char* data)
{
WOLFSSL_ENTER("SHA512_224_Transform");
return wc_Sha512_224Transform((wc_Sha512*)sha512, data) == 0;
}
#endif
#endif
#if !defined(WOLFSSL_NOSHA512_256) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
int wolfSSL_SHA512_256_Init(WOLFSSL_SHA512_256_CTX* sha)
{
WOLFSSL_ENTER("SHA512_256_Init");
return wc_InitSha512_256((wc_Sha512*)sha) == 0;
}
int wolfSSL_SHA512_256_Update(WOLFSSL_SHA512_256_CTX* sha512, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA512_256_Update");
return wc_Sha512_256Update((wc_Sha512*)sha512, (const byte*)input,
(word32)sz) == 0;
}
int wolfSSL_SHA512_256_Final(byte* output, WOLFSSL_SHA512_256_CTX* sha512)
{
int ret;
WOLFSSL_ENTER("SHA512_256_Final");
ret = (wc_Sha512_256Final((wc_Sha512*)sha512, output) == 0);
wc_Sha512_224Free((wc_Sha512*)sha512);
return ret;
}
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
int wolfSSL_SHA512_256_Transform(WOLFSSL_SHA512_CTX* sha512,
const unsigned char* data)
{
WOLFSSL_ENTER("SHA512_256_Transform");
return wc_Sha512_256Transform((wc_Sha512*)sha512, data) == 0;
}
#endif
#endif
#endif
#ifdef WOLFSSL_SHA3
#ifndef WOLFSSL_NOSHA3_224
int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX* sha3_224)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA3_224_CTX, wc_Sha3);
WOLFSSL_ENTER("SHA3_224_Init");
return wc_InitSha3_224((wc_Sha3*)sha3_224, NULL, INVALID_DEVID) == 0;
}
int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX* sha3, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA3_224_Update");
return wc_Sha3_224_Update((wc_Sha3*)sha3, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA3_224_Final(byte* output, WOLFSSL_SHA3_224_CTX* sha3)
{
int ret;
WOLFSSL_ENTER("SHA3_224_Final");
ret = (wc_Sha3_224_Final((wc_Sha3*)sha3, output) == 0);
wc_Sha3_224_Free((wc_Sha3*)sha3);
return ret;
}
#endif
#ifndef WOLFSSL_NOSHA3_256
int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX* sha3_256)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA3_256_CTX, wc_Sha3);
WOLFSSL_ENTER("SHA3_256_Init");
return wc_InitSha3_256((wc_Sha3*)sha3_256, NULL, INVALID_DEVID) == 0;
}
int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX* sha3, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA3_256_Update");
return wc_Sha3_256_Update((wc_Sha3*)sha3, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA3_256_Final(byte* output, WOLFSSL_SHA3_256_CTX* sha3)
{
int ret;
WOLFSSL_ENTER("SHA3_256_Final");
ret = (wc_Sha3_256_Final((wc_Sha3*)sha3, output) == 0);
wc_Sha3_256_Free((wc_Sha3*)sha3);
return ret;
}
#endif
#ifndef WOLFSSL_NOSHA3_384
int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX* sha3_384)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA3_384_CTX, wc_Sha3);
WOLFSSL_ENTER("SHA3_384_Init");
return wc_InitSha3_384((wc_Sha3*)sha3_384, NULL, INVALID_DEVID) == 0;
}
int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX* sha3, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA3_384_Update");
return wc_Sha3_384_Update((wc_Sha3*)sha3, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA3_384_Final(byte* output, WOLFSSL_SHA3_384_CTX* sha3)
{
int ret;
WOLFSSL_ENTER("SHA3_384_Final");
ret = (wc_Sha3_384_Final((wc_Sha3*)sha3, output) == 0);
wc_Sha3_384_Free((wc_Sha3*)sha3);
return ret;
}
#endif
#ifndef WOLFSSL_NOSHA3_512
int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX* sha3_512)
{
WOLFSSL_ASSERT_SIZEOF_GE(WOLFSSL_SHA3_512_CTX, wc_Sha3);
WOLFSSL_ENTER("SHA3_512_Init");
return wc_InitSha3_512((wc_Sha3*)sha3_512, NULL, INVALID_DEVID) == 0;
}
int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX* sha3, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA3_512_Update");
return wc_Sha3_512_Update((wc_Sha3*)sha3, (const byte*)input, (word32)sz)
== 0;
}
int wolfSSL_SHA3_512_Final(byte* output, WOLFSSL_SHA3_512_CTX* sha3)
{
int ret;
WOLFSSL_ENTER("SHA3_512_Final");
ret = (wc_Sha3_512_Final((wc_Sha3*)sha3, output) == 0);
wc_Sha3_512_Free((wc_Sha3*)sha3);
return ret;
}
#endif
#endif
#endif
#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
defined(WOLFSSL_HAPROXY)
#ifndef NO_SHA
unsigned char* wolfSSL_SHA1(const unsigned char* data, size_t len,
unsigned char* hash)
{
static byte dgst[WC_SHA_DIGEST_SIZE];
WC_DECLARE_VAR(sha, wc_Sha, 1, 0);
int ret = 0;
WOLFSSL_ENTER("wolfSSL_SHA1");
if (hash == NULL) {
WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA1 IS NOT "
"THREAD SAFE WHEN hash == NULL");
hash = dgst;
}
WC_ALLOC_VAR_EX(sha, wc_Sha, 1, NULL, DYNAMIC_TYPE_DIGEST,
ret=MEMORY_E);
if (ret == 0) {
ret = wc_InitSha_ex(sha, NULL, INVALID_DEVID);
if (ret != 0) {
WOLFSSL_MSG("SHA1 Init failed");
hash = NULL;
}
}
if (ret == 0) {
ret = wc_ShaUpdate(sha, (const byte*)data, (word32)len);
if (ret != 0) {
WOLFSSL_MSG("SHA1 Update failed");
hash = NULL;
}
if (ret == 0) {
ret = wc_ShaFinal(sha, hash);
if (ret != 0) {
WOLFSSL_MSG("SHA1 Final failed");
hash = NULL;
}
}
wc_ShaFree(sha);
}
WC_FREE_VAR_EX(sha, NULL, DYNAMIC_TYPE_DIGEST);
return hash;
}
#endif
#ifdef WOLFSSL_SHA224
unsigned char* wolfSSL_SHA224(const unsigned char* data, size_t len,
unsigned char* hash)
{
static byte dgst[WC_SHA224_DIGEST_SIZE];
WC_DECLARE_VAR(sha224, wc_Sha224, 1, 0);
int ret = 0;
WOLFSSL_ENTER("wolfSSL_SHA224");
if (hash == NULL) {
WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA224 IS NOT "
"THREAD SAFE WHEN hash == NULL");
hash = dgst;
}
WC_ALLOC_VAR_EX(sha224, wc_Sha224, 1, NULL, DYNAMIC_TYPE_DIGEST,
ret=MEMORY_E);
if (ret == 0) {
ret = wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
if (ret != 0) {
WOLFSSL_MSG("SHA224 Init failed");
hash = NULL;
}
}
if (ret == 0) {
ret = wc_Sha224Update(sha224, (const byte*)data, (word32)len);
if (ret != 0) {
WOLFSSL_MSG("SHA224 Update failed");
hash = NULL;
}
if (ret == 0) {
ret = wc_Sha224Final(sha224, hash);
if (ret != 0) {
WOLFSSL_MSG("SHA224 Final failed");
hash = NULL;
}
}
wc_Sha224Free(sha224);
}
WC_FREE_VAR_EX(sha224, NULL, DYNAMIC_TYPE_DIGEST);
return hash;
}
#endif
#ifndef NO_SHA256
unsigned char* wolfSSL_SHA256(const unsigned char* data, size_t len,
unsigned char* hash)
{
static byte dgst[WC_SHA256_DIGEST_SIZE];
WC_DECLARE_VAR(sha256, wc_Sha256, 1, 0);
int ret = 0;
WOLFSSL_ENTER("wolfSSL_SHA256");
if (hash == NULL) {
WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA256 IS NOT "
"THREAD SAFE WHEN hash == NULL");
hash = dgst;
}
WC_ALLOC_VAR_EX(sha256, wc_Sha256, 1, NULL, DYNAMIC_TYPE_DIGEST,
ret=MEMORY_E);
if (ret == 0) {
ret = wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
if (ret != 0) {
WOLFSSL_MSG("SHA256 Init failed");
hash = NULL;
}
}
if (ret == 0) {
ret = wc_Sha256Update(sha256, (const byte*)data, (word32)len);
if (ret != 0) {
WOLFSSL_MSG("SHA256 Update failed");
hash = NULL;
}
if (ret == 0) {
ret = wc_Sha256Final(sha256, hash);
if (ret != 0) {
WOLFSSL_MSG("SHA256 Final failed");
hash = NULL;
}
}
wc_Sha256Free(sha256);
}
WC_FREE_VAR_EX(sha256, NULL, DYNAMIC_TYPE_DIGEST);
return hash;
}
#endif
#ifdef WOLFSSL_SHA384
unsigned char* wolfSSL_SHA384(const unsigned char* data, size_t len,
unsigned char* hash)
{
static byte dgst[WC_SHA384_DIGEST_SIZE];
WC_DECLARE_VAR(sha384, wc_Sha384, 1, 0);
int ret = 0;
WOLFSSL_ENTER("wolfSSL_SHA384");
if (hash == NULL) {
WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA384 IS NOT "
"THREAD SAFE WHEN hash == NULL");
hash = dgst;
}
WC_ALLOC_VAR_EX(sha384, wc_Sha384, 1, NULL, DYNAMIC_TYPE_DIGEST,
ret=MEMORY_E);
if (ret == 0) {
ret = wc_InitSha384_ex(sha384, NULL, INVALID_DEVID);
if (ret != 0) {
WOLFSSL_MSG("SHA384 Init failed");
hash = NULL;
}
}
if (ret == 0) {
ret = wc_Sha384Update(sha384, (const byte*)data, (word32)len);
if (ret != 0) {
WOLFSSL_MSG("SHA384 Update failed");
hash = NULL;
}
if (ret == 0) {
ret = wc_Sha384Final(sha384, hash);
if (ret != 0) {
WOLFSSL_MSG("SHA384 Final failed");
hash = NULL;
}
}
wc_Sha384Free(sha384);
}
WC_FREE_VAR_EX(sha384, NULL, DYNAMIC_TYPE_DIGEST);
return hash;
}
#endif
#if defined(WOLFSSL_SHA512)
unsigned char* wolfSSL_SHA512(const unsigned char* data, size_t len,
unsigned char* hash)
{
static byte dgst[WC_SHA512_DIGEST_SIZE];
WC_DECLARE_VAR(sha512, wc_Sha512, 1, 0);
int ret = 0;
WOLFSSL_ENTER("wolfSSL_SHA512");
if (hash == NULL) {
WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA512 IS NOT "
"THREAD SAFE WHEN hash == NULL");
hash = dgst;
}
WC_ALLOC_VAR_EX(sha512, wc_Sha512, 1, NULL, DYNAMIC_TYPE_DIGEST,
ret=MEMORY_E);
if (ret == 0) {
ret = wc_InitSha512_ex(sha512, NULL, INVALID_DEVID);
if (ret != 0) {
WOLFSSL_MSG("SHA512 Init failed");
hash = NULL;
}
}
if (ret == 0) {
ret = wc_Sha512Update(sha512, (const byte*)data, (word32)len);
if (ret != 0) {
WOLFSSL_MSG("SHA512 Update failed");
hash = NULL;
}
if (ret == 0) {
ret = wc_Sha512Final(sha512, hash);
if (ret != 0) {
WOLFSSL_MSG("SHA512 Final failed");
hash = NULL;
}
}
wc_Sha512Free(sha512);
}
WC_FREE_VAR_EX(sha512, NULL, DYNAMIC_TYPE_DIGEST);
return hash;
}
#endif
#endif
#define _HMAC_Init _InitHmac
#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
int wolfSSL_HmacCopy(Hmac* dst, Hmac* src)
{
void* heap;
int ret = 1;
#ifndef HAVE_FIPS
heap = src->heap;
#else
heap = NULL;
#endif
if (wc_HmacInit(dst, heap, 0) != 0) {
ret = 0;
}
if (ret == 1) {
int rc;
switch (src->macType) {
#ifndef NO_MD5
case WC_MD5:
rc = wc_Md5Copy(&src->hash.md5, &dst->hash.md5);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Md5Copy(&src->i_hash.md5, &dst->i_hash.md5);
}
if (rc == 0) {
rc = wc_Md5Copy(&src->o_hash.md5, &dst->o_hash.md5);
}
#endif
break;
#endif
#ifndef NO_SHA
case WC_SHA:
rc = wc_ShaCopy(&src->hash.sha, &dst->hash.sha);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_ShaCopy(&src->i_hash.sha, &dst->i_hash.sha);
}
if (rc == 0) {
rc = wc_ShaCopy(&src->o_hash.sha, &dst->o_hash.sha);
}
#endif
break;
#endif
#ifdef WOLFSSL_SHA224
case WC_SHA224:
rc = wc_Sha224Copy(&src->hash.sha224, &dst->hash.sha224);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha224Copy(&src->i_hash.sha224, &dst->i_hash.sha224);
}
if (rc == 0) {
rc = wc_Sha224Copy(&src->o_hash.sha224, &dst->o_hash.sha224);
}
#endif
break;
#endif
#ifndef NO_SHA256
case WC_SHA256:
rc = wc_Sha256Copy(&src->hash.sha256, &dst->hash.sha256);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha256Copy(&src->i_hash.sha256, &dst->i_hash.sha256);
}
if (rc == 0) {
rc = wc_Sha256Copy(&src->o_hash.sha256, &dst->o_hash.sha256);
}
#endif
break;
#endif
#ifdef WOLFSSL_SHA384
case WC_SHA384:
rc = wc_Sha384Copy(&src->hash.sha384, &dst->hash.sha384);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha384Copy(&src->i_hash.sha384, &dst->i_hash.sha384);
}
if (rc == 0) {
rc = wc_Sha384Copy(&src->o_hash.sha384, &dst->o_hash.sha384);
}
#endif
break;
#endif
#ifdef WOLFSSL_SHA512
case WC_SHA512:
rc = wc_Sha512Copy(&src->hash.sha512, &dst->hash.sha512);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha512Copy(&src->i_hash.sha512, &dst->i_hash.sha512);
}
if (rc == 0) {
rc = wc_Sha512Copy(&src->o_hash.sha512, &dst->o_hash.sha512);
}
#endif
break;
#endif
#ifdef WOLFSSL_SHA3
#ifndef WOLFSSL_NOSHA3_224
case WC_SHA3_224:
rc = wc_Sha3_224_Copy(&src->hash.sha3, &dst->hash.sha3);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha3_224_Copy(&src->i_hash.sha3, &dst->i_hash.sha3);
}
if (rc == 0) {
rc = wc_Sha3_224_Copy(&src->o_hash.sha3, &dst->o_hash.sha3);
}
#endif
break;
#endif
#ifndef WOLFSSL_NOSHA3_256
case WC_SHA3_256:
rc = wc_Sha3_256_Copy(&src->hash.sha3, &dst->hash.sha3);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha3_256_Copy(&src->i_hash.sha3, &dst->i_hash.sha3);
}
if (rc == 0) {
rc = wc_Sha3_256_Copy(&src->o_hash.sha3, &dst->o_hash.sha3);
}
#endif
break;
#endif
#ifndef WOLFSSL_NOSHA3_384
case WC_SHA3_384:
rc = wc_Sha3_384_Copy(&src->hash.sha3, &dst->hash.sha3);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha3_384_Copy(&src->i_hash.sha3, &dst->i_hash.sha3);
}
if (rc == 0) {
rc = wc_Sha3_384_Copy(&src->o_hash.sha3, &dst->o_hash.sha3);
}
#endif
break;
#endif
#ifndef WOLFSSL_NOSHA3_512
case WC_SHA3_512:
rc = wc_Sha3_512_Copy(&src->hash.sha3, &dst->hash.sha3);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sha3_512_Copy(&src->i_hash.sha3, &dst->i_hash.sha3);
}
if (rc == 0) {
rc = wc_Sha3_512_Copy(&src->o_hash.sha3, &dst->o_hash.sha3);
}
#endif
break;
#endif
#endif
#ifdef WOLFSSL_SM3
case WC_SM3:
rc = wc_Sm3Copy(&src->hash.sm3, &dst->hash.sm3);
#ifdef WOLFSSL_HMAC_COPY_HASH
if (rc == 0) {
rc = wc_Sm3Copy(&src->i_hash.sm3, &dst->i_hash.sm3);
}
if (rc == 0) {
rc = wc_Sm3Copy(&src->o_hash.sm3, &dst->o_hash.sm3);
}
#endif
break;
#endif
default:
rc = BAD_FUNC_ARG;
}
if (rc != 0) {
ret = 0;
}
}
if (ret == 1) {
XMEMCPY((byte*)dst->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE);
XMEMCPY((byte*)dst->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE);
XMEMCPY((byte*)dst->innerHash, (byte*)src->innerHash,
WC_MAX_DIGEST_SIZE);
#ifndef HAVE_FIPS
dst->heap = heap;
#endif
dst->macType = src->macType;
dst->innerHashKeyed = src->innerHashKeyed;
#ifdef WOLFSSL_ASYNC_CRYPT
XMEMCPY(&dst->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV));
dst->keyLen = src->keyLen;
#ifdef HAVE_CAVIUM
dst->data = (byte*)XMALLOC(src->dataLen, dst->heap, DYNAMIC_TYPE_HMAC);
if (dst->data == NULL) {
ret = BUFFER_E;
}
else {
XMEMCPY(dst->data, src->data, src->dataLen);
dst->dataLen = src->dataLen;
}
#endif
#endif
}
return ret;
}
WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void)
{
WOLFSSL_HMAC_CTX* hmac_ctx;
hmac_ctx = (WOLFSSL_HMAC_CTX*)XMALLOC(sizeof(WOLFSSL_HMAC_CTX), NULL,
DYNAMIC_TYPE_OPENSSL);
if (hmac_ctx != NULL) {
wolfSSL_HMAC_CTX_Init(hmac_ctx);
}
return hmac_ctx;
}
int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
{
WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
if (ctx != NULL) {
XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
}
return 1;
}
int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* dst, WOLFSSL_HMAC_CTX* src)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
if ((dst == NULL) || (src == NULL)) {
ret = 0;
}
if (ret == 1) {
dst->type = src->type;
XMEMCPY((byte *)&dst->save_ipad, (byte *)&src->hmac.ipad,
WC_HMAC_BLOCK_SIZE);
XMEMCPY((byte *)&dst->save_opad, (byte *)&src->hmac.opad,
WC_HMAC_BLOCK_SIZE);
ret = wolfSSL_HmacCopy(&dst->hmac, &src->hmac);
}
return ret;
}
void wolfSSL_HMAC_CTX_cleanup(WOLFSSL_HMAC_CTX* ctx)
{
if (ctx != NULL) {
wolfSSL_HMAC_cleanup(ctx);
}
}
void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx)
{
if (ctx != NULL) {
wolfSSL_HMAC_CTX_cleanup(ctx);
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
const WOLFSSL_EVP_MD* wolfSSL_HMAC_CTX_get_md(const WOLFSSL_HMAC_CTX* ctx)
{
const WOLFSSL_EVP_MD* ret = NULL;
if (ctx != NULL) {
ret = wolfSSL_macType2EVP_md((enum wc_HashType)ctx->type);
}
return ret;
}
int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int keySz,
const WOLFSSL_EVP_MD* type, WOLFSSL_ENGINE* e)
{
WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
(void)e;
return wolfSSL_HMAC_Init(ctx, key, keySz, type);
}
int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
const WOLFSSL_EVP_MD* type)
{
int ret = 1;
void* heap = NULL;
int rc;
WOLFSSL_MSG("wolfSSL_HMAC_Init");
if (ctx == NULL) {
WOLFSSL_MSG("no ctx on init");
ret = 0;
}
if ((ret == 1) && (type == NULL) && (ctx->type == (int)WC_HASH_TYPE_NONE)) {
WOLFSSL_MSG("no hash type");
ret = 0;
}
if ((ret == 1) && (key == NULL) &&
(ctx->hmac.macType == (int)WC_HASH_TYPE_NONE)) {
WOLFSSL_MSG("wolfCrypt hash not setup");
ret = 0;
}
if (ret == 1) {
#ifndef HAVE_FIPS
heap = ctx->hmac.heap;
#endif
if (type != NULL) {
WOLFSSL_MSG("init has type");
if (wolfssl_evp_md_to_hash_type(type, &ctx->type) != 0) {
WOLFSSL_MSG("bad init type");
ret = 0;
}
}
}
if (ret == 1) {
int inited = (ctx->hmac.macType != WC_HASH_TYPE_NONE);
if (inited) {
wc_HmacFree(&ctx->hmac);
}
rc = wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID);
if (rc != 0) {
ret = 0;
}
}
if ((ret == 1) && (key != NULL)) {
rc = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
(word32)keylen);
if (rc != 0) {
WOLFSSL_MSG("hmac set key error");
WOLFSSL_ERROR(rc);
wc_HmacFree(&ctx->hmac);
ret = 0;
}
if (ret == 1) {
XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
WC_HMAC_BLOCK_SIZE);
XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
WC_HMAC_BLOCK_SIZE);
}
}
else if (ret == 1) {
WOLFSSL_MSG("recover hmac");
ctx->hmac.macType = (byte)ctx->type;
ctx->hmac.innerHashKeyed = 0;
XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
WC_HMAC_BLOCK_SIZE);
XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
WC_HMAC_BLOCK_SIZE);
#ifdef WOLFSSL_HMAC_COPY_HASH
rc = _HmacInitIOHashes(&ctx->hmac);
if (rc != 0) {
WOLFSSL_MSG("hmac init i_hash/o_hash error");
WOLFSSL_ERROR(rc);
ret = 0;
}
if (ret == 1)
#endif
{
rc = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap);
if (rc != 0) {
WOLFSSL_MSG("hmac init error");
WOLFSSL_ERROR(rc);
ret = 0;
}
}
}
return ret;
}
int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
int len)
{
int ret = 1;
WOLFSSL_MSG("wolfSSL_HMAC_Update");
if (ctx == NULL) {
WOLFSSL_MSG("no ctx");
ret = 0;
}
if ((ret == 1) && (data != NULL) && (len > 0)) {
int rc;
WOLFSSL_MSG("updating hmac");
rc = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
if (rc != 0){
WOLFSSL_MSG("hmac update error");
ret = 0;
}
}
return ret;
}
int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
unsigned int* len)
{
int ret = 1;
int rc;
WOLFSSL_MSG("wolfSSL_HMAC_Final");
if ((ctx == NULL) || (hash == NULL)) {
WOLFSSL_MSG("invalid parameter");
ret = 0;
}
if (ret == 1) {
WOLFSSL_MSG("final hmac");
rc = wc_HmacFinal(&ctx->hmac, hash);
if (rc != 0){
WOLFSSL_MSG("final hmac error");
ret = 0;
}
}
if ((ret == 1) && (len != NULL)) {
WOLFSSL_MSG("setting output len");
*len = wolfssl_mac_len((unsigned char)ctx->type);
}
return ret;
}
int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
{
WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
if (ctx != NULL) {
wc_HmacFree(&ctx->hmac);
}
return 1;
}
unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
int key_len, const unsigned char* data, size_t len, unsigned char* md,
unsigned int* md_len)
{
unsigned char* ret = NULL;
int rc = 0;
int type = 0;
int hmacLen = 0;
WC_DECLARE_VAR(hmac, Hmac, 1, 0);
void* heap = NULL;
if ((evp_md == NULL) || (key == NULL) || (md == NULL)) {
rc = BAD_FUNC_ARG;
}
if (rc == 0) {
rc = wolfssl_evp_md_to_hash_type(evp_md, &type);
}
#ifdef WOLFSSL_SMALL_STACK
if (rc == 0) {
hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
if (hmac == NULL) {
rc = MEMORY_E;
}
}
#endif
if (rc == 0) {
hmacLen = (int)wolfssl_mac_len((unsigned char)type);
if (hmacLen == 0) {
rc = BAD_FUNC_ARG;
}
}
if ((rc == 0) && (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0)) {
rc = wc_HmacSetKey(hmac, type, (const byte*)key, (word32)key_len);
if (rc == 0) {
rc = wc_HmacUpdate(hmac, data, (word32)len);
}
if ((rc == 0) && (wc_HmacFinal(hmac, md) == 0)) {
if (md_len != NULL) {
*md_len = (unsigned int)hmacLen;
}
ret = md;
}
wc_HmacFree(hmac);
}
WC_FREE_VAR_EX(hmac, heap, DYNAMIC_TYPE_HMAC);
return ret;
}
size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX* ctx)
{
size_t ret = 0;
if (ctx != NULL) {
ret = (size_t)wc_HashGetDigestSize((enum wc_HashType)ctx->hmac.macType);
}
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
#if defined(WOLFSSL_CMAC) && defined(OPENSSL_EXTRA) && \
defined(WOLFSSL_AES_DIRECT)
WOLFSSL_CMAC_CTX* wolfSSL_CMAC_CTX_new(void)
{
WOLFSSL_CMAC_CTX* ctx = NULL;
ctx = (WOLFSSL_CMAC_CTX*)XMALLOC(sizeof(WOLFSSL_CMAC_CTX), NULL,
DYNAMIC_TYPE_OPENSSL);
if (ctx != NULL) {
ctx->internal = NULL;
ctx->cctx = wolfSSL_EVP_CIPHER_CTX_new();
if (ctx->cctx == NULL) {
XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
ctx = NULL;
}
}
return ctx;
}
void wolfSSL_CMAC_CTX_free(WOLFSSL_CMAC_CTX *ctx)
{
if (ctx != NULL) {
if (ctx->internal != NULL) {
#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
wc_CmacFree((Cmac*)ctx->internal);
#endif
XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
}
if (ctx->cctx != NULL) {
wolfSSL_EVP_CIPHER_CTX_cleanup(ctx->cctx);
wolfSSL_EVP_CIPHER_CTX_free(ctx->cctx);
}
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
WOLFSSL_EVP_CIPHER_CTX* wolfSSL_CMAC_CTX_get0_cipher_ctx(WOLFSSL_CMAC_CTX* ctx)
{
WOLFSSL_EVP_CIPHER_CTX* cctx = NULL;
if (ctx != NULL) {
cctx = ctx->cctx;
}
return cctx;
}
int wolfSSL_CMAC_Init(WOLFSSL_CMAC_CTX* ctx, const void *key, size_t keySz,
const WOLFSSL_EVP_CIPHER* cipher, WOLFSSL_ENGINE* engine)
{
int ret = 1;
(void)engine;
WOLFSSL_ENTER("wolfSSL_CMAC_Init");
if ((ctx == NULL) || (cipher == NULL)) {
ret = 0;
}
if ((ret == 1)
#ifdef WOLFSSL_AES_128
&& (cipher != EVP_AES_128_CBC)
#endif
#ifdef WOLFSSL_AES_192
&& (cipher != EVP_AES_192_CBC)
#endif
#ifdef WOLFSSL_AES_256
&& (cipher != EVP_AES_256_CBC)
#endif
) {
WOLFSSL_MSG("wolfSSL_CMAC_Init: requested cipher is unsupported");
ret = 0;
}
if ((ret == 1) && ((int)keySz != wolfSSL_EVP_Cipher_key_length(cipher))) {
WOLFSSL_MSG("wolfSSL_CMAC_Init: "
"supplied key size doesn't match requested cipher");
ret = 0;
}
if ((ret == 1) && (ctx->internal == NULL)) {
ctx->internal = (Cmac*)XMALLOC(sizeof(Cmac), NULL, DYNAMIC_TYPE_CMAC);
if (ctx->internal == NULL)
ret = 0;
}
if ((ret == 1) && (wc_InitCmac((Cmac*)ctx->internal, (const byte*)key,
(word32)keySz, WC_CMAC_AES, NULL) != 0)) {
WOLFSSL_MSG("wolfSSL_CMAC_Init: wc_InitCmac() failed");
XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
ctx->internal = NULL;
ret = 0;
}
if (ret == 1) {
ret = wolfSSL_EVP_CipherInit(ctx->cctx, cipher, (const byte*)key, NULL,
1);
if (ret != WOLFSSL_SUCCESS)
WOLFSSL_MSG("wolfSSL_CMAC_Init: wolfSSL_EVP_CipherInit() failed");
}
WOLFSSL_LEAVE("wolfSSL_CMAC_Init", ret);
return ret;
}
int wolfSSL_CMAC_Update(WOLFSSL_CMAC_CTX* ctx, const void* data, size_t len)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CMAC_Update");
if (ctx == NULL) {
ret = 0;
}
if ((ret == 1) && (data != NULL) && (wc_CmacUpdate((Cmac*)ctx->internal,
(const byte*)data, (word32)len) != 0)) {
ret = 0;
}
WOLFSSL_LEAVE("wolfSSL_CMAC_Update", ret);
return ret;
}
int wolfSSL_CMAC_Final(WOLFSSL_CMAC_CTX* ctx, unsigned char* out, size_t* len)
{
int ret = 1;
int blockSize;
word32 len32;
WOLFSSL_ENTER("wolfSSL_CMAC_Final");
if (ctx == NULL) {
ret = 0;
}
if (ret == 1) {
blockSize = wolfSSL_EVP_CIPHER_CTX_block_size(ctx->cctx);
if (blockSize <= 0) {
ret = 0;
}
else {
len32 = (word32)blockSize;
if (len != NULL) {
*len = (size_t)blockSize;
}
}
}
if ((ret == 1) && (out != NULL)) {
if (wc_CmacFinal((Cmac*)ctx->internal, out, &len32) != 0) {
ret = 0;
}
else if (len != NULL) {
*len = (size_t)len32;
}
XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
ctx->internal = NULL;
}
WOLFSSL_LEAVE("wolfSSL_CMAC_Final", ret);
return ret;
}
#endif
#endif
#ifdef OPENSSL_EXTRA
#ifndef NO_DES3
void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* key)
{
int i;
WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
for (i = 0; i < DES_KEY_SIZE; i++) {
unsigned char c = (*key)[i];
c ^= ((c >> 0) ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^ (c >> 4) ^ (c >> 5) ^
(c >> 6) ^ (c >> 7) ^ 0x01) & 0x01;
(*key)[i] = c;
}
}
int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock *key)
{
int i;
unsigned char p = 1;
WOLFSSL_ENTER("wolfSSL_DES_check_key_parity");
for (i = 0; i < DES_KEY_SIZE; i++) {
unsigned char c = (*key)[i];
p &= (c >> 0) ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^ (c >> 4) ^ (c >> 5) ^
(c >> 6) ^ (c >> 7);
}
return p & 1;
}
static int wolfssl_des_check(word32 k1, word32 k2, unsigned char* key)
{
return (((word32*)key)[0] == k1) && (((word32*)key)[1] == k2);
}
int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
if (key == NULL) {
WOLFSSL_MSG("NULL key passed in");
ret = 1;
}
if ((ret == 0) && (wolfssl_des_check(0x01010101, 0x01010101, *key) ||
wolfssl_des_check(0xFEFEFEFE, 0xFEFEFEFE, *key) ||
wolfssl_des_check(0xE0E0E0E0, 0xF1F1F1F1, *key) ||
wolfssl_des_check(0x1F1F1F1F, 0x0E0E0E0E, *key))) {
WOLFSSL_MSG("Weak key found");
ret = 1;
}
if ((ret == 0) && (wolfssl_des_check(0x011F011F, 0x010E010E, *key) ||
wolfssl_des_check(0x1F011F01, 0x0E010E01, *key) ||
wolfssl_des_check(0x01E001E0, 0x01F101F1, *key) ||
wolfssl_des_check(0xE001E001, 0xF101F101, *key) ||
wolfssl_des_check(0x01FE01FE, 0x01FE01FE, *key) ||
wolfssl_des_check(0xFE01FE01, 0xFE01FE01, *key) ||
wolfssl_des_check(0x1FE01FE0, 0x0EF10EF1, *key) ||
wolfssl_des_check(0xE01FE01F, 0xF10EF10E, *key) ||
wolfssl_des_check(0x1FFE1FFE, 0x0EFE0EFE, *key) ||
wolfssl_des_check(0xFE1FFE1F, 0xFE0EFE0E, *key) ||
wolfssl_des_check(0xE0FEE0FE, 0xF1FEF1FE, *key) ||
wolfssl_des_check(0xFEE0FEE0, 0xFEF1FEF1, *key))) {
WOLFSSL_MSG("Semi-weak key found");
ret = 1;
}
return ret;
}
int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* key,
WOLFSSL_DES_key_schedule* schedule)
{
int ret = 0;
if ((key == NULL) || (schedule == NULL)) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
ret = -2;
}
if ((ret == 0) && (!wolfSSL_DES_check_key_parity(key))) {
WOLFSSL_MSG("Odd parity test fail");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 0) && wolfSSL_DES_is_weak_key(key)) {
WOLFSSL_MSG("Weak key found");
ret = -2;
}
if (ret == 0) {
XMEMCPY(schedule, key, DES_KEY_SIZE);
}
return ret;
}
void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* key,
WOLFSSL_DES_key_schedule* schedule)
{
if ((key != NULL) && (schedule != NULL)) {
XMEMCPY(schedule, key, DES_KEY_SIZE);
}
}
int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* key,
WOLFSSL_DES_key_schedule* schedule)
{
#ifdef WOLFSSL_CHECK_DESKEY
return wolfSSL_DES_set_key_checked(key, schedule);
#else
wolfSSL_DES_set_key_unchecked(key, schedule);
return 0;
#endif
}
int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
WOLFSSL_DES_key_schedule* schedule)
{
WOLFSSL_ENTER("wolfSSL_DES_key_sched");
if ((key == NULL) || (schedule == NULL)) {
WOLFSSL_MSG("Null argument passed in");
}
else {
XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
}
return 0;
}
WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
WOLFSSL_const_DES_cblock* iv)
{
WOLFSSL_DES_LONG ret = 0;
int err = 0;
unsigned char* data = (unsigned char*)in;
unsigned char* tmp = NULL;
long dataSz = length;
WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
if ((in == NULL) || (out == NULL) || (sc == NULL) || (iv == NULL)) {
WOLFSSL_MSG("Bad argument passed in");
err = 1;
}
if ((!err) && (dataSz % DES_BLOCK_SIZE)) {
dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
data = (unsigned char*)XMALLOC((size_t)dataSz, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (data == NULL) {
WOLFSSL_MSG("Issue creating temporary buffer");
err = 1;
}
else {
XMEMCPY(data, in, (size_t)length);
XMEMSET(data + length, 0, (size_t)(dataSz - length));
}
}
if (!err) {
tmp = (unsigned char*)XMALLOC((size_t)dataSz, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
WOLFSSL_MSG("Issue creating temporary buffer");
err = 1;
}
}
if (!err) {
wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc, (WOLFSSL_DES_cblock*)iv,
WC_DES_ENCRYPT);
XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
DES_BLOCK_SIZE);
ret = (((*((unsigned char*)out + 4) & 0xFF) << 24) |
((*((unsigned char*)out + 5) & 0xFF) << 16) |
((*((unsigned char*)out + 6) & 0xFF) << 8) |
(*((unsigned char*)out + 7) & 0xFF) );
}
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (data != in) {
XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
return ret;
}
void wolfSSL_DES_cbc_encrypt(const unsigned char* input, unsigned char* output,
long length, WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
int enc)
{
WC_DECLARE_VAR(des, Des, 1, 0);
byte lastBlock[DES_BLOCK_SIZE];
WOLFSSL_ENTER("wolfSSL_DES_cbc_encrypt");
#ifdef WOLFSSL_SMALL_STACK
des = (Des*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_CIPHER);
if (des == NULL) {
WOLFSSL_MSG("Failed to allocate memory for Des object");
}
else
#endif
if (wc_Des_SetKey(des, (const byte*)schedule, (const byte*)ivec,
!enc) != 0) {
WOLFSSL_MSG("wc_Des_SetKey return error.");
}
else {
int lb_sz = length % DES_BLOCK_SIZE;
word32 len = (word32)(length - lb_sz);
if (enc == WC_DES_ENCRYPT) {
wc_Des_CbcEncrypt(des, output, input, len);
if (lb_sz != 0) {
XMEMSET(lastBlock, 0, DES_BLOCK_SIZE);
XMEMCPY(lastBlock, input + len, (size_t)lb_sz);
wc_Des_CbcEncrypt(des, output + len, lastBlock,
(word32)DES_BLOCK_SIZE);
}
}
else {
wc_Des_CbcDecrypt(des, output, input, len);
if (lb_sz != 0) {
wc_Des_CbcDecrypt(des, lastBlock, input + len,
(word32)DES_BLOCK_SIZE);
XMEMCPY(output + len, lastBlock, (size_t)lb_sz);
}
}
}
WC_FREE_VAR_EX(des, NULL, DYNAMIC_TYPE_CIPHER);
}
void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, unsigned char* output,
long length, WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
int enc)
{
unsigned char tmp[DES_IV_SIZE];
size_t offset = (size_t)length;
WOLFSSL_ENTER("wolfSSL_DES_ncbc_encrypt");
offset = (offset + DES_BLOCK_SIZE - 1) / DES_BLOCK_SIZE;
offset *= DES_BLOCK_SIZE;
offset -= DES_BLOCK_SIZE;
if (enc == WC_DES_ENCRYPT) {
wolfSSL_DES_cbc_encrypt(input, output, length, schedule, ivec, enc);
XMEMCPY(ivec, output + offset, DES_IV_SIZE);
}
else {
XMEMCPY(tmp, input + offset, DES_IV_SIZE);
wolfSSL_DES_cbc_encrypt(input, output, length, schedule, ivec, enc);
XMEMCPY(ivec, tmp, DES_IV_SIZE);
}
}
void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
unsigned char* output, long sz, WOLFSSL_DES_key_schedule* ks1,
WOLFSSL_DES_key_schedule* ks2, WOLFSSL_DES_key_schedule* ks3,
WOLFSSL_DES_cblock* ivec, int enc)
{
WC_DECLARE_VAR(des3, Des3, 1, 0);
WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
#ifdef WOLFSSL_SMALL_STACK
des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_CIPHER);
if (des3 == NULL) {
WOLFSSL_MSG("Failed to allocate memory for Des3 object");
sz = 0;
}
#endif
if (sz > 0) {
int ret;
byte key[DES3_KEY_SIZE];
byte lastBlock[DES_BLOCK_SIZE];
int lb_sz;
word32 len;
XMEMCPY(key + 0 * DES_BLOCK_SIZE, *ks1, DES_BLOCK_SIZE);
XMEMCPY(key + 1 * DES_BLOCK_SIZE, *ks2, DES_BLOCK_SIZE);
XMEMCPY(key + 2 * DES_BLOCK_SIZE, *ks3, DES_BLOCK_SIZE);
lb_sz = sz % DES_BLOCK_SIZE;
len = (word32)(sz - lb_sz);
XMEMSET(des3, 0, sizeof(Des3));
ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
(void)ret;
if (enc == WC_DES_ENCRYPT) {
if (wc_Des3_SetKey(des3, key, (const byte*)ivec, DES_ENCRYPTION)
== 0) {
ret = wc_Des3_CbcEncrypt(des3, output, input, len);
(void)ret;
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &des3->asyncDev, WC_ASYNC_FLAG_NONE);
(void)ret;
#endif
if (lb_sz != 0) {
XMEMSET(lastBlock, 0, DES_BLOCK_SIZE);
XMEMCPY(lastBlock, input + len, (size_t)lb_sz);
ret = wc_Des3_CbcEncrypt(des3, output + len, lastBlock,
(word32)DES_BLOCK_SIZE);
(void)ret;
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &des3->asyncDev,
WC_ASYNC_FLAG_NONE);
(void)ret;
#endif
XMEMCPY(ivec, output + len, DES_BLOCK_SIZE);
}
else {
XMEMCPY(ivec, output + len - DES_BLOCK_SIZE,
DES_BLOCK_SIZE);
}
}
}
else {
if (wc_Des3_SetKey(des3, key, (const byte*)ivec, DES_DECRYPTION)
== 0) {
if (lb_sz != 0) {
XMEMCPY(ivec, input + len, DES_BLOCK_SIZE);
}
else {
XMEMCPY(ivec, input + len - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
}
ret = wc_Des3_CbcDecrypt(des3, output, input, len);
(void)ret;
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &des3->asyncDev, WC_ASYNC_FLAG_NONE);
(void)ret;
#endif
if (lb_sz != 0) {
ret = wc_Des3_CbcDecrypt(des3, lastBlock, input + len,
(word32)DES_BLOCK_SIZE);
(void)ret;
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &des3->asyncDev,
WC_ASYNC_FLAG_NONE);
(void)ret;
#endif
XMEMCPY(output + len, lastBlock, (size_t)lb_sz);
}
}
}
wc_Des3Free(des3);
}
WC_FREE_VAR_EX(des3, NULL, DYNAMIC_TYPE_CIPHER);
}
#ifdef WOLFSSL_DES_ECB
void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* in, WOLFSSL_DES_cblock* out,
WOLFSSL_DES_key_schedule* key, int enc)
{
WC_DECLARE_VAR(des, Des, 1, 0);
WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
if ((in == NULL) || (out == NULL) || (key == NULL) ||
((enc != WC_DES_ENCRYPT) && (enc != WC_DES_DECRYPT))) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
}
#ifdef WOLFSSL_SMALL_STACK
else if ((des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_CIPHER))
== NULL)
{
WOLFSSL_MSG("Failed to allocate memory for Des object");
}
#endif
else if (wc_Des_SetKey(des, (const byte*)key, NULL, !enc) != 0) {
WOLFSSL_MSG("wc_Des_SetKey return error.");
}
else if (enc == WC_DES_ENCRYPT) {
if (wc_Des_EcbEncrypt(des, (byte*)out, (const byte*)in, DES_KEY_SIZE)
!= 0) {
WOLFSSL_MSG("wc_Des_EcbEncrypt return error.");
}
}
else {
if (wc_Des_EcbDecrypt(des, (byte*)out, (const byte*)in, DES_KEY_SIZE)
!= 0) {
WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
}
}
WC_FREE_VAR_EX(des, NULL, DYNAMIC_TYPE_CIPHER);
}
#endif
#endif
#endif
#ifdef OPENSSL_EXTRA
#if !defined(NO_AES) && !defined(WOLFSSL_NO_OPENSSL_AES_LOW_LEVEL_API)
static int wolfssl_aes_set_key(const unsigned char *key, const int bits,
WOLFSSL_AES_KEY *aes, int enc)
{
wc_static_assert(sizeof(WOLFSSL_AES_KEY) >= sizeof(Aes));
if ((key == NULL) || (aes == NULL)) {
WOLFSSL_MSG("Null argument passed in");
return WOLFSSL_FATAL_ERROR;
}
XMEMSET(aes, 0, sizeof(WOLFSSL_AES_KEY));
if (wc_AesInit((Aes*)aes, NULL, INVALID_DEVID) != 0) {
WOLFSSL_MSG("Error in initting AES key");
return WOLFSSL_FATAL_ERROR;
}
if (wc_AesSetKey((Aes*)aes, key, (word32)((bits)/8), NULL, enc) != 0) {
WOLFSSL_MSG("Error in setting AES key");
return WOLFSSL_FATAL_ERROR;
}
return 0;
}
int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
WOLFSSL_AES_KEY *aes)
{
WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
return wolfssl_aes_set_key(key, bits, aes, AES_ENCRYPTION);
}
int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
WOLFSSL_AES_KEY *aes)
{
WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
return wolfssl_aes_set_key(key, bits, aes, AES_DECRYPTION);
}
#ifdef WOLFSSL_AES_DIRECT
void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
WOLFSSL_AES_KEY *key)
{
WOLFSSL_ENTER("wolfSSL_AES_encrypt");
if ((input == NULL) || (output == NULL) || (key == NULL)) {
WOLFSSL_MSG("Null argument passed in");
}
else
#if !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) \
|| defined(WOLFSSL_KERNEL_MODE))
if (wc_AesEncryptDirect((Aes*)key, output, input) != 0) {
WOLFSSL_MSG("wc_AesEncryptDirect failed");
}
#else
{
wc_AesEncryptDirect((Aes*)key, output, input);
}
#endif
}
void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
WOLFSSL_AES_KEY *key)
{
WOLFSSL_ENTER("wolfSSL_AES_decrypt");
if ((input == NULL) || (output == NULL) || (key == NULL)) {
WOLFSSL_MSG("Null argument passed in");
}
else
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(FIPS_VERSION_GE) && FIPS_VERSION3_GE(5,3,0)))
if (wc_AesDecryptDirect((Aes*)key, output, input) != 0) {
WOLFSSL_MSG("wc_AesDecryptDirect failed");
}
#else
{
wc_AesDecryptDirect((Aes*)key, output, input);
}
#endif
}
#endif
#ifdef HAVE_AES_ECB
void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
WOLFSSL_AES_KEY *key, const int enc)
{
WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
if ((key == NULL) || (in == NULL) || (out == NULL)) {
WOLFSSL_MSG("Error, Null argument passed in");
}
else if (enc == AES_ENCRYPTION) {
if (wc_AesEcbEncrypt((Aes*)key, out, in, WC_AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES CBC encrypt");
}
}
else {
#ifdef HAVE_AES_DECRYPT
if (wc_AesEcbDecrypt((Aes*)key, out, in, WC_AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES CBC decrypt");
}
#else
WOLFSSL_MSG("AES decryption not compiled in");
#endif
}
}
#endif
#ifdef HAVE_AES_CBC
void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
size_t len, WOLFSSL_AES_KEY *key, unsigned char* iv, const int enc)
{
WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
if ((key == NULL) || (in == NULL) || (out == NULL) || (iv == NULL) ||
(len == 0)) {
WOLFSSL_MSG("Error, Null argument passed in");
}
else {
int ret;
Aes* aes = (Aes*)key;
if ((ret = wc_AesSetIV(aes, (const byte*)iv)) != 0) {
WOLFSSL_MSG("Error with setting iv");
}
else if (enc == AES_ENCRYPTION) {
if ((ret = wc_AesCbcEncrypt(aes, out, in, (word32)len)) != 0) {
WOLFSSL_MSG("Error with AES CBC encrypt");
}
}
else {
if ((ret = wc_AesCbcDecrypt(aes, out, in, (word32)len)) != 0) {
WOLFSSL_MSG("Error with AES CBC decrypt");
}
}
if (ret == 0) {
XMEMCPY(iv, (byte*)(aes->reg), WC_AES_BLOCK_SIZE);
}
}
}
#endif
void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
size_t len, WOLFSSL_AES_KEY *key, unsigned char* iv, int* num,
const int enc)
{
#ifndef WOLFSSL_AES_CFB
WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
(void)in;
(void)out;
(void)len;
(void)key;
(void)iv;
(void)num;
(void)enc;
#else
WOLFSSL_ENTER("wolfSSL_AES_cfb_encrypt");
if ((key == NULL) || (in == NULL) || (out == NULL) || (iv == NULL)) {
WOLFSSL_MSG("Error, Null argument passed in");
}
else {
int ret;
Aes* aes = (Aes*)key;
XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
if (enc == AES_ENCRYPTION) {
if ((ret = wc_AesCfbEncrypt(aes, out, in, (word32)len)) != 0) {
WOLFSSL_MSG("Error with AES CBC encrypt");
}
}
else {
if ((ret = wc_AesCfbDecrypt(aes, out, in, (word32)len)) != 0) {
WOLFSSL_MSG("Error with AES CBC decrypt");
}
}
if (ret == 0) {
XMEMCPY(iv, (byte*)(aes->reg), WC_AES_BLOCK_SIZE);
if (num != NULL) {
*num = (WC_AES_BLOCK_SIZE - aes->left) % WC_AES_BLOCK_SIZE;
}
}
}
#endif
}
#if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
int wolfSSL_AES_wrap_key(WOLFSSL_AES_KEY *key, const unsigned char *iv,
unsigned char *out, const unsigned char *in, unsigned int inSz)
{
int ret = 0;
int len = 0;
WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
if ((out == NULL) || (in == NULL)) {
WOLFSSL_MSG("Error, Null argument passed in");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && ((ret = wc_AesKeyWrap_ex((Aes*)key, in, inSz, out,
inSz + KEYWRAP_BLOCK_SIZE, iv)) > 0)) {
len = ret;
}
return len;
}
int wolfSSL_AES_unwrap_key(WOLFSSL_AES_KEY *key, const unsigned char *iv,
unsigned char *out, const unsigned char *in, unsigned int inSz)
{
int ret = 0;
int len = 0;
WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
if ((out == NULL) || (in == NULL)) {
WOLFSSL_MSG("Error, Null argument passed in");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && ((ret = wc_AesKeyUnWrap_ex((Aes*)key, in, inSz, out,
inSz + KEYWRAP_BLOCK_SIZE, iv)) > 0)) {
len = ret;
}
return len;
}
#endif
#ifdef HAVE_CTS
size_t wolfSSL_CRYPTO_cts128_encrypt(const unsigned char *in,
unsigned char *out, size_t len, const void *key, unsigned char *iv,
WOLFSSL_CBC128_CB cbc)
{
byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ];
int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_encrypt");
if ((in == NULL) || (out == NULL) || (len <= WOLFSSL_CTS128_BLOCK_SZ) ||
(cbc == NULL) || (key == NULL) || (iv == NULL)) {
WOLFSSL_MSG("Bad parameter");
len = 0;
}
if (len > 0) {
if (lastBlkLen == 0) {
lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
}
(*cbc)(in, out, len - lastBlkLen, key, iv, AES_ENCRYPTION);
in += len - lastBlkLen;
out += len - lastBlkLen;
XMEMCPY(lastBlk, in, lastBlkLen);
XMEMSET(lastBlk + lastBlkLen, 0, WOLFSSL_CTS128_BLOCK_SZ - lastBlkLen);
XMEMCPY(out, out - WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
(*cbc)(lastBlk, out - WOLFSSL_CTS128_BLOCK_SZ, WOLFSSL_CTS128_BLOCK_SZ,
key, iv, AES_ENCRYPTION);
}
return len;
}
size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in,
unsigned char *out, size_t len, const void *key, unsigned char *iv,
WOLFSSL_CBC128_CB cbc)
{
byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ];
byte prevBlk[WOLFSSL_CTS128_BLOCK_SZ];
int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_decrypt");
if ((in == NULL) || (out == NULL) || (len <= WOLFSSL_CTS128_BLOCK_SZ) ||
(cbc == NULL) || (key == NULL) || (iv == NULL)) {
WOLFSSL_MSG("Bad parameter");
len = 0;
}
if (len > 0) {
if (lastBlkLen == 0) {
lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
}
if (len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ != 0) {
(*cbc)(in, out, len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ, key, iv,
AES_DECRYPTION);
in += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
out += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
}
XMEMSET(lastBlk, 0, WOLFSSL_CTS128_BLOCK_SZ);
(*cbc)(in, prevBlk, WOLFSSL_CTS128_BLOCK_SZ, key, lastBlk,
AES_DECRYPTION);
XMEMCPY(prevBlk, in + WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
(*cbc)(prevBlk, out, WOLFSSL_CTS128_BLOCK_SZ, key, iv, AES_DECRYPTION);
(*cbc)(lastBlk, lastBlk, WOLFSSL_CTS128_BLOCK_SZ, key, iv,
AES_DECRYPTION);
XMEMCPY(out + WOLFSSL_CTS128_BLOCK_SZ, lastBlk, lastBlkLen);
}
return len;
}
#endif
#endif
#endif
#ifdef OPENSSL_EXTRA
#ifndef NO_RC4
void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
const unsigned char* data)
{
wc_static_assert(sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4));
WOLFSSL_ENTER("wolfSSL_RC4_set_key");
if ((key == NULL) || (len < 0) || (data == NULL)) {
WOLFSSL_MSG("bad argument passed in");
}
else {
XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
wc_Arc4SetKey((Arc4*)key, data, (word32)len);
}
}
void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len, const unsigned char* in,
unsigned char* out)
{
WOLFSSL_ENTER("wolfSSL_RC4");
if ((key == NULL) || (in == NULL) || (out == NULL)) {
WOLFSSL_MSG("Bad argument passed in");
}
else {
wc_Arc4Process((Arc4*)key, out, in, (word32)len);
}
}
#endif
#endif
#endif