diff --git a/src/wh_dma.c b/src/wh_dma.c index 0f6835b78..7126da005 100644 --- a/src/wh_dma.c +++ b/src/wh_dma.c @@ -99,9 +99,9 @@ static int _checkMemOperAgainstAllowList(const whDmaAddrAllowList* allowlist, return rc; } - /* If no allowlist is registered, anything goes */ + /* If no allowlist is registered, deny all operations (fail-closed) */ if (allowlist == NULL) { - return WH_ERROR_OK; + return WH_ERROR_ACCESS; } /* If a read/write operation is requested, check the transformed address diff --git a/src/wh_server_cert.c b/src/wh_server_cert.c index 06d1a211e..2640a57ab 100644 --- a/src/wh_server_cert.c +++ b/src/wh_server_cert.c @@ -556,9 +556,10 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, #ifdef WOLFHSM_CFG_DMA case WH_MESSAGE_CERT_ACTION_ADDTRUSTED_DMA: { - whMessageCert_AddTrustedDmaRequest req = {0}; - whMessageCert_SimpleResponse resp = {0}; - void* cert_data = NULL; + whMessageCert_AddTrustedDmaRequest req = {0}; + whMessageCert_SimpleResponse resp = {0}; + void* cert_data = NULL; + int cert_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -574,6 +575,9 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, resp.rc = wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (resp.rc == WH_ERROR_OK) { + cert_dma_pre_ok = 1; + } } if (resp.rc == WH_ERROR_OK) { /* Process the add trusted action */ @@ -586,9 +590,10 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, (void)WH_SERVER_NVM_UNLOCK(server); } /* WH_SERVER_NVM_LOCK() */ } - if (resp.rc == WH_ERROR_OK) { - /* Post-process client address */ - resp.rc = wh_Server_DmaProcessClientAddress( + /* Always call POST for successful PRE, regardless of operation + * result */ + if (cert_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); } @@ -600,11 +605,12 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, }; break; case WH_MESSAGE_CERT_ACTION_READTRUSTED_DMA: { - whMessageCert_ReadTrustedDmaRequest req = {0}; - whMessageCert_SimpleResponse resp = {0}; - void* cert_data = NULL; + whMessageCert_ReadTrustedDmaRequest req = {0}; + whMessageCert_SimpleResponse resp = {0}; + void* cert_data = NULL; uint32_t cert_len; whNvmMetadata meta; + int cert_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -620,6 +626,9 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, resp.rc = wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_WRITE_PRE, (whServerDmaFlags){0}); + if (resp.rc == WH_ERROR_OK) { + cert_dma_pre_ok = 1; + } } if (resp.rc == WH_ERROR_OK) { /* Check metadata to see if the certificate is non-exportable */ @@ -641,10 +650,11 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, (void)WH_SERVER_NVM_UNLOCK(server); } /* WH_SERVER_NVM_LOCK() */ } - if (resp.rc == WH_ERROR_OK) { - /* Post-process client address */ - resp.rc = wh_Server_DmaProcessClientAddress( - server, req.cert_addr, &cert_data, cert_len, + /* Always call POST for successful PRE, regardless of operation + * result */ + if (cert_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( + server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); } @@ -655,10 +665,11 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, }; break; case WH_MESSAGE_CERT_ACTION_VERIFY_DMA: { - whMessageCert_VerifyDmaRequest req = {0}; - whMessageCert_VerifyDmaResponse resp = {0}; - void* cert_data = NULL; - whKeyId keyId = WH_KEYID_ERASED; + whMessageCert_VerifyDmaRequest req = {0}; + whMessageCert_VerifyDmaResponse resp = {0}; + void* cert_data = NULL; + whKeyId keyId = WH_KEYID_ERASED; + int cert_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -677,6 +688,9 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, resp.rc = wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (resp.rc == WH_ERROR_OK) { + cert_dma_pre_ok = 1; + } } if (resp.rc == WH_ERROR_OK) { resp.rc = WH_SERVER_NVM_LOCK(server); @@ -693,9 +707,10 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, (void)WH_SERVER_NVM_UNLOCK(server); } /* WH_SERVER_NVM_LOCK() */ } - if (resp.rc == WH_ERROR_OK) { - /* Post-process client address */ - resp.rc = wh_Server_DmaProcessClientAddress( + /* Always call POST for successful PRE, regardless of operation + * result */ + if (cert_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); } @@ -766,9 +781,10 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, #if defined(WOLFHSM_CFG_DMA) case WH_MESSAGE_CERT_ACTION_VERIFY_ACERT_DMA: { /* Acert verify request uses standard cert verify request struct */ - whMessageCert_VerifyDmaRequest req = {0}; - whMessageCert_SimpleResponse resp = {0}; - void* cert_data = NULL; + whMessageCert_VerifyDmaRequest req = {0}; + whMessageCert_SimpleResponse resp = {0}; + void* cert_data = NULL; + int cert_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -783,6 +799,9 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, rc = wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (rc == WH_ERROR_OK) { + cert_dma_pre_ok = 1; + } } if (rc == WH_ERROR_OK) { /* Process the verify action */ @@ -805,9 +824,10 @@ int wh_Server_HandleCertRequest(whServerContext* server, uint16_t magic, resp.rc = rc; } } - if (rc == WH_ERROR_OK) { - /* Post-process client address */ - rc = wh_Server_DmaProcessClientAddress( + /* Always call POST for successful PRE, regardless of operation + * result */ + if (cert_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.cert_addr, &cert_data, req.cert_len, WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); } diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 0fb7bd130..3cad89146 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -4784,11 +4784,17 @@ static int _HandleSha256Dma(whServerContext* ctx, uint16_t magic, int devId, res.dmaAddrStatus.badAddr = req.state; } else { - /* Save the client devId to be restored later, when the context is - * copied back into client memory. */ - clientDevId = sha256->devId; - /* overwrite the devId to that of the server for local crypto */ - sha256->devId = devId; + /* Validate buffLen from untrusted context */ + if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) { + ret = WH_ERROR_BADARGS; + } + else { + /* Save the client devId to be restored later, when the context + * is copied back into client memory. */ + clientDevId = sha256->devId; + /* overwrite the devId to that of the server for local crypto */ + sha256->devId = devId; + } } } @@ -4906,11 +4912,17 @@ static int _HandleSha224Dma(whServerContext* ctx, uint16_t magic, int devId, res.dmaAddrStatus.badAddr = req.state; } else { - /* Save the client devId to be restored later, when the context is - * copied back into client memory. */ - clientDevId = sha224->devId; - /* overwrite the devId to that of the server for local crypto */ - sha224->devId = devId; + /* Validate buffLen from untrusted context */ + if (sha224->buffLen >= WC_SHA224_BLOCK_SIZE) { + ret = WH_ERROR_BADARGS; + } + else { + /* Save the client devId to be restored later, when the context + * is copied back into client memory. */ + clientDevId = sha224->devId; + /* overwrite the devId to that of the server for local crypto */ + sha224->devId = devId; + } } } @@ -5028,11 +5040,17 @@ static int _HandleSha384Dma(whServerContext* ctx, uint16_t magic, int devId, res.dmaAddrStatus.badAddr = req.state; } else { - /* Save the client devId to be restored later, when the context is - * copied back into client memory. */ - clientDevId = sha384->devId; - /* overwrite the devId to that of the server for local crypto */ - sha384->devId = devId; + /* Validate buffLen from untrusted context */ + if (sha384->buffLen >= WC_SHA384_BLOCK_SIZE) { + ret = WH_ERROR_BADARGS; + } + else { + /* Save the client devId to be restored later, when the context + * is copied back into client memory. */ + clientDevId = sha384->devId; + /* overwrite the devId to that of the server for local crypto */ + sha384->devId = devId; + } } } @@ -5150,13 +5168,25 @@ static int _HandleSha512Dma(whServerContext* ctx, uint16_t magic, int devId, res.dmaAddrStatus.badAddr = req.state; } else { - /* Save the client devId to be restored later, when the context is - * copied back into client memory. */ - clientDevId = sha512->devId; - /* overwrite the devId to that of the server for local crypto */ - sha512->devId = devId; - /* retrieve hash Type to handle 512, 512-224, or 512-256 */ - hashType = sha512->hashType; + /* Validate buffLen from untrusted context */ + if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE) { + ret = WH_ERROR_BADARGS; + } + else { + /* Save the client devId to be restored later, when the context + * is copied back into client memory. */ + clientDevId = sha512->devId; + /* overwrite the devId to that of the server for local crypto */ + sha512->devId = devId; + /* retrieve hash Type to handle 512, 512-224, or 512-256 */ + hashType = sha512->hashType; + /* Validate hashType from untrusted context */ + if (hashType != WC_HASH_TYPE_SHA512 && + hashType != WC_HASH_TYPE_SHA512_224 && + hashType != WC_HASH_TYPE_SHA512_256) { + ret = WH_ERROR_BADARGS; + } + } } } diff --git a/src/wh_server_dma.c b/src/wh_server_dma.c index 5843f33d2..023aeaddf 100644 --- a/src/wh_server_dma.c +++ b/src/wh_server_dma.c @@ -131,15 +131,7 @@ int whServerDma_CopyFromClient(struct whServerContext_t* server, return WH_ERROR_BADARGS; } - /* Check the server address against the allow list */ - rc = wh_Dma_CheckMemOperAgainstAllowList(server->dma.dmaAddrAllowList, - WH_DMA_OPER_CLIENT_READ_PRE, - serverPtr, len); - if (rc != WH_ERROR_OK) { - return rc; - } - - /* Process the client address pre-read */ + /* Process the client address pre-read (includes allow list check) */ rc = wh_Server_DmaProcessClientAddress( server, clientAddr, &transformedAddr, len, WH_DMA_OPER_CLIENT_READ_PRE, flags); @@ -185,15 +177,7 @@ int whServerDma_CopyToClient(struct whServerContext_t* server, return WH_ERROR_BADARGS; } - /* Check the server address against the allow list */ - rc = wh_Dma_CheckMemOperAgainstAllowList(server->dma.dmaAddrAllowList, - WH_DMA_OPER_CLIENT_WRITE_PRE, - serverPtr, len); - if (rc != WH_ERROR_OK) { - return rc; - } - - /* Process the client address pre-write */ + /* Process the client address pre-write (includes allow list check) */ rc = wh_Server_DmaProcessClientAddress(server, clientAddr, &transformedAddr, len, WH_DMA_OPER_CLIENT_WRITE_PRE, flags); diff --git a/src/wh_server_nvm.c b/src/wh_server_nvm.c index c8e20efab..f5597b6b8 100644 --- a/src/wh_server_nvm.c +++ b/src/wh_server_nvm.c @@ -349,6 +349,8 @@ int wh_Server_HandleNvmRequest(whServerContext* server, whMessageNvm_SimpleResponse resp = {0}; void* metadata = NULL; void* data = NULL; + int metadata_dma_pre_ok = 0; + int data_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -363,11 +365,17 @@ int wh_Server_HandleNvmRequest(whServerContext* server, resp.rc = wh_Server_DmaProcessClientAddress( server, req.metadata_hostaddr, &metadata, sizeof(whNvmMetadata), WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (resp.rc == 0) { + metadata_dma_pre_ok = 1; + } } if (resp.rc == 0) { resp.rc = wh_Server_DmaProcessClientAddress( server, req.data_hostaddr, &data, req.data_len, WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (resp.rc == 0) { + data_dma_pre_ok = 1; + } } if (resp.rc == 0) { rc = WH_SERVER_NVM_LOCK(server); @@ -381,14 +389,15 @@ int wh_Server_HandleNvmRequest(whServerContext* server, } /* WH_SERVER_NVM_LOCK() */ resp.rc = rc; } - if (resp.rc == 0) { - /* perform platform-specific host address processing */ - resp.rc = wh_Server_DmaProcessClientAddress( + /* Always call POST for successful PREs, regardless of operation + * result */ + if (metadata_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.metadata_hostaddr, &metadata, sizeof(whNvmMetadata), WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); } - if (resp.rc == 0) { - resp.rc = wh_Server_DmaProcessClientAddress( + if (data_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.data_hostaddr, &data, req.data_len, WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); } @@ -405,6 +414,7 @@ int wh_Server_HandleNvmRequest(whServerContext* server, whNvmMetadata meta = {0}; whNvmSize read_len = 0; void* data = NULL; + int data_dma_pre_ok = 0; if (req_size != sizeof(req)) { /* Request is malformed */ @@ -441,15 +451,19 @@ int wh_Server_HandleNvmRequest(whServerContext* server, rc = wh_Server_DmaProcessClientAddress( server, req.data_hostaddr, &data, req.data_len, WH_DMA_OPER_CLIENT_WRITE_PRE, (whServerDmaFlags){0}); + if (rc == 0) { + data_dma_pre_ok = 1; + } } if (rc == 0) { /* Process the Read action */ rc = wh_Nvm_ReadChecked(server->nvm, req.id, req.offset, read_len, (uint8_t*)data); } - if (rc == 0) { - /* perform platform-specific host address processing */ - rc = wh_Server_DmaProcessClientAddress( + /* Always call POST for successful PRE, regardless of read + * result */ + if (data_dma_pre_ok) { + (void)wh_Server_DmaProcessClientAddress( server, req.data_hostaddr, &data, req.data_len, WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); } diff --git a/test/wh_test_clientserver.c b/test/wh_test_clientserver.c index f0ef41048..10fc2b630 100644 --- a/test/wh_test_clientserver.c +++ b/test/wh_test_clientserver.c @@ -351,18 +351,6 @@ static int _testDma(whServerContext* server, whClientContext* client) WH_TEST_ASSERT_RETURN(0 == memcmp(testMem.srvBufAllow, testMem.cliBuf, sizeof(testMem.srvBufAllow))); - /* Now try and copy from the denylisted addresses */ - WH_TEST_ASSERT_RETURN(WH_ERROR_ACCESS == - whServerDma_CopyFromClient(server, testMem.srvBufDeny, - (uintptr_t)testMem.cliBuf, - sizeof(testMem.cliBuf), - (whServerDmaFlags){0})); - WH_TEST_ASSERT_RETURN( - WH_ERROR_ACCESS == - whServerDma_CopyToClient(server, (uintptr_t)testMem.cliBuf, - testMem.srvBufDeny, sizeof(testMem.srvBufDeny), - (whServerDmaFlags){0})); - /* Check that zero-sized copies fail, even from allowed addresses */ WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == whServerDma_CopyFromClient( server, testMem.srvBufAllow, @@ -397,6 +385,21 @@ static int _testDma(whServerContext* server, whClientContext* client) testMem.srvRemapBufAllow, sizeof(testMem.srvBufAllow))); + /* Check that out-of-allowlist client addresses are rejected (done after + * clearing the custom DMA callback to avoid the callback remapping the + * deny address out of bounds) */ + WH_TEST_ASSERT_RETURN(WH_ERROR_ACCESS == whServerDma_CopyFromClient( + server, testMem.srvBufAllow, + (uintptr_t)testMem.srvBufDeny, + sizeof(testMem.srvBufAllow), + (whServerDmaFlags){0})); + WH_TEST_ASSERT_RETURN(WH_ERROR_ACCESS == + whServerDma_CopyToClient( + server, (uintptr_t)testMem.srvBufDeny, + testMem.srvBufAllow, + sizeof(testMem.srvBufAllow), + (whServerDmaFlags){0})); + return rc; } #endif /* WOLFHSM_CFG_DMA && WOLFHSM_CFG_ENABLE_CLIENT && \ @@ -972,16 +975,30 @@ int whTest_ClientServerSequential(whTestNvmBackendType nvmType) WH_TEST_ASSERT_RETURN(avail_objects == WOLFHSM_CFG_NVM_OBJECT_COUNT); #ifdef WOLFHSM_CFG_DMA + { + /* Register DMA allow list for the buffers used in DMA NVM tests. + * static so the server's retained pointer remains valid */ + static whNvmMetadata meta; + static whServerDmaAddrAllowList nvm_dma_allow; + memset(&meta, 0, sizeof(meta)); + memset(&nvm_dma_allow, 0, sizeof(nvm_dma_allow)); + nvm_dma_allow.readList[0].addr = send_buffer; + nvm_dma_allow.readList[0].size = sizeof(send_buffer); + nvm_dma_allow.readList[1].addr = &meta; + nvm_dma_allow.readList[1].size = sizeof(meta); + nvm_dma_allow.writeList[0].addr = recv_buffer; + nvm_dma_allow.writeList[0].size = sizeof(recv_buffer); + WH_TEST_RETURN_ON_FAIL( + wh_Server_DmaRegisterAllowList(server, &nvm_dma_allow)); + /* Same writeback test, but with DMA */ for (counter = 0; counter < 5; counter++) { - whNvmMetadata meta = { - .id = counter + 40, - .access = WH_NVM_ACCESS_ANY, - .flags = WH_NVM_FLAGS_NONE, - .len = 0, - .label = {0}, - }; whNvmSize len = 0; + meta.id = counter + 40; + meta.access = WH_NVM_ACCESS_ANY; + meta.flags = WH_NVM_FLAGS_NONE; + meta.len = 0; + memset(meta.label, 0, sizeof(meta.label)); whNvmId gid = 0; whNvmAccess gaccess = 0; @@ -1121,6 +1138,7 @@ int whTest_ClientServerSequential(whTestNvmBackendType nvmType) WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_OK); WH_TEST_ASSERT_RETURN(avail_objects == WOLFHSM_CFG_NVM_OBJECT_COUNT); + } /* DMA allow list scope */ #endif /* WOLFHSM_CFG_DMA */ /* Test custom registered callbacks */ @@ -1159,6 +1177,31 @@ int whTest_ClientServerSequential(whTestNvmBackendType nvmType) #endif /* WOLFHSM_CFG_ENABLE_CLIENT && WOLFHSM_CFG_ENABLE_SERVER */ #ifdef WOLFHSM_CFG_ENABLE_CLIENT + +#ifdef WOLFHSM_CFG_DMA +/* File-scope buffers for the client-config DMA tests so the server thread's + * allow list can reference them */ +static char _ccfg_send[WOLFHSM_CFG_COMM_DATA_LEN]; +static char _ccfg_recv[WOLFHSM_CFG_COMM_DATA_LEN]; +static whNvmMetadata _ccfg_meta; +static whServerDmaAddrAllowList _ccfg_dmaAllowList; +static whServerDmaConfig _ccfg_serverDmaConfig; + +static void _initClientCfgDma(void) +{ + memset(&_ccfg_dmaAllowList, 0, sizeof(_ccfg_dmaAllowList)); + _ccfg_dmaAllowList.readList[0].addr = _ccfg_send; + _ccfg_dmaAllowList.readList[0].size = sizeof(_ccfg_send); + _ccfg_dmaAllowList.readList[1].addr = &_ccfg_meta; + _ccfg_dmaAllowList.readList[1].size = sizeof(_ccfg_meta); + _ccfg_dmaAllowList.writeList[0].addr = _ccfg_recv; + _ccfg_dmaAllowList.writeList[0].size = sizeof(_ccfg_recv); + + memset(&_ccfg_serverDmaConfig, 0, sizeof(_ccfg_serverDmaConfig)); + _ccfg_serverDmaConfig.dmaAddrAllowList = &_ccfg_dmaAllowList; +} +#endif /* WOLFHSM_CFG_DMA */ + int whTest_ClientServerClientConfig(whClientConfig* clientCfg) { int ret = 0; @@ -1167,8 +1210,15 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) WH_TEST_RETURN_ON_FAIL(wh_Client_Init(client, clientCfg)); int counter = 1; - char recv_buffer[WOLFHSM_CFG_COMM_DATA_LEN] = {0}; - char send_buffer[WOLFHSM_CFG_COMM_DATA_LEN] = {0}; +#ifdef WOLFHSM_CFG_DMA + char* recv_buffer = _ccfg_recv; + char* send_buffer = _ccfg_send; +#else + char recv_buffer[WOLFHSM_CFG_COMM_DATA_LEN]; + char send_buffer[WOLFHSM_CFG_COMM_DATA_LEN]; +#endif + memset(recv_buffer, 0, WOLFHSM_CFG_COMM_DATA_LEN); + memset(send_buffer, 0, WOLFHSM_CFG_COMM_DATA_LEN); uint16_t send_len = 0; uint16_t recv_len = 0; @@ -1189,8 +1239,8 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) /* Prepare echo test */ send_len = - snprintf(send_buffer, sizeof(send_buffer), "Request:%u", counter); - (void)snprintf(recv_buffer, sizeof(recv_buffer), "NOTHING RECEIVED"); + snprintf(send_buffer, WOLFHSM_CFG_COMM_DATA_LEN, "Request:%u", counter); + (void)snprintf(recv_buffer, WOLFHSM_CFG_COMM_DATA_LEN, "NOTHING RECEIVED"); recv_len = 0; WH_TEST_RETURN_ON_FAIL(ret = wh_Client_Echo(client, send_len, send_buffer, &recv_len, recv_buffer)); @@ -1249,8 +1299,8 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) whNvmId lastAvailObjects = 0; label_len = snprintf(label, sizeof(label), "Label:%d", id); - len = snprintf(send_buffer, sizeof(send_buffer), "Data:%d Counter:%d", - id, counter); + len = snprintf(send_buffer, WOLFHSM_CFG_COMM_DATA_LEN, + "Data:%d Counter:%d", id, counter); lastAvailObjects = avail_objects; @@ -1288,7 +1338,7 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_OK); WH_TEST_ASSERT_RETURN(gid == id); - memset(recv_buffer, 0, sizeof(recv_buffer)); + memset(recv_buffer, 0, WOLFHSM_CFG_COMM_DATA_LEN); WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmRead(client, id, 0, glen, &server_rc, &rlen, (uint8_t*)recv_buffer)); @@ -1350,15 +1400,16 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) WH_TEST_ASSERT_RETURN(avail_objects == WOLFHSM_CFG_NVM_OBJECT_COUNT); #ifdef WOLFHSM_CFG_DMA - /* Same writeback test, but with DMA */ + /* Same writeback test, but with DMA. + * Uses file-scope buffers so the server thread's DMA allow list can + * reference them (configured in wh_ClientServer_MemThreadTest). */ for (counter = 0; counter < 5; counter++) { - whNvmMetadata meta = { - .id = counter + 40, - .access = WH_NVM_ACCESS_ANY, - .flags = WH_NVM_FLAGS_NONE, - .len = 0, - .label = {0}, - }; + whNvmMetadata* meta = &_ccfg_meta; + memset(meta, 0, sizeof(*meta)); + meta->id = counter + 40; + meta->access = WH_NVM_ACCESS_ANY; + meta->flags = WH_NVM_FLAGS_NONE; + meta->len = 0; whNvmSize len = 0; whNvmId gid = 0; @@ -1369,16 +1420,16 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) whNvmId lastAvailObjects = 0; - snprintf((char*)(meta.label), sizeof(meta.label), "Label:%d", meta.id); - len = snprintf(send_buffer, sizeof(send_buffer), "Data:%d Counter:%d", - meta.id, counter); + snprintf((char*)(meta->label), sizeof(meta->label), "Label:%d", meta->id); + len = snprintf(send_buffer, WOLFHSM_CFG_COMM_DATA_LEN, + "Data:%d Counter:%d", meta->id, counter); lastAvailObjects = avail_objects; - WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmAddObjectDma(client, &meta, len, (uint8_t*)send_buffer, &server_rc)); + WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmAddObjectDma(client, meta, len, (uint8_t*)send_buffer, &server_rc)); WH_TEST_PRINT("Client NvmAddObjectDma:%d, server_rc:%d, meta.len:%u\n", - ret, (int)server_rc, meta.len); + ret, (int)server_rc, meta->len); WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_OK); WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmGetAvailable(client, &server_rc, &avail_size, &avail_objects, &reclaim_size, &reclaim_objects)); @@ -1389,7 +1440,7 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) (int)reclaim_size, (int)reclaim_objects); WH_TEST_ASSERT_RETURN(lastAvailObjects - 1 == avail_objects); - WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmGetMetadata(client, meta.id, &server_rc, &gid, &gaccess, &gflags, &glen, sizeof(glabel), (uint8_t*)glabel)); + WH_TEST_RETURN_ON_FAIL(ret = wh_Client_NvmGetMetadata(client, meta->id, &server_rc, &gid, &gaccess, &gflags, &glen, sizeof(glabel), (uint8_t*)glabel)); WH_TEST_PRINT("Client NvmGetMetadata:%d, id:%u, access:0x%x, " "flags:0x%x, len:%u label:%s\n", @@ -1397,12 +1448,12 @@ int whTest_ClientServerClientConfig(whClientConfig* clientCfg) (unsigned int)gflags, (unsigned int)glen, glabel); /* Ensure metadata matches that of the object we just wrote */ - WH_TEST_ASSERT_RETURN(gid == meta.id); + WH_TEST_ASSERT_RETURN(gid == meta->id); - memset(recv_buffer, 0, sizeof(recv_buffer)); + memset(recv_buffer, 0, WOLFHSM_CFG_COMM_DATA_LEN); WH_TEST_RETURN_ON_FAIL( - ret = wh_Client_NvmReadDma(client, meta.id, 0, glen, + ret = wh_Client_NvmReadDma(client, meta->id, 0, glen, (uint8_t*)recv_buffer, &server_rc)); WH_TEST_PRINT("Client NvmReadDma:%d, server_rc:%d id:%u, len:%u " "data:%s\n", @@ -1639,12 +1690,19 @@ static int wh_ClientServer_MemThreadTest(whTestNvmBackendType nvmType) #endif +#ifdef WOLFHSM_CFG_DMA + _initClientCfgDma(); +#endif + whServerConfig s_conf[1] = {{ .comm_config = cs_conf, .nvm = nvm, #ifndef WOLFHSM_CFG_NO_CRYPTO .crypto = crypto, .devId = INVALID_DEVID, +#endif +#ifdef WOLFHSM_CFG_DMA + .dmaConfig = &_ccfg_serverDmaConfig, #endif }}; diff --git a/test/wh_test_dma.c b/test/wh_test_dma.c index d57e0bccd..a8c46243e 100644 --- a/test/wh_test_dma.c +++ b/test/wh_test_dma.c @@ -65,11 +65,11 @@ static int whTest_DmaAllowListBasic(void) (void*)((uintptr_t)0x10000), 0); WH_TEST_ASSERT_RETURN(rc == WH_ERROR_BADARGS); - WH_TEST_PRINT(" Testing NULL allowlist passthrough...\n"); + WH_TEST_PRINT(" Testing NULL allowlist denial (fail-closed)...\n"); rc = wh_Dma_CheckMemOperAgainstAllowList( NULL, WH_DMA_OPER_CLIENT_READ_PRE, (void*)((uintptr_t)0x10000), 0x1000); - WH_TEST_ASSERT_RETURN(rc == WH_ERROR_OK); + WH_TEST_ASSERT_RETURN(rc == WH_ERROR_ACCESS); return WH_ERROR_OK; } diff --git a/test/wh_test_multiclient.c b/test/wh_test_multiclient.c index 8e54e9e64..9e31807d1 100644 --- a/test/wh_test_multiclient.c +++ b/test/wh_test_multiclient.c @@ -442,13 +442,40 @@ static int _testGlobalKeyDma(whClientContext* client1, whServerContext* server1, int ret; whKeyId keyId1 = WH_CLIENT_KEYID_MAKE_GLOBAL(DUMMY_KEYID_1); whKeyId keyId2 = WH_CLIENT_KEYID_MAKE_GLOBAL(DUMMY_KEYID_2); - uint8_t keyData1[32] = "GlobalDmaCacheTestKey123456!"; - uint8_t keyData2[32] = "GlobalDmaExportTestKey12345!"; - uint8_t outBuf[32] = {0}; + /* Use static buffers so addresses are stable for DMA allow list */ + static uint8_t keyData1[32]; + static uint8_t keyData2[32]; + static uint8_t outBuf[32]; uint8_t label[WH_NVM_LABEL_LEN]; uint16_t labelSz = sizeof(label); uint16_t outSz; + static whServerDmaAddrAllowList dmaAllowList = {0}; + + memset(keyData1, 0, sizeof(keyData1)); + memcpy(keyData1, "GlobalDmaCacheTestKey123456!", + sizeof("GlobalDmaCacheTestKey123456!") - 1); + memset(keyData2, 0, sizeof(keyData2)); + memcpy(keyData2, "GlobalDmaExportTestKey12345!", + sizeof("GlobalDmaExportTestKey12345!") - 1); + memset(outBuf, 0, sizeof(outBuf)); + + /* Register DMA allow list for both servers and clients */ + dmaAllowList.readList[0].addr = keyData1; + dmaAllowList.readList[0].size = sizeof(keyData1); + dmaAllowList.readList[1].addr = keyData2; + dmaAllowList.readList[1].size = sizeof(keyData2); + dmaAllowList.writeList[0].addr = outBuf; + dmaAllowList.writeList[0].size = sizeof(outBuf); + WH_TEST_RETURN_ON_FAIL( + wh_Server_DmaRegisterAllowList(server1, &dmaAllowList)); + WH_TEST_RETURN_ON_FAIL( + wh_Server_DmaRegisterAllowList(server2, &dmaAllowList)); + WH_TEST_RETURN_ON_FAIL( + wh_Client_DmaRegisterAllowList(client1, &dmaAllowList)); + WH_TEST_RETURN_ON_FAIL( + wh_Client_DmaRegisterAllowList(client2, &dmaAllowList)); + WH_TEST_PRINT("Test: DMA operations with global keys\n"); /* Part 1: Cache via DMA, export via regular */ diff --git a/test/wh_test_posix_threadsafe_stress.c b/test/wh_test_posix_threadsafe_stress.c index e66db7e16..6c3117521 100644 --- a/test/wh_test_posix_threadsafe_stress.c +++ b/test/wh_test_posix_threadsafe_stress.c @@ -501,6 +501,12 @@ typedef struct { /* Per-client DMA buffers */ uint8_t dmaKeyBuffer[KEY_DATA_SIZE]; uint8_t dmaNvmBuffer[NVM_OBJECT_DATA_SIZE]; + whNvmMetadata dmaNvmMeta; + /* DMA configuration */ + whServerDmaConfig dmaConfig; + whServerDmaAddrAllowList dmaAllowList; + whClientDmaConfig clientDmaConfig; + whDmaAddrAllowList clientDmaAllowList; #endif } ClientServerPair; @@ -654,6 +660,43 @@ static int initClientServerPair(StressTestContext* ctx, int pairIndex) pair->serverConfig.crypto = &pair->cryptoCtx; pair->serverConfig.devId = INVALID_DEVID; +#ifdef WOLFHSM_CFG_DMA + /* Configure DMA allow list for this pair's buffers */ + memset(&pair->dmaAllowList, 0, sizeof(pair->dmaAllowList)); + pair->dmaAllowList.readList[0].addr = pair->dmaKeyBuffer; + pair->dmaAllowList.readList[0].size = sizeof(pair->dmaKeyBuffer); + pair->dmaAllowList.readList[1].addr = pair->dmaNvmBuffer; + pair->dmaAllowList.readList[1].size = sizeof(pair->dmaNvmBuffer); + pair->dmaAllowList.readList[2].addr = &pair->dmaNvmMeta; + pair->dmaAllowList.readList[2].size = sizeof(pair->dmaNvmMeta); + + pair->dmaAllowList.writeList[0].addr = pair->dmaKeyBuffer; + pair->dmaAllowList.writeList[0].size = sizeof(pair->dmaKeyBuffer); + pair->dmaAllowList.writeList[1].addr = pair->dmaNvmBuffer; + pair->dmaAllowList.writeList[1].size = sizeof(pair->dmaNvmBuffer); + + memset(&pair->dmaConfig, 0, sizeof(pair->dmaConfig)); + pair->dmaConfig.dmaAddrAllowList = &pair->dmaAllowList; + pair->serverConfig.dmaConfig = &pair->dmaConfig; + + /* Configure client DMA allow list (same buffers) */ + memset(&pair->clientDmaAllowList, 0, sizeof(pair->clientDmaAllowList)); + pair->clientDmaAllowList.readList[0].addr = pair->dmaKeyBuffer; + pair->clientDmaAllowList.readList[0].size = sizeof(pair->dmaKeyBuffer); + pair->clientDmaAllowList.readList[1].addr = pair->dmaNvmBuffer; + pair->clientDmaAllowList.readList[1].size = sizeof(pair->dmaNvmBuffer); + pair->clientDmaAllowList.readList[2].addr = &pair->dmaNvmMeta; + pair->clientDmaAllowList.readList[2].size = sizeof(pair->dmaNvmMeta); + pair->clientDmaAllowList.writeList[0].addr = pair->dmaKeyBuffer; + pair->clientDmaAllowList.writeList[0].size = sizeof(pair->dmaKeyBuffer); + pair->clientDmaAllowList.writeList[1].addr = pair->dmaNvmBuffer; + pair->clientDmaAllowList.writeList[1].size = sizeof(pair->dmaNvmBuffer); + + memset(&pair->clientDmaConfig, 0, sizeof(pair->clientDmaConfig)); + pair->clientDmaConfig.dmaAddrAllowList = &pair->clientDmaAllowList; + pair->clientConfig.dmaConfig = &pair->clientDmaConfig; +#endif + /* Initialize client in the main thread to avoid concurrent calls to * wolfCrypt_Init() and wc_CryptoCb_RegisterDevice() */ rc = wh_Client_Init(&pair->client, &pair->clientConfig); @@ -1191,24 +1234,24 @@ static int doKeyExportDma(ClientServerPair* pair, whKeyId keyId) static int doNvmAddObjectDma(ClientServerPair* pair, whNvmId id, int iteration) { - whNvmMetadata meta; - int32_t out_rc; - int rc; + int32_t out_rc; + int rc; /* Fill DMA buffer with pattern */ memset(pair->dmaNvmBuffer, (uint8_t)(iteration & 0xFF), sizeof(pair->dmaNvmBuffer)); - /* Set up metadata */ - memset(&meta, 0, sizeof(meta)); - meta.id = id; - meta.access = WH_NVM_ACCESS_ANY; - meta.flags = WH_NVM_FLAGS_USAGE_ANY; - meta.len = sizeof(pair->dmaNvmBuffer); + /* Set up metadata in pair struct so address is in the DMA allow list */ + memset(&pair->dmaNvmMeta, 0, sizeof(pair->dmaNvmMeta)); + pair->dmaNvmMeta.id = id; + pair->dmaNvmMeta.access = WH_NVM_ACCESS_ANY; + pair->dmaNvmMeta.flags = WH_NVM_FLAGS_USAGE_ANY; + pair->dmaNvmMeta.len = sizeof(pair->dmaNvmBuffer); /* Send DMA request */ rc = wh_Client_NvmAddObjectDmaRequest( - &pair->client, &meta, sizeof(pair->dmaNvmBuffer), pair->dmaNvmBuffer); + &pair->client, &pair->dmaNvmMeta, sizeof(pair->dmaNvmBuffer), + pair->dmaNvmBuffer); if (rc != WH_ERROR_OK) { return rc; } diff --git a/wolfhsm/wh_server.h b/wolfhsm/wh_server.h index 153cd82dc..57294be10 100644 --- a/wolfhsm/wh_server.h +++ b/wolfhsm/wh_server.h @@ -372,7 +372,7 @@ int wh_Server_DmaRegisterAllowList(struct whServerContext_t* server, * This function verifies whether a specified DMA memory operation is permitted * by checking the operation type and the address range against the server's * registered allowlist. If no allowlist is registered, the operation is - * allowed. + * denied (fail-closed). * * @param[in] server Pointer to the server context. * @param[in] oper The DMA operation type (e.g., read or write).