diff --git a/src/wh_nvm.c b/src/wh_nvm.c index a9b67a1c8..5b5512cd5 100644 --- a/src/wh_nvm.c +++ b/src/wh_nvm.c @@ -275,6 +275,10 @@ int wh_Nvm_AddObjectChecked(whNvmContext* context, const whNvmMetadata* meta, int ret; whNvmMetadata sanitized; + if (meta == NULL) { + return WH_ERROR_BADARGS; + } + ret = wh_Nvm_CheckPolicy(context, WH_NVM_OP_ADD, meta->id, NULL); if (ret != WH_ERROR_OK && ret != WH_ERROR_NOTFOUND) { return ret; diff --git a/src/wh_server_nvm.c b/src/wh_server_nvm.c index 9481db048..b73a767e1 100644 --- a/src/wh_server_nvm.c +++ b/src/wh_server_nvm.c @@ -394,6 +394,13 @@ int wh_Server_HandleNvmRequest(whServerContext* server, } } if (resp.rc == 0) { + /* A permit-all DMA config passes a zero metadata address through + * untouched, so reject it before it reaches the NVM layer. */ + if (metadata == NULL) { + resp.rc = WH_ERROR_BADARGS; + } + } + if (resp.rc == 0) { #if !defined(WOLFHSM_CFG_NO_CRYPTO) && \ (defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)) /* Block direct NVM import of stateful (LMS/XMSS) private key state; diff --git a/test-refactor/client-server/wh_test_nvm_ops.c b/test-refactor/client-server/wh_test_nvm_ops.c index 2460877d1..105aec5fa 100644 --- a/test-refactor/client-server/wh_test_nvm_ops.c +++ b/test-refactor/client-server/wh_test_nvm_ops.c @@ -457,9 +457,44 @@ static const WhNvmTestObjectOps g_dmaTestOps = { }; +/* A zero DMA address passes through the permit-all DMA config untouched, + * so the server must reject it, not dereference it. */ +static int _whTest_NvmDmaNullAddrs(whClientContext* ctx) +{ + whNvmMetadata meta = {0}; + int32_t server_rc = 0; + uint32_t client_id = 0; + uint32_t server_id = 0; + + WH_TEST_RETURN_ON_FAIL(wh_Client_NvmInit( + ctx, &server_rc, &client_id, &server_id)); + WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_OK); + + /* Zero metadata address */ + WH_TEST_RETURN_ON_FAIL(wh_Client_NvmAddObjectDma( + ctx, NULL, 0, NULL, &server_rc)); + WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_BADARGS); + + /* Valid metadata, but a zero data address with a non-zero length. + * The NVM backend rejects this rather than reading through it. */ + meta.id = NVM_TEST_DMA_ID_BASE; + meta.access = WH_NVM_ACCESS_ANY; + meta.flags = WH_NVM_FLAGS_NONE; + WH_TEST_RETURN_ON_FAIL(wh_Client_NvmAddObjectDma( + ctx, &meta, sizeof(meta), NULL, &server_rc)); + WH_TEST_ASSERT_RETURN(server_rc == WH_ERROR_BADARGS); + + return WH_ERROR_OK; +} + + int whTest_NvmDma(whClientContext* ctx) { - return _runNvmObjectTest(ctx, &g_dmaTestOps, NVM_TEST_DMA_ID_BASE); + WH_TEST_RETURN_ON_FAIL( + _runNvmObjectTest(ctx, &g_dmaTestOps, NVM_TEST_DMA_ID_BASE)); + WH_TEST_RETURN_ON_FAIL(_whTest_NvmDmaNullAddrs(ctx)); + + return WH_ERROR_OK; } #endif /* WOLFHSM_CFG_DMA */