Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 105 additions & 1 deletion src/wh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ int wh_Client_Init(whClientContext* c, const whClientConfig* config)
/* register the cancel callback */
c->cancelCb = config->cancelCb;
#endif

#if defined(WOLFHSM_CFG_CLIENT_TIMEOUT)
if (NULL != config->timeoutConfig) {
c->timeout.timeout_val = config->timeoutConfig->timeout_val;
c->timeout.timeout_enabled = config->timeoutConfig->timeout_enabled;
c->timeout.start_time = 0;
}
#endif
rc = wh_CommClient_Init(c->comm, config->comm);

#ifndef WOLFHSM_CFG_NO_CRYPTO
Expand Down Expand Up @@ -1516,4 +1522,102 @@ int wh_Client_KeyExportDma(whClientContext* c, uint16_t keyId,
}
#endif /* WOLFHSM_CFG_DMA */

#if defined(WOLFHSM_CFG_CLIENT_TIMEOUT)
static uint64_t wh_timeval_to_64(const wh_timeval* tv)
{
if (tv == NULL)
return 0;
return (uint64_t)tv->tv_sec * WH_BASE_TIMEOUT_UNIT +
(uint64_t)((tv->tv_usec * WH_BASE_TIMEOUT_UNIT) / 1000000ULL);
}
/* Start Timeout */
int wh_Client_TimeoutStart(whClientContext* c)
{
if (c == NULL) {
return WH_ERROR_BADARGS;
}

/* if feature not enabled, nothing to do */
if (c->timeout.timeout_enabled != 1) {
return WH_ERROR_OK;
}
if (c->timeout.cb.GetCurrentTime == NULL) {
return WH_ERROR_BADARGS;
}
/* initialize start time */
c->timeout.start_time = c->timeout.cb.GetCurrentTime(1);

return WH_ERROR_OK;
}

/* Check Timeout */
int wh_Client_TimeoutCheck(whClientContext* c)
{
uint64_t current_ = 0;
uint64_t elapsed_ = 0;
uint64_t timeout_ = 0;

if (c == NULL) {
return WH_ERROR_BADARGS;
}

if (c->timeout.timeout_enabled != 1) {
return WH_ERROR_OK;
}

if (c->timeout.cb.GetCurrentTime == NULL) {
return WH_ERROR_BADARGS;
}

timeout_ = wh_timeval_to_64(&c->timeout.timeout_val);
if (timeout_ == 0) {
return WH_ERROR_OK;
}

/* check timeout by user cb if defined */
if (c->timeout.cb.CheckTimeout != NULL) {
return c->timeout.cb.CheckTimeout(&c->timeout.start_time, timeout_);
}

/* Otherwise compute elapsed using user-provided GetCurrentTime */
current_ = c->timeout.cb.GetCurrentTime(0);
elapsed_ = current_ - c->timeout.start_time;
if (elapsed_ > timeout_) {
return WH_ERROR_TIMEOUT;
}

return WH_ERROR_OK;
}

int wh_Client_TimeoutRegisterCb(whClientContext* client, whClientTimeOutCb* cb)
{
/* No NULL check for cb, since it is optional and always NULL checked before
* it is called */
if (NULL == client) {
return WH_ERROR_BADARGS;
}

client->timeout.cb.GetCurrentTime = cb->GetCurrentTime;
client->timeout.cb.CheckTimeout = cb->CheckTimeout;

return WH_ERROR_OK;
}

int wh_Client_TimeoutSet(whClientContext* client, wh_timeval* timeout_val)
{
if (NULL == client) {
return WH_ERROR_BADARGS;
}

if (timeout_val != NULL) {
client->timeout.timeout_enabled = 1;
memcpy(&client->timeout.timeout_val, timeout_val, sizeof(wh_timeval));
}
else {
client->timeout.timeout_enabled = 0;
memset(&client->timeout.timeout_val, 0, sizeof(wh_timeval));
}
return WH_ERROR_OK;
}
#endif /* WOLFHSM_CFG_CLIENT_TIMEOUT */
#endif /* WOLFHSM_CFG_ENABLE_CLIENT */
80 changes: 55 additions & 25 deletions src/wh_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,38 @@ static int _getCryptoResponse(uint8_t* respBuf, uint16_t type,

return header->rc;
}
static int _SendRecieveWithTimeout(whClientContext* ctx, uint16_t* group,
uint16_t* action, uint16_t req_len,
uint16_t* res_len, void* data)
{

int ret = WH_ERROR_OK;

ret = wh_Client_SendRequest(ctx, *group, *action, req_len, data);
#if defined(WOLFHSM_CFG_CLIENT_TIMEOUT)
if (ret == WH_ERROR_OK) {
ret = wh_Client_TimeoutStart(ctx);
}
#endif
if (ret == WH_ERROR_OK) {
do {
ret = wh_Client_RecvResponse(ctx, group, action, res_len, data);
#if defined(WOLFHSM_CFG_CLIENT_TIMEOUT)
if (ret == WH_ERROR_NOTREADY) {
/* Check for crypto timeout */
int chk = wh_Client_TimeoutCheck(ctx);
if (chk == WH_ERROR_TIMEOUT) {
return WH_ERROR_TIMEOUT;
}
else if (chk < 0 && chk != WH_ERROR_OK) {
return chk;
}
}
#endif
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

/** Implementations */
int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size)
Expand Down Expand Up @@ -230,12 +262,11 @@ int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size)
(unsigned int)size);
WH_DEBUG_CLIENT_VERBOSE("RNG: req:%p\n", req);

/* Send request and get response */
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
/* Send request and get response with Timeout */
if (ret == 0) {
do {
ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len,
dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, req_len,
&res_len, dataPtr);
} while (ret == WH_ERROR_NOTREADY);
}
if (ret == WH_ERROR_OK) {
Expand Down Expand Up @@ -409,15 +440,16 @@ int wh_Client_AesCtr(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in,
WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len);
WH_DEBUG_VERBOSE_HEXDUMP("[client] tmp: \n", req_tmp, AES_BLOCK_SIZE);
WH_DEBUG_VERBOSE_HEXDUMP("[client] req packet: \n", (uint8_t*)req, req_len);
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
/* read response */

/* Send and get response with Timeout */
if (ret == WH_ERROR_OK) {
/* Response packet */
uint16_t res_len = 0;
do {
ret =
wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, req_len,
&res_len, dataPtr);
} while (ret == WH_ERROR_NOTREADY);

if (ret == WH_ERROR_OK) {
ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res);
if (ret == WH_ERROR_OK) {
Expand Down Expand Up @@ -521,15 +553,16 @@ int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in,
WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, key_len);
WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len);
WH_DEBUG_VERBOSE_HEXDUMP("[client] req packet: \n", (uint8_t*)req, req_len);
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
/* read response */

/* Send and get response with Timeout */
if (ret == WH_ERROR_OK) {
/* Response packet */
uint16_t res_len = 0;
do {
ret =
wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, req_len,
&res_len, dataPtr);
} while (ret == WH_ERROR_NOTREADY);

if (ret == WH_ERROR_OK) {
ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res);
if (ret == WH_ERROR_OK) {
Expand Down Expand Up @@ -630,15 +663,15 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in,
WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, key_len);
WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len);
WH_DEBUG_VERBOSE_HEXDUMP("[client] req packet: \n", (uint8_t*)req, req_len);
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
/* read response */
/* Send and get response with Timeout */
if (ret == WH_ERROR_OK) {
/* Response packet */
uint16_t res_len = 0;
do {
ret =
wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, req_len,
&res_len, dataPtr);
} while (ret == WH_ERROR_NOTREADY);

if (ret == WH_ERROR_OK) {
ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res);
if (ret == WH_ERROR_OK) {
Expand Down Expand Up @@ -752,13 +785,12 @@ int wh_Client_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in,

WH_DEBUG_VERBOSE_HEXDUMP("[client] AESGCM req packet: \n", dataPtr, req_len);

/* Send request and receive response */
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
/* Send and get response with Timeout */
if (ret == 0) {
uint16_t res_len = 0;
do {
ret =
wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, req_len,
&res_len, dataPtr);
} while (ret == WH_ERROR_NOTREADY);

if (ret == WH_ERROR_OK) {
Expand Down Expand Up @@ -951,14 +983,12 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc,
/* Send request and receive response */
reqLen = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req);
WH_DEBUG_VERBOSE_HEXDUMP("[client] AESGCM DMA req packet: \n", dataPtr, reqLen);
if (ret == WH_ERROR_OK) {
ret = wh_Client_SendRequest(ctx, group, action, reqLen, dataPtr);
}
/* Send and get response with Timeout */
if (ret == 0) {
uint16_t resLen = 0;
do {
ret =
wh_Client_RecvResponse(ctx, &group, &action, &resLen, dataPtr);
ret = _SendRecieveWithTimeout(ctx, &group, &action, reqLen, &resLen,
dataPtr);
} while (ret == WH_ERROR_NOTREADY);

if (ret == WH_ERROR_OK) {
Expand Down
1 change: 1 addition & 0 deletions src/wh_comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ int wh_CommClient_Cleanup(whCommClient* context)
return rc;
}


#endif /* WOLFHSM_CFG_ENABLE_CLIENT */

/** Server Functions */
Expand Down
3 changes: 3 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ else
DEF += -DWOLFHSM_CFG_IS_TEST_SERVER
endif

ifeq ($(CRYPTIMEOUT),1)
DEF += -DWOLFHSM_CFG_CLIENT_TIMEOUT
endif

## Source files
# Assembly source files
Expand Down
6 changes: 6 additions & 0 deletions test/config/wolfhsm_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,10 @@
/* Test log-based NVM flash backend */
#define WOLFHSM_CFG_SERVER_NVM_FLASH_LOG

/* Enable client crypto timeout feature for testing */
#if defined(WOLFHSM_CFG_CLIENT_TIMEOUT) && defined(WOLFHSM_CFG_TEST_POSIX)
#define WOLFHSM_CFG_CLIENT_TIMEOUT_USEC (500000) /* 500ms */
#define WOLFHSM_CFG_TEST_CLIENT_TIMEOUT
#endif /* WOLFHSM_CFG_TEST_CLIENT_TIMEOUT */

#endif /* WOLFHSM_CFG_H_ */
57 changes: 56 additions & 1 deletion test/wh_test_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
#include <wolfhsm/wh_error.h>

#include "wh_test_common.h"

#if defined(WOLFHSM_CFG_TEST_CLIENT_TIMEOUT)
#include <sys/time.h> /* For gettimeofday */
#endif

/**
* Helper function to configure and select an NVM backend for testing.
Expand Down Expand Up @@ -90,3 +92,56 @@ int whTest_NvmCfgBackend(whTestNvmBackendType type,

return 0;
}

#if defined(WOLFHSM_CFG_TEST_CLIENT_TIMEOUT)
#include <time.h>
#include <sys/time.h> /* For gettimeofday */

uint64_t whTest_GetCurrentTime(int reset)
{
(void)reset;
#if defined(CLOCK_MONOTONIC)
struct timespec ts;

if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
return 0;

/* Convert to milliseconds number. */
return (uint64_t)ts.tv_sec * 1000ULL + (uint64_t)ts.tv_nsec / 1000000ULL;
#else
struct timeval tv;
if (gettimeofday(&tv, 0) < 0)
return 0;
/* Convert to milliseconds number. */
return (uint64_t)(tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL);
#endif
}
/* start_time stores the time (in milliseconds) returned by the GetCurrentTime()
* callback when the operation started.
* The actual unit depends on the GetCurrentTime() implementation.
* timeout_val represents the timeout in milliseconds(default),
* which is derived from the timeout value in whCommClientConfig.
*/
int whTest_CheckTimeout(uint64_t* start_time, uint64_t timeout_val)
{
uint64_t current_time;
uint64_t elapsed_time;

if (start_time == NULL) {
return WH_ERROR_BADARGS;
}

if (timeout_val == 0) {
return WH_ERROR_OK;
}

current_time = whTest_GetCurrentTime(0);
elapsed_time = current_time - *start_time;

if (elapsed_time > timeout_val) {
return WH_ERROR_TIMEOUT;
}

return WH_ERROR_OK;
}
#endif /* WOLFHSM_CFG_TEST_CLIENT_TIMEOUT */
9 changes: 9 additions & 0 deletions test/wh_test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,13 @@ int whTest_NvmCfgBackend(whTestNvmBackendType type,
whTestNvmBackendUnion* nvmSetup, whNvmConfig* nvmCfg,
whFlashRamsimCfg* fCfg, whFlashRamsimCtx* fCtx,
const whFlashCb* fCb);
uint64_t whTest_GetCurrentTime(int reset);
int whTest_CheckTimeout(uint64_t* start_time, uint64_t timeout_val);

#define WH_CLIENT_TIMEOUT_CB \
{ \
.GetCurrentTime = whTest_GetCurrentTime, \
.CheckTimeout = whTest_CheckTimeout, \
}

#endif /* WH_TEST_COMMON_H_ */
Loading