diff --git a/src/wh_client.c b/src/wh_client.c index 2c8e3ea0..9a87124d 100644 --- a/src/wh_client.c +++ b/src/wh_client.c @@ -23,6 +23,7 @@ /* Message definitions */ #include "wolfhsm/wh_message.h" #include "wolfhsm/wh_message_comm.h" +#include "wolfhsm/wh_message_customcb.h" #include "wolfhsm/wh_client.h" @@ -34,7 +35,7 @@ int wh_Client_Init(whClientContext* c, const whClientConfig* config) } memset(c, 0, sizeof(*c)); - + if ( ((rc = wh_CommClient_Init(c->comm, config->comm)) == 0) && ((rc = wolfCrypt_Init()) == 0) && ((rc = wc_CryptoCb_RegisterDevice(WOLFHSM_DEV_ID, wolfHSM_CryptoCb, c)) == 0) && @@ -201,3 +202,110 @@ int wh_Client_Echo(whClientContext* c, uint16_t snd_len, const void* snd_data, return rc; } +int wh_Client_CustomCbRequest(whClientContext* c, const whMessageCustomCb_Request* req) +{ + if (NULL == c || req == NULL || req->id >= WH_CUSTOM_CB_NUM_CALLBACKS) { + return WH_ERROR_BADARGS; + } + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_CUSTOM, req->id, + sizeof(*req), req); +} + +int wh_Client_CustomCbResponse(whClientContext* c, + whMessageCustomCb_Response* outResp) +{ + whMessageCustomCb_Response resp; + uint16_t resp_group = 0; + uint16_t resp_action = 0; + uint16_t resp_size = 0; + int32_t rc = 0; + + if (NULL == c || outResp == NULL) { + return WH_ERROR_BADARGS; + } + + rc = + wh_Client_RecvResponse(c, &resp_group, &resp_action, &resp_size, &resp); + if (rc != WH_ERROR_OK) { + return rc; + } + + if (resp_size != sizeof(resp) || resp_group != WH_MESSAGE_GROUP_CUSTOM || + resp_action >= WH_CUSTOM_CB_NUM_CALLBACKS) { + /* message invalid */ + return WH_ERROR_ABORTED; + } + + memcpy(outResp, &resp, sizeof(resp)); + + return WH_ERROR_OK; +} + +int wh_Client_CustomCheckRegisteredRequest(whClientContext* c, uint32_t id) +{ + whMessageCustomCb_Request req = {0}; + + if (c == NULL || id >= WH_CUSTOM_CB_NUM_CALLBACKS) { + return WH_ERROR_BADARGS; + } + + req.id = id; + req.type = WH_MESSAGE_CUSTOM_CB_TYPE_QUERY; + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_CUSTOM, req.id, + sizeof(req), &req); +} + + +int wh_Client_CustomCbCheckRegisteredResponse(whClientContext* c, uint16_t* outId, int* responseError) +{ + int rc = 0; + whMessageCustomCb_Response resp = {0}; + + if (c == NULL || outId == NULL || responseError == NULL) { + return WH_ERROR_BADARGS; + } + + rc = wh_Client_CustomCbResponse(c, &resp); + if (rc != WH_ERROR_OK) { + return rc; + } + + if (resp.type != WH_MESSAGE_CUSTOM_CB_TYPE_QUERY) { + /* message invalid */ + return WH_ERROR_ABORTED; + } + + if (resp.err != WH_ERROR_OK && resp.err != WH_ERROR_NO_HANDLER) { + /* error codes that aren't related to the query should be fatal */ + return WH_ERROR_ABORTED; + } + + *outId = resp.id; + *responseError = resp.err; + + return WH_ERROR_OK; +} + + +int wh_Client_CustomCbCheckRegistered(whClientContext* c, uint16_t id, int* responseError) +{ + int rc = 0; + + if (NULL == c || NULL == responseError || id >= WH_CUSTOM_CB_NUM_CALLBACKS) { + return WH_ERROR_BADARGS; + } + + do { + rc = wh_Client_CustomCheckRegisteredRequest(c, id); + } while (rc == WH_ERROR_NOTREADY); + + if (rc == WH_ERROR_OK) { + do { + rc = wh_Client_CustomCbCheckRegisteredResponse(c, &id, responseError); + } while (rc == WH_ERROR_NOTREADY); + } + + return rc; +} \ No newline at end of file diff --git a/src/wh_message_customcb.c b/src/wh_message_customcb.c new file mode 100644 index 00000000..1512d4be --- /dev/null +++ b/src/wh_message_customcb.c @@ -0,0 +1,84 @@ +#include +#include + +#include "wolfhsm/wh_message_customcb.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" + + +static void _translateCustomData(uint16_t magic, uint32_t translatedType, + const whMessageCustomCb_Data* src, + whMessageCustomCb_Data* dst) +{ + if (translatedType < WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START) { + switch (translatedType) { + case WH_MESSAGE_CUSTOM_CB_TYPE_QUERY: { + /* right now, no further translations required */ + } break; + case WH_MESSAGE_CUSTOM_CB_TYPE_DMA32: { + dst->dma32.client_addr = + wh_Translate32(magic, src->dma32.client_addr); + dst->dma32.client_sz = + wh_Translate32(magic, src->dma32.client_sz); + dst->dma32.server_addr = + wh_Translate32(magic, src->dma32.server_addr); + dst->dma32.server_sz = + wh_Translate32(magic, src->dma32.server_sz); + } break; + case WH_MESSAGE_CUSTOM_CB_TYPE_DMA64: { + dst->dma64.client_addr = + wh_Translate64(magic, src->dma64.client_addr); + dst->dma64.client_sz = + wh_Translate64(magic, src->dma64.client_sz); + dst->dma64.server_addr = + wh_Translate64(magic, src->dma64.server_addr); + dst->dma64.server_sz = + wh_Translate64(magic, src->dma64.server_sz); + } break; + default: { + /* reserved message types - no translation for now */ + } break; + } + } + else { + /* use memmove in case data is translated "in place" */ + memmove(dst->buffer.data, src->buffer.data, sizeof(dst->buffer.data)); + } +} + + +int wh_MessageCustomCb_TranslateRequest(uint16_t magic, + const whMessageCustomCb_Request* src, + whMessageCustomCb_Request* dst) +{ + if ((src == NULL) || (dst == NULL)) { + return WH_ERROR_BADARGS; + } + + dst->id = wh_Translate32(magic, src->id); + dst->type = wh_Translate32(magic, src->type); + _translateCustomData(magic, dst->type, &src->data, &dst->data); + + return WH_ERROR_OK; +} + + +int wh_MessageCustomCb_TranslateResponse(uint16_t magic, + const whMessageCustomCb_Response* src, + whMessageCustomCb_Response* dst) +{ + if ((src == NULL) || (dst == NULL)) { + return WH_ERROR_BADARGS; + } + + dst->rc = wh_Translate32(magic, src->rc); + dst->err = wh_Translate32(magic, src->err); + + /* TODO: should we continue to translate responses for err != 0? + * Probably still should...*/ + dst->id = wh_Translate32(magic, src->id); + dst->type = wh_Translate32(magic, src->type); + _translateCustomData(magic, dst->type, &src->data, &dst->data); + + return WH_ERROR_OK; +} \ No newline at end of file diff --git a/src/wh_server.c b/src/wh_server.c index e64725d8..edd9ee19 100644 --- a/src/wh_server.c +++ b/src/wh_server.c @@ -18,8 +18,8 @@ /* Server API's */ #include "wolfhsm/wh_server.h" -#include "wolfhsm/wh_server_crypto.h" #include "wolfhsm/wh_server_internal.h" +#include "wolfhsm/wh_server_crypto.h" #if defined(WOLFHSM_SHE_EXTENSION) #include "wolfhsm/wh_server_she.h" #endif @@ -44,11 +44,6 @@ static int _wh_Server_HandleSheRequest(whServerContext* server, uint16_t req_size, const void* req_packet, uint16_t *out_resp_size, void* resp_packet); #endif -static int _wh_Server_HandleCustomRequest(whServerContext* server, - uint16_t magic, uint16_t action, uint16_t seq, - uint16_t req_size, const void* req_packet, - uint16_t *out_resp_size, void* resp_packet); - int wh_Server_Init(whServerContext* server, whServerConfig* config) { @@ -215,20 +210,7 @@ static int _wh_Server_HandleSheRequest(whServerContext* server, } #endif -static int _wh_Server_HandleCustomRequest(whServerContext* server, - uint16_t magic, uint16_t action, uint16_t seq, - uint16_t req_size, const void* req_packet, - uint16_t *out_resp_size, void* resp_packet) -{ - int rc = 0; - switch (action) { - /* TODO: Add custom/user callback message handling here */ - default: - /* Unknown request. Respond with empty packet */ - *out_resp_size = 0; - } - return rc; -} + int wh_Server_HandleRequestMessage(whServerContext* server) { @@ -266,11 +248,11 @@ int wh_Server_HandleRequestMessage(whServerContext* server) rc = _wh_Server_HandleKeyRequest(server, magic, action, seq, size, data, &size, data); break; - + case WH_MESSAGE_GROUP_CRYPTO: rc = wh_Server_HandleCryptoRequest(server, action, data, &size); break; - + case WH_MESSAGE_GROUP_PKCS11: rc = _wh_Server_HandlePkcs11Request(server, magic, action, seq, size, data, &size, data); @@ -283,7 +265,7 @@ int wh_Server_HandleRequestMessage(whServerContext* server) #endif case WH_MESSAGE_GROUP_CUSTOM: - rc = _wh_Server_HandleCustomRequest(server, magic, action, seq, + rc = wh_Server_HandleCustomCbRequest(server, magic, action, seq, size, data, &size, data); break; diff --git a/src/wh_server_customcb.c b/src/wh_server_customcb.c new file mode 100644 index 00000000..5685b7bb --- /dev/null +++ b/src/wh_server_customcb.c @@ -0,0 +1,81 @@ +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_common.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_message.h" +#include "wolfhsm/wh_message_customcb.h" + + +int wh_Server_RegisterCustomCb(whServerContext* server, uint16_t action, + whServerCustomCb handler) +{ + if (NULL == server || NULL == handler || + action >= WH_CUSTOM_CB_NUM_CALLBACKS) { + return WH_ERROR_BADARGS; + } + + server->customHandlerTable[action] = handler; + + return WH_ERROR_OK; +} + + +int wh_Server_HandleCustomCbRequest(whServerContext* server, uint16_t magic, + uint16_t action, uint16_t seq, + uint16_t req_size, const void* req_packet, + uint16_t* out_resp_size, void* resp_packet) +{ + int rc = 0; + whMessageCustomCb_Request req = {0}; + whMessageCustomCb_Response resp = {0}; + + if (NULL == server || NULL == req_packet || NULL == resp_packet || + out_resp_size == NULL) { + return WH_ERROR_BADARGS; + } + + if (action >= WH_CUSTOM_CB_NUM_CALLBACKS) { + /* Invalid callback index */ + /* TODO: is this the appropriate error to return? */ + return WH_ERROR_BADARGS; + } + + if (req_size != sizeof(whMessageCustomCb_Request)) { + /* Request is malformed */ + return WH_ERROR_ABORTED; + } + + /* Translate the request */ + if ((rc = wh_MessageCustomCb_TranslateRequest(magic, req_packet, &req)) != + WH_ERROR_OK) { + return rc; + } + + if (server->customHandlerTable[action] != NULL) { + /* If this isn't a query to check if the callback exists, invoke the + * registered callback, storing the return value in the reponse */ + if (req.type != WH_MESSAGE_CUSTOM_CB_TYPE_QUERY) { + resp.rc = server->customHandlerTable[action](server, &req, &resp); + } + /* TODO: propagate other wolfHSM error codes (requires modifiying caller + * function) once generic server code supports it */ + resp.err = WH_ERROR_OK; + } + else { + /* No callback was registered, populate response error. We must + * return success to ensure the "error" response is sent */ + resp.err = WH_ERROR_NO_HANDLER; + } + + /* tag response with requested callback ID for client-side bookkeeping*/ + resp.id = req.id; + + /* Translate the response */ + if ((rc = wh_MessageCustomCb_TranslateResponse( + magic, &resp, resp_packet)) != WH_ERROR_OK) { + return rc; + } + + *out_resp_size = sizeof(resp); + + return WH_ERROR_OK; +} diff --git a/test/Makefile b/test/Makefile index c64a9283..489a6e52 100644 --- a/test/Makefile +++ b/test/Makefile @@ -80,11 +80,13 @@ SRC_C += \ $(WOLFHSM_DIR)/src/wh_flash_unit.c \ $(WOLFHSM_DIR)/src/wh_message_comm.c \ $(WOLFHSM_DIR)/src/wh_message_nvm.c \ + $(WOLFHSM_DIR)/src/wh_message_customcb.c \ $(WOLFHSM_DIR)/src/wh_nvm.c \ $(WOLFHSM_DIR)/src/wh_nvm_flash.c \ $(WOLFHSM_DIR)/src/wh_server.c \ $(WOLFHSM_DIR)/src/wh_server_nvm.c \ $(WOLFHSM_DIR)/src/wh_server_crypto.c \ + $(WOLFHSM_DIR)/src/wh_server_customcb.c \ $(WOLFHSM_DIR)/src/wh_client_cryptocb.c \ $(WOLFHSM_DIR)/src/wh_transport_mem.c \ $(WOLFHSM_DIR)/src/wh_flash_ramsim.c diff --git a/test/wh_test_clientserver.c b/test/wh_test_clientserver.c index 28010353..560d1a46 100644 --- a/test/wh_test_clientserver.c +++ b/test/wh_test_clientserver.c @@ -17,6 +17,7 @@ #include "wolfhsm/wh_flash_ramsim.h" #include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_message.h" #include "wolfhsm/wh_client.h" #if defined(WH_CFG_TEST_POSIX) @@ -31,6 +32,109 @@ #define REPEAT_COUNT 10 #define ONE_MS 1000 + +/* Dummy callback that loopback-copies client data */ +static int _customServerCb(whServerContext* server, + const whMessageCustomCb_Request* req, + whMessageCustomCb_Response* resp) +{ + uint8_t* serverPtr = NULL; + uint8_t* clientPtr = NULL; + size_t copySz = 0; + + if (req->type == WH_MESSAGE_CUSTOM_CB_TYPE_DMA64) { + clientPtr = (uint8_t*)((uintptr_t)req->data.dma64.client_addr); + serverPtr = (uint8_t*)((uintptr_t)req->data.dma64.server_addr); + resp->data.dma64.client_sz = req->data.dma64.server_sz; + copySz = req->data.dma64.server_sz; + } + else if (req->type == WH_MESSAGE_CUSTOM_CB_TYPE_DMA32) { + clientPtr = (uint8_t*)((uintptr_t)req->data.dma32.client_addr); + serverPtr = (uint8_t*)((uintptr_t)req->data.dma32.server_addr); + resp->data.dma32.client_sz = req->data.dma32.server_sz; + copySz = req->data.dma32.server_sz; + } + + memcpy(clientPtr, serverPtr, copySz); + + return req->id; +} + +/* Helper function to test client server callbacks. Client and server must be + * already initialized */ +static int _testCallbacks(whServerContext* server, whClientContext* client) +{ + size_t counter; + whMessageCustomCb_Request req = {0}; + whMessageCustomCb_Response resp = {0}; + uint16_t outId = 0; + int respErr = 0; + + const char input[] = "The answer to the ultimate question of life, the " + "universe and everything is 42"; + char output[sizeof(input)] = {0}; + + for (counter = 0; counter < WH_CUSTOM_CB_NUM_CALLBACKS; counter++) { + req.id = counter; + + /* Check that the callback shows as unregistered */ + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCheckRegisteredRequest(client, req.id)); + WH_TEST_RETURN_ON_FAIL(wh_Server_HandleRequestMessage(server)); + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbCheckRegisteredResponse(client, &outId, &respErr)); + WH_TEST_ASSERT_RETURN(outId == req.id); + WH_TEST_ASSERT_RETURN(respErr == WH_ERROR_NO_HANDLER); + + /* Test that calling an unregistered callback returns error */ + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbRequest(client, &req)); + WH_TEST_RETURN_ON_FAIL(wh_Server_HandleRequestMessage(server)); + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbResponse(client, &resp)); + WH_TEST_ASSERT_RETURN(resp.err == WH_ERROR_NO_HANDLER); + + /* Register a custom callback */ + WH_TEST_RETURN_ON_FAIL( + wh_Server_RegisterCustomCb(server, counter, _customServerCb)); + + /* Check that the callback now shows as registered */ + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCheckRegisteredRequest(client, req.id)); + WH_TEST_RETURN_ON_FAIL(wh_Server_HandleRequestMessage(server)); + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbCheckRegisteredResponse(client, &outId, &respErr)); + WH_TEST_ASSERT_RETURN(outId == req.id); + WH_TEST_ASSERT_RETURN(respErr == WH_ERROR_OK); + + /* prepare the rest of the request */ + if (sizeof(uintptr_t) == sizeof(uint64_t)) { + /* 64-bit host system */ + req.type = WH_MESSAGE_CUSTOM_CB_TYPE_DMA64; + req.data.dma64.server_addr = (uint64_t)((uintptr_t)input); + req.data.dma64.server_sz = sizeof(input); + req.data.dma64.client_addr = (uint64_t)((uintptr_t)output); + req.data.dma64.client_sz = 0; + } + else if (sizeof(uintptr_t) == sizeof(uint32_t)) { + /* 32-bit host system */ + req.type = WH_MESSAGE_CUSTOM_CB_TYPE_DMA32; + req.data.dma32.server_addr = (uint32_t)((uintptr_t)&input); + req.data.dma32.server_sz = sizeof(input); + req.data.dma32.client_addr = (uint32_t)((uintptr_t)output); + req.data.dma32.client_sz = 0; + } + + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbRequest(client, &req)); + WH_TEST_RETURN_ON_FAIL(wh_Server_HandleRequestMessage(server)); + WH_TEST_RETURN_ON_FAIL(wh_Client_CustomCbResponse(client, &resp)); + WH_TEST_ASSERT_RETURN(resp.err == WH_ERROR_OK); + WH_TEST_ASSERT_RETURN(resp.rc == counter); + WH_TEST_ASSERT_RETURN(0 == memcmp(output, input, sizeof(input))); + + memset(output, 0, sizeof(output)); + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); + } + + return WH_ERROR_OK; +} + + int whTest_ClientServerSequential(void) { int ret = 0; @@ -430,6 +534,9 @@ int whTest_ClientServerSequential(void) ret, server_rc, avail_size, avail_objects, reclaim_size, reclaim_objects); #endif + /* Test custom registered callbacks */ + WH_TEST_RETURN_ON_FAIL(_testCallbacks(server, client)); + WH_TEST_RETURN_ON_FAIL(wh_Server_Cleanup(server)); WH_TEST_RETURN_ON_FAIL(wh_Client_Cleanup(client)); diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 3b175b7a..cf7beedc 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -26,6 +26,7 @@ /* Component includes */ #include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_message_customcb.h" /* Client context */ struct whClientContext_t { @@ -177,4 +178,16 @@ int wh_Client_NvmReadDma(whClientContext* c, whNvmId id, whNvmSize offset, whNvmSize data_len, uint8_t* data, int32_t *out_rc); + +/* Client custom-callback support */ +int wh_Client_CustomCbRequest(whClientContext* c, const whMessageCustomCb_Request* req); +int wh_Client_CustomCbResponse(whClientContext* c, whMessageCustomCb_Response *resp); +/* Instructs server to query if a callback is registered */ +int wh_Client_CustomCheckRegisteredRequest(whClientContext* c, uint32_t id); +/* Processes a server response to callback query. OutId is set to the ID of the + * received query. ResponseError is set to WH_ERROR_OK if the callback is + * registered, and WH_ERROR_NO_HANDLER if not */ +int wh_Client_CustomCbCheckRegisteredResponse(whClientContext* c, uint16_t* outId, int* responseError); + + #endif /* WOLFHSM_WH_CLIENT_H_ */ diff --git a/wolfhsm/wh_common.h b/wolfhsm/wh_common.h index eda1adfd..f023c26e 100644 --- a/wolfhsm/wh_common.h +++ b/wolfhsm/wh_common.h @@ -98,4 +98,7 @@ typedef struct { extern const whManifest_ex manifests[WOLFHSM_NUM_MANIFESTS]; +/* Custom request shared defs */ +#define WH_CUSTOM_CB_NUM_CALLBACKS 8 + #endif /* WOLFHSM_WH_COMMON_H_ */ diff --git a/wolfhsm/wh_error.h b/wolfhsm/wh_error.h index 5ba1b9dc..d49ac946 100644 --- a/wolfhsm/wh_error.h +++ b/wolfhsm/wh_error.h @@ -24,6 +24,9 @@ enum { WH_ERROR_NOTBLANK = -413, /* Area is no blank */ WH_ERROR_NOTFOUND = -414, /* Matching object not found */ WH_ERROR_NOSPACE = -415, /* No available space */ + + /* Custom-callback status returns */ + WH_ERROR_NO_HANDLER = -420, /* No handler registered for action */ }; #endif /* WOLFHSM_WH_ERROR_H_ */ diff --git a/wolfhsm/wh_message.h b/wolfhsm/wh_message.h index dfe3e57e..3b794d41 100644 --- a/wolfhsm/wh_message.h +++ b/wolfhsm/wh_message.h @@ -23,8 +23,9 @@ enum { WH_MESSAGE_GROUP_SHE = 0x0700, /* SHE protocol */ WH_MESSAGE_GROUP_CUSTOM = 0x1000, /* User-specified features */ - WH_MESSAGE_ACTION_MASK = 0x00FF, /* 255 subtypes per group*/ - WH_MESSAGE_ACTION_NONE = 0x0000, /* No action. Invalid. */ + WH_MESSAGE_ACTION_MASK = 0x00FF, /* 255 subtypes per group*/ + WH_MESSAGE_ACTION_NONE = 0x0000, /* No action. Invalid. */ + WH_MESSAGE_ACTION_MAX = 0x00FF, /* Max action value */ }; /* Construct the message kind based on group and action */ diff --git a/wolfhsm/wh_message_customcb.h b/wolfhsm/wh_message_customcb.h new file mode 100644 index 00000000..c4b07213 --- /dev/null +++ b/wolfhsm/wh_message_customcb.h @@ -0,0 +1,79 @@ +#ifndef WH_MESSAGE_CUSTOM_CB_H_ +#define WH_MESSAGE_CUSTOM_CB_H_ + +#include + +#define WH_MESSAGE_CUSTOM_CB_BUF_SIZE (256) + +/* Type indicator for custom request/response messages. Indicates how + * to interpret whMessageCustomData */ +typedef enum { + /* message types reserved for internal usage*/ + WH_MESSAGE_CUSTOM_CB_TYPE_QUERY = 0, + WH_MESSAGE_CUSTOM_CB_TYPE_DMA32 = 1, + WH_MESSAGE_CUSTOM_CB_TYPE_DMA64 = 2, + WH_MESSAGE_CUSTOM_CB_TYPE_RESERVED_3 = 3, + WH_MESSAGE_CUSTOM_CB_TYPE_RESERVED_4 = 4, + WH_MESSAGE_CUSTOM_CB_TYPE_RESERVED_5 = 5, + WH_MESSAGE_CUSTOM_CB_TYPE_RESERVED_6 = 6, + WH_MESSAGE_CUSTOM_CB_TYPE_RESERVED_7 = 7, + /* User-defined types start from here, up to UINT32_MAX */ + WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START = 8, +} whMessageCustomCb_Type; + + +/* union providing some helpful abstractions for passing pointers in/out of + * custom callbacks on top of a raw data buffer */ +typedef union { + /* pointer/size pairs for 32-bit systems */ + struct { + uint32_t client_addr; + uint32_t client_sz; + uint32_t server_addr; + uint32_t server_sz; + } dma32; + /* pointer/size pairs for 64-bit systems */ + struct { + uint64_t client_addr; + uint64_t client_sz; + uint64_t server_addr; + uint64_t server_sz; + } dma64; + /* raw data buffer for user-defined schema */ + struct { + uint8_t data[WH_MESSAGE_CUSTOM_CB_BUF_SIZE]; + } buffer; +} whMessageCustomCb_Data; + +/* request message to the custom server callback */ +typedef struct { + uint32_t id; /* indentifier of registered callback */ + uint32_t type; /* whMessageCustomCb_Type */ + whMessageCustomCb_Data data; +} whMessageCustomCb_Request; + +/* response message from the custom server callback */ +typedef struct { + uint32_t id; /* indentifier of registered callback */ + uint32_t type; /* whMessageCustomCb_Type */ + int32_t rc; /* Return code from custom callback. Invalid if err != 0 */ + int32_t err; /* wolfHSM-specific error. If err != 0, rc is invalid */ + whMessageCustomCb_Data data; +} whMessageCustomCb_Response; + + +/* Translates a custom request message. The whMessageCustomCb_Request.data field + * will not be translated for whMessageCustomCb_Request.type values greater than + * WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START */ +int wh_MessageCustomCb_TranslateRequest(uint16_t magic, + const whMessageCustomCb_Request* src, + whMessageCustomCb_Request* dst); + +/* Translates a custom response message. The whMessageCustomCb_Request.data + * field will not be translated for whMessageCustomCb_Request.type values + * greater than WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START */ +int wh_MessageCustomCb_TranslateResponse(uint16_t magic, + const whMessageCustomCb_Response* src, + whMessageCustomCb_Response* dst); + +#endif /* WH_MESSAGE_CUSTOM_CB_H_*/ \ No newline at end of file diff --git a/wolfhsm/wh_server.h b/wolfhsm/wh_server.h index 226cc3ce..8944b767 100644 --- a/wolfhsm/wh_server.h +++ b/wolfhsm/wh_server.h @@ -12,6 +12,7 @@ #include "wolfhsm/wh_common.h" #include "wolfhsm/wh_comm.h" #include "wolfhsm/wh_nvm.h" +#include "wolfhsm/wh_message_customcb.h" #include "wolfssl/wolfcrypt/settings.h" #include "wolfssl/wolfcrypt/random.h" @@ -37,6 +38,17 @@ typedef struct { bool wcDevIdInitFlag: 1; } whServerFlags; +/* Forward declaration of the server structure so its elements can reference + * itself (e.g. server argument to custom callback) */ +struct whServerContext_t; + +/* Type definition for a custom server callback */ +typedef int (*whServerCustomCb)( + struct whServerContext_t* server, /* points to dispatching server ctx */ + const whMessageCustomCb_Request* req, /* request from client to callback */ + whMessageCustomCb_Response* resp /* response from callback to client */ +); + /* Context structure to maintain the state of an HSM server */ typedef struct whServerContext_t { whServerFlags flags; @@ -44,6 +56,7 @@ typedef struct whServerContext_t { whNvmContext nvm[1]; crypto_context crypto[1]; CacheSlot cache[WOLFHSM_NUM_RAMKEYS]; + whServerCustomCb customHandlerTable[WH_CUSTOM_CB_NUM_CALLBACKS]; } whServerContext; typedef struct whServerConfig_t { @@ -67,4 +80,15 @@ int wh_Server_HandleRequestMessage(whServerContext* server); */ int wh_Server_Cleanup(whServerContext* server); +/* Registers a custom callback with the server +*/ +int wh_Server_RegisterCustomCb(whServerContext* server, uint16_t actionId, whServerCustomCb cb); + +/* Receive and handle an incoming custom callback request +*/ +int wh_Server_HandleCustomCbRequest(whServerContext* server, uint16_t magic, + uint16_t action, uint16_t seq, + uint16_t req_size, const void* req_packet, + uint16_t* out_resp_size, void* resp_packet); + #endif /* WOLFHSM_WH_SERVER_H_ */