#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if !defined(NO_SHA) || !defined(NO_SHA256)
#include <string.h>
#include <stdio.h>
#include <wolfssl/internal.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(WOLFSSL_RENESAS_TSIP_TLS) || \
defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY))
#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h>
extern struct WOLFSSL_HEAP_HINT* tsip_heap_hint;
#ifdef WOLFSSL_RENESAS_TSIP_TLS
WOLFSSL_LOCAL int tsip_Tls13GetHmacMessages(struct WOLFSSL* ssl, byte* mac)
{
int ret = 0;
int isTLS13 = 0;
TsipUserCtx* tuc = NULL;
e_tsip_err_t err = TSIP_SUCCESS;
byte hash[WC_SHA256_DIGEST_SIZE];
int hmacSz = 0;
WOLFSSL_ENTER("tsip_Tls13GetHmacMessages");
if (ssl == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0) {
if (ssl->version.major == SSLv3_MAJOR &&
ssl->version.minor == TLSv1_3_MINOR)
isTLS13 = 1;
if (!isTLS13 || ssl->options.side != WOLFSSL_CLIENT_END) {
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
tuc = ssl->RenesasUserCtx;
if (tuc == NULL) {
ret = CRYPTOCB_UNAVAILABLE;
}
else if (!tuc->internal->HandshakeClientTrafficKey_set) {
WOLFSSL_MSG("Client handshake traffic keys aren't created by TSIP");
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
ForceZero(hash, sizeof(hash));
ret = tsip_GetMessageSha256(ssl, hash, (int*)&hmacSz);
}
if (ret == 0) {
if ((ret = tsip_hw_lock()) == 0) {
err = R_TSIP_Sha256HmacGenerateInit(
&(tuc->internal->hmacFinished13Handle),
&(tuc->internal->clientFinished13Idx));
if (err != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_Sha256HmacGenerateInit failed");
ret = WC_HW_E;
}
if (ret == 0) {
err = R_TSIP_Sha256HmacGenerateUpdate(
&(tuc->internal->hmacFinished13Handle),
(uint8_t*)hash,
WC_SHA256_DIGEST_SIZE);
if (err != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_Sha256HmacGenerateUpdate failed");
ret = WC_HW_E;
}
}
if (ret == 0) {
err = R_TSIP_Sha256HmacGenerateFinal(
&(tuc->internal->hmacFinished13Handle), mac);
if (err != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_Sha256HmacGenerateFinal failed");
ret = WC_HW_E;
}
}
tsip_hw_unlock();
}
else {
WOLFSSL_MSG("mutex locking error");
}
}
WOLFSSL_LEAVE("tsipTls13GetHmacMessages", ret);
return ret;
}
WOLFSSL_LOCAL int tsip_StoreMessage(struct WOLFSSL* ssl, const byte* data,
int sz)
{
int ret = 0;
int isTLS13 = 0;
word32 messageSz;
MsgBag* bag = NULL;
TsipUserCtx* tuc = NULL;
WOLFSSL_ENTER("tsip_StoreMessage");
if (ssl == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0) {
if (ssl->version.major == SSLv3_MAJOR &&
ssl->version.minor == TLSv1_3_MINOR)
isTLS13 = 1;
if (!isTLS13 || ssl->options.side != WOLFSSL_CLIENT_END) {
WOLFSSL_MSG("Not in tls1.3 or not in client end");
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
if (ssl->options.handShakeDone) {
WOLFSSL_MSG("handshake is done.");
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
tuc = ssl->RenesasUserCtx;
if (tuc == NULL) {
WOLFSSL_MSG("RenesasUserCtx is not set in ssl.");
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
if (!tuc->internal->Dhe_key_set) {
WOLFSSL_MSG("DH key not set.");
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
c24to32(&data[1], &messageSz);
bag = &(tuc->internal->messageBag);
if (bag->msgIdx +1 > MAX_MSGBAG_MESSAGES ||
bag->buffIdx + sz > MSGBAG_SIZE) {
WOLFSSL_MSG("Capacity over error in tsip_StoreMessage");
ret = MEMORY_E;
}
XMEMCPY(bag->buff + bag->buffIdx, data, sz);
bag->msgTypes[bag->msgIdx++] = *data;
bag->buffIdx += sz;
}
WOLFSSL_LEAVE("tsip_StoreMessage", ret);
return ret;
}
WOLFSSL_LOCAL int tsip_GetMessageSha256(struct WOLFSSL* ssl, byte* hash,
int* sz)
{
int ret = 0;
int isTLS13 = 0;
MsgBag* bag = NULL;
TsipUserCtx* tuc = NULL;
tsip_sha_md5_handle_t handle;
e_tsip_err_t err = TSIP_SUCCESS;
uint32_t hashSz = 0;
WOLFSSL_ENTER("tsip_GetMessageSha256");
if (ssl == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0) {
if (ssl->version.major == SSLv3_MAJOR &&
ssl->version.minor == TLSv1_3_MINOR)
isTLS13 = 1;
if (!isTLS13 || ssl->options.side != WOLFSSL_CLIENT_END) {
ret = CRYPTOCB_UNAVAILABLE;
}
}
if (ret == 0) {
tuc = ssl->RenesasUserCtx;
if (tuc == NULL) {
ret = CRYPTOCB_UNAVAILABLE;
}
bag = &(tuc->internal->messageBag);
}
if (ret == 0) {
if ((ret = tsip_hw_lock()) == 0) {
err = R_TSIP_Sha256Init(&handle);
if (err == TSIP_SUCCESS) {
err = R_TSIP_Sha256Update(&handle, (uint8_t*)bag->buff,
bag->buffIdx);
}
if (err == TSIP_SUCCESS) {
err = R_TSIP_Sha256Final(&handle, hash, &hashSz);
}
if (err == TSIP_SUCCESS) {
if (sz != NULL) {
*sz = hashSz;
}
}
else {
ret = WC_HW_E;
}
tsip_hw_unlock();
}
else {
WOLFSSL_MSG("mutex locking error");
}
}
WOLFSSL_LEAVE("tsip_GetMessageSha256", ret);
return ret;
}
#endif
static void TSIPHashFree(wolfssl_TSIP_Hash* hash)
{
if (hash == NULL)
return;
XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
}
static int TSIPHashInit(wolfssl_TSIP_Hash* hash, void* heap, int devId,
word32 sha_type)
{
if (hash == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
ForceZero(hash, sizeof(wolfssl_TSIP_Hash));
if (heap == NULL && tsip_heap_hint != NULL) {
hash->heap = (struct wolfSSL_HEAP_HINT*)tsip_heap_hint;
}
else {
hash->heap = heap;
}
hash->len = 0;
hash->used = 0;
hash->msg = NULL;
hash->sha_type = sha_type;
return 0;
}
static int TSIPHashUpdate(wolfssl_TSIP_Hash* hash, const byte* data, word32 sz)
{
if (hash == NULL || (sz > 0 && data == NULL)) {
return BAD_FUNC_ARG;
}
if (hash->len < hash->used + sz) {
if (hash->msg == NULL) {
hash->msg = (byte*)XMALLOC(hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
}
else {
#ifdef FREERTOS
byte* pt = (byte*)XMALLOC(hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
XMEMCPY(pt, hash->msg, hash->used);
XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
hash->msg = pt;
#else
byte* pt = (byte*)XREALLOC(hash->msg, hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
hash->msg = pt;
#endif
}
if (hash->msg == NULL) {
return MEMORY_E;
}
hash->len = hash->used + sz;
}
XMEMCPY(hash->msg + hash->used, data , sz);
hash->used += sz;
return 0;
}
static int TSIPHashFinal(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz)
{
int ret;
void* heap;
tsip_sha_md5_handle_t handle;
uint32_t sz;
e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*);
e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t);
e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*);
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
if (hash->sha_type == TSIP_SHA1) {
Init = R_TSIP_Sha1Init;
Update = R_TSIP_Sha1Update;
Final = R_TSIP_Sha1Final;
}
else if (hash->sha_type == TSIP_SHA256) {
Init = R_TSIP_Sha256Init;
Update = R_TSIP_Sha256Update;
Final = R_TSIP_Sha256Final;
}
else
return BAD_FUNC_ARG;
heap = hash->heap;
tsip_hw_lock();
if (Init(&handle) == TSIP_SUCCESS) {
ret = Update(&handle, (uint8_t*)hash->msg, hash->used);
if (ret == TSIP_SUCCESS) {
ret = Final(&handle, out, (uint32_t*)&sz);
if (ret != TSIP_SUCCESS || sz != outSz) {
tsip_hw_unlock();
return ret;
}
}
}
tsip_hw_unlock();
TSIPHashFree(hash);
return TSIPHashInit(hash, heap, 0, hash->sha_type);
}
static int TSIPHashGet(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz)
{
int ret;
tsip_sha_md5_handle_t handle;
uint32_t sz;
e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*);
e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t);
e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*);
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
if (hash->sha_type == TSIP_SHA1) {
Init = R_TSIP_Sha1Init;
Update = R_TSIP_Sha1Update;
Final = R_TSIP_Sha1Final;
}
else if (hash->sha_type == TSIP_SHA256) {
Init = R_TSIP_Sha256Init;
Update = R_TSIP_Sha256Update;
Final = R_TSIP_Sha256Final;
}
else
return BAD_FUNC_ARG;
tsip_hw_lock();
if (Init(&handle) == TSIP_SUCCESS) {
ret = Update(&handle, (uint8_t*)hash->msg, hash->used);
if (ret == TSIP_SUCCESS) {
ret = Final(&handle, out, &sz);
if (ret != TSIP_SUCCESS || sz != outSz) {
tsip_hw_unlock();
return ret;
}
}
}
tsip_hw_unlock();
return 0;
}
static int TSIPHashCopy(wolfssl_TSIP_Hash* src, wolfssl_TSIP_Hash* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
XMEMCPY(dst, src, sizeof(wolfssl_TSIP_Hash));
if (src->len > 0 && src->msg != NULL) {
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (dst->msg == NULL) {
return MEMORY_E;
}
XMEMCPY(dst->msg, src->msg, src->len);
}
return 0;
}
#if !defined(NO_SHA) && !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
#include <wolfssl/wolfcrypt/sha.h>
int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
{
return TSIPHashInit(sha, heap, devId, TSIP_SHA1);
}
int wc_ShaUpdate(wc_Sha* sha, const byte* in, word32 sz)
{
return TSIPHashUpdate(sha, in, sz);
}
int wc_ShaFinal(wc_Sha* sha, byte* hash)
{
return TSIPHashFinal(sha, hash, WC_SHA_DIGEST_SIZE);
}
int wc_ShaGetHash(wc_Sha* sha, byte* hash)
{
return TSIPHashGet(sha, hash, WC_SHA_DIGEST_SIZE);
}
int wc_ShaCopy(wc_Sha256* src, wc_Sha256* dst)
{
return TSIPHashCopy(src, dst);
}
#endif
#if !defined(NO_SHA256) && !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
#include <wolfssl/wolfcrypt/sha256.h>
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
return TSIPHashInit(sha, heap, devId, TSIP_SHA256);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
{
return TSIPHashUpdate(sha, in, sz);
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
return TSIPHashFinal(sha, hash, WC_SHA256_DIGEST_SIZE);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
return TSIPHashGet(sha, hash, WC_SHA256_DIGEST_SIZE);
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
return TSIPHashCopy(src, dst);
}
#endif
#endif
#endif