diff --git a/.gitignore b/.gitignore index 95423d4..345816b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ -.DS_Store -Build/ -*.o -*.a -*.la - +.DS_Store +Build/ +*.o +*.a +*.la +**/.gdb_history + diff --git a/src/wh_client.c b/src/wh_client.c index 3adec46..27286ed 100644 --- a/src/wh_client.c +++ b/src/wh_client.c @@ -1211,14 +1211,12 @@ int wh_Client_KeyCacheDma32Request(whClientContext* c, uint32_t flags, packet->keyCacheDma32Req.key.addr = keyAddr; packet->keyCacheDma32Req.key.sz = keySz; - /* Copy label if provided */ + /* Copy label if provided, truncate if necessary */ if (labelSz > 0) { if (labelSz > WH_NVM_LABEL_LEN) { - memcpy(packet->keyCacheDma32Req.label, label, WH_NVM_LABEL_LEN); - } - else { - memcpy(packet->keyCacheDma32Req.label, label, labelSz); + labelSz = WH_NVM_LABEL_LEN; } + memcpy(packet->keyCacheDma32Req.label, label, labelSz); } return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_CACHE_DMA32, @@ -1377,14 +1375,12 @@ int wh_Client_KeyCacheDma64Request(whClientContext* c, uint32_t flags, packet->keyCacheDma64Req.key.addr = keyAddr; packet->keyCacheDma64Req.key.sz = keySz; - /* Copy label if provided */ + /* Copy label if provided, truncate if necessary */ if (labelSz > 0) { if (labelSz > WH_NVM_LABEL_LEN) { - memcpy(packet->keyCacheDma64Req.label, label, WH_NVM_LABEL_LEN); - } - else { - memcpy(packet->keyCacheDma64Req.label, label, labelSz); + labelSz = WH_NVM_LABEL_LEN; } + memcpy(packet->keyCacheDma64Req.label, label, labelSz); } return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_CACHE_DMA64, diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index faca704..86c5b01 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -53,6 +53,7 @@ #include "wolfssl/wolfcrypt/rsa.h" #include "wolfssl/wolfcrypt/ecc.h" #include "wolfssl/wolfcrypt/curve25519.h" +#include "wolfssl/wolfcrypt/dilithium.h" /* Message definitions */ #include "wolfhsm/wh_message.h" @@ -90,6 +91,20 @@ static int _RsaMakeKey(whClientContext* ctx, whKeyId *inout_key_id, RsaKey* rsa); #endif +#ifdef HAVE_DILITHIUM +/* Make a ML-DSA key on the server based on the flags */ +static int _MlDsaMakeKey(whClientContext* ctx, + int size, int level, + whKeyId *inout_key_id, whNvmFlags flags, + uint16_t label_len, uint8_t* label, + MlDsaKey* key); + +#ifdef WOLFHSM_CFG_DMA +static int _MlDsaMakeKeyDma(whClientContext* ctx, int level, + whKeyId* inout_key_id, whNvmFlags flags, + uint16_t label_len, uint8_t* label, MlDsaKey* key); +#endif /* WOLFHSM_CFG_DMA */ +#endif /* HAVE_DILITHIUM */ /** Implementations */ int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size) @@ -2081,7 +2096,8 @@ int wh_Client_MlDsaSetKeyId(MlDsaKey* key, whKeyId keyId) return WH_ERROR_BADARGS; } - key->devCtx = (void*)((intptr_t)keyId); + key->devCtx = WH_KEYID_TO_DEVCTX(keyId); + return WH_ERROR_OK; } @@ -2091,7 +2107,8 @@ int wh_Client_MlDsaGetKeyId(MlDsaKey* key, whKeyId* outId) return WH_ERROR_BADARGS; } - *outId = (whKeyId)((intptr_t)key->devCtx); + *outId = WH_DEVCTX_TO_KEYID(key->devCtx); + return WH_ERROR_OK; } @@ -2288,8 +2305,8 @@ int wh_Client_MlDsaMakeCacheKey(whClientContext* ctx, int size, int level, label, NULL); } -int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, MlDsaKey* key, - int size, WC_RNG* rng) +int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, int size, + MlDsaKey* key) { if (key == NULL) { return WH_ERROR_BADARGS; @@ -2301,8 +2318,7 @@ int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, MlDsaKey* key, int wh_Client_MlDsaSign(whClientContext* ctx, const byte* in, word32 in_len, - byte* out, word32* inout_len, WC_RNG* rng, - MlDsaKey* key) + byte* out, word32* inout_len, MlDsaKey* key) { int ret = 0; whPacket* packet; @@ -2313,7 +2329,7 @@ int wh_Client_MlDsaSign(whClientContext* ctx, const byte* in, word32 in_len, #ifdef DEBUG_CRYPTOCB_VERBOSE printf("[client] %s ctx:%p key:%p, in:%p in_len:%u, out:%p inout_len:%p\n", - __func__, ctx, key, hash, (unsigned)hash_len, sig, inout_sig_len); + __func__, ctx, key, in, (unsigned)in_len, out, inout_len); #endif if ( (ctx == NULL) || @@ -2558,6 +2574,456 @@ int wh_Client_MlDsaCheckPrivKey(whClientContext* ctx, MlDsaKey* key, } + +#ifdef WOLFHSM_CFG_DMA + +int wh_Client_MlDsaImportKeyDma(whClientContext* ctx, MlDsaKey* key, + whKeyId* inout_keyId, whNvmFlags flags, + uint16_t label_len, uint8_t* label) +{ + int ret = WH_ERROR_OK; + whKeyId key_id = WH_KEYID_ERASED; + byte buffer[DILITHIUM_MAX_PRV_KEY_SIZE]; + uint16_t buffer_len = 0; + + if ((ctx == NULL) || (key == NULL) || + ((label_len != 0) && (label == NULL))) { + return WH_ERROR_BADARGS; + } + + if (inout_keyId != NULL) { + key_id = *inout_keyId; + } + + /* Serialize the key to a temporary buffer first */ + ret = wh_Crypto_MlDsaSerializeKeyDer(key, sizeof(buffer), buffer, + &buffer_len); + if (ret == WH_ERROR_OK) { + /* Cache the key using DMA and get the keyID */ +#if WH_DMA_IS_32BIT + ret = wh_Client_KeyCacheDma32(ctx, flags, label, label_len, + (uint32_t)(uintptr_t)buffer, buffer_len, + &key_id); +#else + ret = wh_Client_KeyCacheDma64(ctx, flags, label, label_len, + (uint64_t)(uintptr_t)buffer, buffer_len, + &key_id); +#endif + if ((ret == WH_ERROR_OK) && (inout_keyId != NULL)) { + *inout_keyId = key_id; + } + } + + return ret; +} + +int wh_Client_MlDsaExportKeyDma(whClientContext* ctx, whKeyId keyId, + MlDsaKey* key, uint16_t label_len, + uint8_t* label) +{ + int ret = WH_ERROR_OK; + byte buffer[DILITHIUM_MAX_PRV_KEY_SIZE]; + uint16_t buffer_len = sizeof(buffer); + + if ((ctx == NULL) || WH_KEYID_ISERASED(keyId) || (key == NULL)) { + return WH_ERROR_BADARGS; + } + + /* Export the key from server using DMA */ +#if WH_DMA_IS_32BIT + ret = wh_Client_KeyExportDma32(ctx, keyId, (uint32_t)(uintptr_t)buffer, + buffer_len, label, label_len, &buffer_len); +#else + ret = wh_Client_KeyExportDma64(ctx, keyId, (uint64_t)(uintptr_t)buffer, + buffer_len, label, label_len, &buffer_len); +#endif + if (ret == WH_ERROR_OK) { + /* Deserialize the key */ + ret = wh_Crypto_MlDsaDeserializeKeyDer(buffer, buffer_len, key); + } + + return ret; +} + +static int _MlDsaMakeKeyDma(whClientContext* ctx, int level, + whKeyId* inout_key_id, whNvmFlags flags, + uint16_t label_len, uint8_t* label, MlDsaKey* key) +{ + int ret = WH_ERROR_OK; + whPacket* packet = NULL; + whKeyId key_id = WH_KEYID_ERASED; + byte buffer[DILITHIUM_MAX_PRV_KEY_SIZE]; + + if (ctx == NULL) { + return WH_ERROR_BADARGS; + } + + /* Get data pointer from the context to use as request/response storage */ + packet = (whPacket*)wh_CommClient_GetDataPtr(ctx->comm); + if (packet == NULL) { + return WH_ERROR_BADARGS; + } + + /* Use the supplied key id if provided */ + if (inout_key_id != NULL) { + key_id = *inout_key_id; + } + + /* Request Message */ + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_PK; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_keygen_Dma32_req* req = &packet->pqMldsaKeygenDma32Req; +#else + wh_Packet_pq_mldsa_keygen_Dma64_req* req = &packet->pqMldsaKeygenDma64Req; +#endif + uint16_t req_len = WH_PACKET_STUB_SIZE + sizeof(*req); + + if (req_len <= WOLFHSM_CFG_COMM_DATA_LEN) { + memset(req, 0, sizeof(*req)); + req->type = WC_PK_TYPE_PQC_SIG_KEYGEN; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->level = level; + req->flags = flags; + req->keyId = key_id; +#if WH_DMA_IS_32BIT + req->key.addr = (uint32_t)(uintptr_t)buffer; +#else + req->key.addr = (uint64_t)(uintptr_t)buffer; +#endif + req->key.sz = sizeof(buffer); + + if ((label != NULL) && (label_len > 0)) { + if (label_len > WH_NVM_LABEL_LEN) { + label_len = WH_NVM_LABEL_LEN; + } + memcpy(req->label, label, label_len); + req->labelSize = label_len; + } + + ret = wh_Client_SendRequest(ctx, group, action, req_len, + (uint8_t*)packet); + if (ret == WH_ERROR_OK) { + /* Response Message */ +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_Dma32_res* res = &packet->pqMldsaDma32Res; +#else + wh_Packet_pq_mldsa_Dma64_res* res = &packet->pqMldsaDma64Res; +#endif + uint16_t res_len; + + do { + ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + + if (ret == WH_ERROR_OK) { + if (packet->rc == WH_ERROR_OK) { + /* Key is cached on server or is ephemeral */ + key_id = (whKeyId)(res->keyId); + + /* Update output variable if requested */ + if (inout_key_id != NULL) { + *inout_key_id = key_id; + } + + /* Update the context if provided */ + if (key != NULL) { + /* Set the key_id. Should be ERASED if EPHEMERAL */ + wh_Client_MlDsaSetKeyId(key, key_id); + + if (flags & WH_NVM_FLAGS_EPHEMERAL) { + /* Response has the exported key */ + ret = wh_Crypto_MlDsaDeserializeKeyDer( + buffer, res->keySize, key); + } + } + } + else { + /* Server detected a problem with generation */ + ret = packet->rc; + } + } + } + } + else { + ret = WH_ERROR_BADARGS; + } + return ret; +} + + +int wh_Client_MlDsaMakeExportKeyDma(whClientContext* ctx, int level, + MlDsaKey* key) +{ + if (key == NULL) { + return WH_ERROR_BADARGS; + } + + return _MlDsaMakeKeyDma(ctx, level, NULL, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, + key); +} + + +int wh_Client_MlDsaSignDma(whClientContext* ctx, const byte* in, word32 in_len, + byte* out, word32* out_len, MlDsaKey* key) +{ + int ret = 0; + whPacket* packet; + + /* Transaction state */ + whKeyId key_id; + int evict = 0; + + if ((ctx == NULL) || (key == NULL) || ((in == NULL) && (in_len > 0)) || + (out == NULL) || (out_len == NULL)) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(ctx->comm); + if (packet == NULL) { + return WH_ERROR_BADARGS; + } + + key_id = WH_DEVCTX_TO_KEYID(key->devCtx); + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s keyid:%x, in_len:%u, inout_len:%p\n", __func__, key_id, + in_len, out_len); +#endif + + /* Import key if necessary */ + if (WH_KEYID_ISERASED(key_id)) { + /* Must import the key to the server and evict it afterwards */ + uint8_t keyLabel[] = "TempMlDsaSign"; + whNvmFlags flags = WH_NVM_FLAGS_NONE; + + ret = wh_Client_MlDsaImportKeyDma(ctx, key, &key_id, flags, + sizeof(keyLabel), keyLabel); + if (ret == WH_ERROR_OK) { + evict = 1; + } + } + + if (ret == WH_ERROR_OK) { + /* Request Message */ + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_PK; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_sign_Dma32_req* req = &packet->pqMldsaSignDma32Req; +#else + wh_Packet_pq_mldsa_sign_Dma64_req* req = &packet->pqMldsaSignDma64Req; +#endif + uint16_t req_len = WH_PACKET_STUB_SIZE + sizeof(*req); + uint32_t options = 0; + + if (req_len <= WOLFHSM_CFG_COMM_DATA_LEN) { + if (evict != 0) { + options |= WH_PACKET_PQ_MLDSA_SIGN_OPTIONS_EVICT; + } + + memset(req, 0, sizeof(*req)); + req->type = WC_PK_TYPE_PQC_SIG_SIGN; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->options = options; + req->level = key->level; + req->keyId = key_id; + + /* Set up DMA buffers */ +#if WH_DMA_IS_32BIT + req->msg.addr = (uint32_t)(uintptr_t)in; + req->msg.sz = in_len; + req->sig.addr = (uint32_t)(uintptr_t)out; + req->sig.sz = *out_len; +#else + req->msg.addr = (uint64_t)(uintptr_t)in; + req->msg.sz = in_len; + req->sig.addr = (uint64_t)(uintptr_t)out; + req->sig.sz = *out_len; +#endif + + /* Send Request */ + ret = wh_Client_SendRequest(ctx, group, action, req_len, + (uint8_t*)packet); + if (ret == WH_ERROR_OK) { + /* Server will evict at this point if requested */ + evict = 0; + + /* Response Message */ +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_sign_Dma32_res* res = + &packet->pqMldsaSignDma32Res; +#else + wh_Packet_pq_mldsa_sign_Dma64_res* res = + &packet->pqMldsaSignDma64Res; +#endif + uint16_t res_len = 0; + + /* Recv Response */ + do { + ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + + if (ret == WH_ERROR_OK) { + if (packet->rc == 0) { + /* Update signature length */ + *out_len = res->sigLen; + } + else { + ret = packet->rc; + } + } + } + } + else { + ret = WH_ERROR_BADARGS; + } + } + + /* Evict the key manually on error if needed */ + if (evict != 0) { + (void)wh_Client_KeyEvict(ctx, key_id); + } + + return ret; +} + +int wh_Client_MlDsaVerifyDma(whClientContext* ctx, const byte* sig, + word32 sig_len, const byte* msg, word32 msg_len, + int* out_res, MlDsaKey* key) +{ + int ret = 0; + whPacket* packet; + + /* Transaction state */ + whKeyId key_id; + int evict = 0; + + if ((ctx == NULL) || (key == NULL) || ((sig == NULL) && (sig_len > 0)) || + ((msg == NULL) && (msg_len > 0)) || (out_res == NULL)) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(ctx->comm); + if (packet == NULL) { + return WH_ERROR_BADARGS; + } + + key_id = WH_DEVCTX_TO_KEYID(key->devCtx); + + /* Import key if necessary */ + if (WH_KEYID_ISERASED(key_id)) { + /* Must import the key to the server and evict it afterwards */ + uint8_t keyLabel[] = "TempMlDsaVerify"; + whNvmFlags flags = WH_NVM_FLAGS_NONE; + + ret = wh_Client_MlDsaImportKeyDma(ctx, key, &key_id, flags, + sizeof(keyLabel), keyLabel); + if (ret == 0) { + evict = 1; + } + } + + if (ret == WH_ERROR_OK) { + /* Request Message */ + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_PK; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_verify_Dma32_req* req = + &packet->pqMldsaVerifyDma32Req; +#else + wh_Packet_pq_mldsa_verify_Dma64_req* req = + &packet->pqMldsaVerifyDma64Req; +#endif + uint16_t req_len = WH_PACKET_STUB_SIZE + sizeof(*req); + uint32_t options = 0; + + if (req_len <= WOLFHSM_CFG_COMM_DATA_LEN) { + if (evict != 0) { + options |= WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EVICT; + } + + memset(req, 0, sizeof(*req)); + req->type = WC_PK_TYPE_PQC_SIG_VERIFY; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->options = options; + req->level = key->level; + req->keyId = key_id; + + /* Set up DMA buffers */ +#if WH_DMA_IS_32BIT + req->sig.addr = (uint32_t)(uintptr_t)sig; + req->sig.sz = sig_len; + req->msg.addr = (uint32_t)(uintptr_t)msg; + req->msg.sz = msg_len; +#else + req->sig.addr = (uint64_t)(uintptr_t)sig; + req->sig.sz = sig_len; + req->msg.addr = (uint64_t)(uintptr_t)msg; + req->msg.sz = msg_len; +#endif + + /* Send Request */ + ret = wh_Client_SendRequest(ctx, group, action, req_len, + (uint8_t*)packet); + if (ret == WH_ERROR_OK) { + /* Server will evict at this point if requested */ + evict = 0; + + /* Response Message */ +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_verify_Dma32_res* res = + &packet->pqMldsaVerifyDma32Res; +#else + wh_Packet_pq_mldsa_verify_Dma64_res* res = + &packet->pqMldsaVerifyDma64Res; +#endif + uint16_t res_len = 0; + + /* Recv Response */ + do { + ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + + if (ret == WH_ERROR_OK) { + if (packet->rc == 0) { + /* Set verification result */ + *out_res = res->verifyResult; + } + else { + ret = packet->rc; + } + } + } + } + else { + ret = WH_ERROR_BADARGS; + } + } + + /* Evict the key manually on error if needed */ + if (evict != 0) { + (void)wh_Client_KeyEvict(ctx, key_id); + } + + return ret; +} + + +int wh_Client_MlDsaCheckPrivKeyDma(whClientContext* ctx, MlDsaKey* key, + const byte* pubKey, word32 pubKeySz) +{ + /* TODO */ + return CRYPTOCB_UNAVAILABLE; +} + + +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_DILITHIUM */ -#endif /* !WOLFHSM_CFG_NO_CRYPTO */ +#endif /* !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index dc2a4f0..ed20c5e 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -56,19 +56,24 @@ #ifndef NO_SHA256 static int _handleSha256(wc_CryptoInfo* info, void* inCtx, whPacket* packet); static int _xferSha256BlockAndUpdateDigest(whClientContext* ctx, - wc_Sha256* sha256, - whPacket* packet, + wc_Sha256* sha256, whPacket* packet, uint32_t isLastBlock); -static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info); -static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info); -static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info); -static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info); - #ifdef WOLFHSM_CFG_DMA static int _handleSha256Dma(wc_CryptoInfo* info, void* inCtx, whPacket* packet); #endif /* WOLFHSM_CFG_DMA */ #endif /* ! NO_SHA256 */ +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) +static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info, + int useDma); +static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info, + int useDma); +static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info, + int useDma); +static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info, + int useDma); +#endif /* HAVE_DILITHIUM || HAVE_FALCON */ + int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) { /* III When possible, return wolfCrypt-enumerated errors */ @@ -338,19 +343,19 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) #if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) case WC_PK_TYPE_PQC_SIG_KEYGEN: - ret = _handlePqcSigKeyGen(ctx, info); + ret = _handlePqcSigKeyGen(ctx, info, 0); break; case WC_PK_TYPE_PQC_SIG_SIGN: - ret = _handlePqcSign(ctx, info); + ret = _handlePqcSign(ctx, info, 0); break; case WC_PK_TYPE_PQC_SIG_VERIFY: - ret = _handlePqcVerify(ctx, info); + ret = _handlePqcVerify(ctx, info, 0); break; case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: - ret = _handlePqcSigCheckPrivKey(ctx, info); + ret = _handlePqcSigCheckPrivKey(ctx, info, 0); break; #endif /* HAVE_DILITHIUM || HAVE_FALCON */ @@ -752,21 +757,36 @@ static int _handleSha256Dma(wc_CryptoInfo* info, void* inCtx, whPacket* packet) #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) -static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info) +static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info, + int useDma) { int ret = CRYPTOCB_UNAVAILABLE; /* Extract info parameters */ - WC_RNG* rng = info->pk.pqc_sig_kg.rng; int size = info->pk.pqc_sig_kg.size; void* key = info->pk.pqc_sig_kg.key; int type = info->pk.pqc_sig_kg.type; +#ifndef WOLFHSM_CFG_DMA + if (useDma) { + /* TODO: proper error code? */ + return WC_HW_E; + } +#endif + switch (type) { #ifdef HAVE_DILITHIUM case WC_PQC_SIG_TYPE_DILITHIUM: { int level = ((MlDsaKey*)key)->level; - ret = wh_Client_MlDsaMakeExportKey(ctx, level, key, size, rng); +#ifdef WOLFHSM_CFG_DMA + if (useDma) { + ret = wh_Client_MlDsaMakeExportKeyDma(ctx, level, key); + } + else +#endif /* WOLFHSM_CFG_DMA */ + { + ret = wh_Client_MlDsaMakeExportKey(ctx, level, size, key); + } } break; #endif /* HAVE_DILITHIUM */ @@ -780,7 +800,7 @@ static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info) return ret; } -static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info) +static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info, int useDma) { int ret = CRYPTOCB_UNAVAILABLE; @@ -789,14 +809,29 @@ static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info) word32 in_len = info->pk.pqc_sign.inlen; byte* out = info->pk.pqc_sign.out; word32* out_len = info->pk.pqc_sign.outlen; - WC_RNG* rng = info->pk.pqc_sign.rng; void* key = info->pk.pqc_sign.key; int type = info->pk.pqc_sign.type; +#ifndef WOLFHSM_CFG_DMA + if (useDma) { + /* TODO: proper error code? */ + return WC_HW_E; + } +#endif + switch (type) { #ifdef HAVE_DILITHIUM case WC_PQC_SIG_TYPE_DILITHIUM: - ret = wh_Client_MlDsaSign(ctx, in, in_len, out, out_len, rng, key); +#ifdef WOLFHSM_CFG_DMA + if (useDma) { + ret = + wh_Client_MlDsaSignDma(ctx, in, in_len, out, out_len, key); + } + else +#endif /* WOLFHSM_CFG_DMA */ + { + ret = wh_Client_MlDsaSign(ctx, in, in_len, out, out_len, key); + } break; #endif /* HAVE_DILITHIUM */ @@ -810,7 +845,8 @@ static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info) return ret; } -static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info) +static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info, + int useDma) { int ret = CRYPTOCB_UNAVAILABLE; @@ -823,11 +859,27 @@ static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info) void* key = info->pk.pqc_verify.key; int type = info->pk.pqc_verify.type; +#ifndef WOLFHSM_CFG_DMA + if (useDma) { + /* TODO: proper error code? */ + return WC_HW_E; + } +#endif + switch (type) { #ifdef HAVE_DILITHIUM case WC_PQC_SIG_TYPE_DILITHIUM: - ret = wh_Client_MlDsaVerify(ctx, sig, sig_len, msg, msg_len, res, - key); +#ifdef WOLFHSM_CFG_DMA + if (useDma) { + ret = wh_Client_MlDsaVerifyDma(ctx, sig, sig_len, msg, msg_len, + res, key); + } + else +#endif /* WOLFHSM_CFG_DMA */ + { + ret = wh_Client_MlDsaVerify(ctx, sig, sig_len, msg, msg_len, res, + key); + } break; #endif /* HAVE_DILITHIUM */ @@ -841,7 +893,8 @@ static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info) return ret; } -static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info) +static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info, + int useDma) { int ret = CRYPTOCB_UNAVAILABLE; @@ -851,14 +904,30 @@ static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info) word32 pubKeySz = info->pk.pqc_sig_check.pubKeySz; int type = info->pk.pqc_sig_check.type; +#ifndef WOLFHSM_CFG_DMA + if (useDma) { + /* TODO: proper error code? */ + return WC_HW_E; + } +#endif + switch (type) { #ifdef HAVE_DILITHIUM case WC_PQC_SIG_TYPE_DILITHIUM: - ret = wh_Client_MlDsaCheckPrivKey(ctx, key, pubKey, pubKeySz); +#ifdef WOLFHSM_CFG_DMA + if (useDma) { + ret = + wh_Client_MlDsaCheckPrivKeyDma(ctx, key, pubKey, pubKeySz); + } + else +#endif /* WOLFHSM_CFG_DMA */ + { + ret = wh_Client_MlDsaCheckPrivKey(ctx, key, pubKey, pubKeySz); + } break; #endif /* HAVE_DILITHIUM */ - /* Support for additional PQC algorithms should be added here */ + /* Support for additional PQC algorithms should be added here */ default: ret = CRYPTOCB_UNAVAILABLE; @@ -913,6 +982,26 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) } } break; /* case WC_ALGO_TYPE_HASH */ + + case WC_ALGO_TYPE_PK: { + switch (info->pk.type) { +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) + case WC_PK_TYPE_PQC_SIG_KEYGEN: + ret = _handlePqcSigKeyGen(ctx, info, 1); + break; + case WC_PK_TYPE_PQC_SIG_SIGN: + ret = _handlePqcSign(ctx, info, 1); + break; + case WC_PK_TYPE_PQC_SIG_VERIFY: + ret = _handlePqcVerify(ctx, info, 1); + break; + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = _handlePqcSigCheckPrivKey(ctx, info, 1); + break; +#endif /* HAVE_DILITHIUM || HAVE_FALCON */ + } + } break; /* case WC_ALGO_TYPE_PK */ + case WC_ALGO_TYPE_NONE: default: ret = CRYPTOCB_UNAVAILABLE; diff --git a/src/wh_crypto.c b/src/wh_crypto.c index c8e225a..1820034 100644 --- a/src/wh_crypto.c +++ b/src/wh_crypto.c @@ -257,7 +257,36 @@ int wh_Crypto_MlDsaSerializeKeyDer(MlDsaKey* key, uint16_t max_size, return WH_ERROR_BADARGS; } - ret = wc_Dilithium_KeyToDer(key, buffer, max_size); + /* Choose appropriate serialization based on key flags */ + if (key->prvKeySet && key->pubKeySet) { +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) && \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) + /* Full keypair - use KeyToDer */ + ret = wc_Dilithium_KeyToDer(key, buffer, max_size); +#else + ret = WH_ERROR_BADARGS; +#endif + } + else if (key->pubKeySet) { +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + /* Public key only - use PublicKeyToDer with SPKI format */ + ret = wc_Dilithium_PublicKeyToDer(key, buffer, max_size, 1); +#else + ret = WH_ERROR_BADARGS; +#endif + } + else if (key->prvKeySet) { +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + /* Private key only */ + ret = wc_Dilithium_PrivateKeyToDer(key, buffer, max_size); +#else + ret = WH_ERROR_BADARGS; +#endif + } + else { + /* No key data set */ + return WH_ERROR_BADARGS; + } /* ASN.1 functions return the size of the DER encoded key on success */ if (ret > 0) { @@ -271,12 +300,29 @@ int wh_Crypto_MlDsaDeserializeKeyDer(const uint8_t* buffer, uint16_t size, MlDsaKey* key) { word32 idx = 0; + int ret; if ((buffer == NULL) || (key == NULL)) { return WH_ERROR_BADARGS; } - return wc_Dilithium_PrivateKeyDecode(buffer, &idx, key, size); +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) && \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) + /* Try private key first, if that fails try public key */ + ret = wc_Dilithium_PrivateKeyDecode(buffer, &idx, key, size); + if (ret != 0) { + /* Reset index before trying public key */ + idx = 0; + ret = wc_Dilithium_PublicKeyDecode(buffer, &idx, key, size); + } +#elif defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) + ret = wc_Dilithium_PublicKeyDecode(buffer, &idx, key, size); +#elif defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) + ret = wc_Dilithium_PrivateKeyDecode(buffer, &idx, key, size); +#else + ret = WH_ERROR_BADARGS; +#endif + return ret; } #endif /* HAVE_DILITHIUM */ diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 9386968..75a5e84 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -523,7 +523,14 @@ int wh_Server_MlDsaKeyCacheImport(whServerContext* ctx, MlDsaKey* key, whNvmMetadata* cacheMeta; uint16_t der_size; - const uint16_t MAX_MLDSA_DER_SIZE = 5000; + const uint16_t MAX_MLDSA_DER_SIZE = +#if !defined(WOLFSSL_NO_ML_DSA_87) + ML_DSA_LEVEL5_PRV_KEY_DER_SIZE; +#elif !defined(WOLFSSL_NO_ML_DSA_65) + ML_DSA_LEVEL3_PRV_KEY_DER_SIZE; +#else + ML_DSA_LEVEL2_PRV_KEY_DER_SIZE; +#endif if ((ctx == NULL) || (key == NULL) || (WH_KEYID_ISERASED(keyId)) || ((label != NULL) && (label_len > sizeof(cacheMeta->label)))) { @@ -557,9 +564,9 @@ int wh_Server_MlDsaKeyCacheImport(whServerContext* ctx, MlDsaKey* key, int wh_Server_MlDsaKeyCacheExport(whServerContext* ctx, whKeyId keyId, MlDsaKey* key) { - uint8_t* cacheBuf; + uint8_t* cacheBuf; whNvmMetadata* cacheMeta; - int ret = WH_ERROR_OK; + int ret = WH_ERROR_OK; if ((ctx == NULL) || (key == NULL) || (WH_KEYID_ISERASED(keyId))) { return WH_ERROR_BADARGS; @@ -1430,26 +1437,48 @@ static int _HandleSha256(whServerContext* server, whPacket* packet, #endif /* !NO_SHA256 */ #ifdef HAVE_DILITHIUM -/* Check if the ML-DSA security level is supported + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY +/* Check if the ML-DSA security level is supported * returns 1 if supported, 0 otherwise */ static int _IsMlDsaLevelSupported(int level) { int ret = 0; switch (level) { +#ifndef WOLFSSL_NO_ML_DSA_44 case WC_ML_DSA_44: + ret = 1; + break; +#endif /* !WOLFSSL_NO_ML_DSA_44 */ +#ifndef WOLFSSL_NO_ML_DSA_65 case WC_ML_DSA_65: + ret = 1; + break; +#endif /* !WOLFSSL_NO_ML_DSA_65 */ +#ifndef WOLFSSL_NO_ML_DSA_87 case WC_ML_DSA_87: ret = 1; break; +#endif /* !WOLFSSL_NO_ML_DSA_87 */ + default: + ret = 0; + break; } return ret; } +#endif /* WOLFSSL_DILITHIUM_NO_MAKE_KEY */ static int _HandleMlDsaKeyGen(whServerContext* ctx, whPacket* packet, uint16_t* out_size) { +#ifdef WOLFSSL_DILITHIUM_NO_MAKE_KEY + (void)ctx; + (void)packet; + (void)out_size; + return WH_ERROR_NOHANDLER; +#else int ret = WH_ERROR_OK; MlDsaKey key[1]; wh_Packet_pq_mldsa_kg_req* req = &packet->pqMldsaKgReq; @@ -1526,11 +1555,18 @@ static int _HandleMlDsaKeyGen(whServerContext* ctx, whPacket* packet, } } return ret; +#endif /* WOLFSSL_DILITHIUM_NO_MAKE_KEY */ } static int _HandleMlDsaSign(whServerContext* ctx, whPacket* packet, uint16_t *out_size) { +#ifdef WOLFSSL_DILITHIUM_NO_SIGN + (void)ctx; + (void)packet; + (void)out_size; + return WH_ERROR_NOHANDLER; +#else int ret; MlDsaKey key[1]; wh_Packet_pq_mldsa_sign_req* req = &packet->pqMldsaSignReq; @@ -1571,11 +1607,18 @@ static int _HandleMlDsaSign(whServerContext* ctx, whPacket* packet, *out_size = WH_PACKET_STUB_SIZE + sizeof(*res) + res_len; } return ret; +#endif /* WOLFSSL_DILITHIUM_NO_SIGN */ } static int _HandleMlDsaVerify(whServerContext* ctx, whPacket* packet, uint16_t *out_size) { +#ifdef WOLFSSL_DILITHIUM_NO_VERIFY + (void)ctx; + (void)packet; + (void)out_size; + return WH_ERROR_NOHANDLER; +#else int ret; MlDsaKey key[1]; wh_Packet_pq_mldsa_verify_req* req = &packet->pqMldsaVerifyReq; @@ -1615,6 +1658,7 @@ static int _HandleMlDsaVerify(whServerContext* ctx, whPacket* packet, *out_size = WH_PACKET_STUB_SIZE + sizeof(*res); } return ret; +#endif /* WOLFSSL_DILITHIUM_NO_VERIFY */ } static int _HandleMlDsaCheckPrivKey(whServerContext* ctx, whPacket* packet, @@ -1963,6 +2007,348 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, } #endif /* ! NO_SHA256 */ + +#if defined(HAVE_DILITHIUM) + +static int _HandleMlDsaKeyGenDma(whServerContext* server, whPacket* packet, + uint16_t* size) +{ +#ifdef WOLFSSL_DILITHIUM_NO_MAKE_KEY + (void)server; + (void)packet; + (void)size; + return WH_ERROR_NOHANDLER; +#else + int ret = WH_ERROR_OK; + MlDsaKey key[1]; + void* clientOutAddr = NULL; + uint16_t keySize = 0; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_keygen_Dma32_req* req = &packet->pqMldsaKeygenDma32Req; + wh_Packet_pq_mldsa_Dma32_res* res = &packet->pqMldsaDma32Res; +#else + wh_Packet_pq_mldsa_keygen_Dma64_req* req = &packet->pqMldsaKeygenDma64Req; + wh_Packet_pq_mldsa_Dma64_res* res = &packet->pqMldsaDma64Res; +#endif + + /* Check the ML-DSA security level is valid and supported */ + if (0 == _IsMlDsaLevelSupported(req->level)) { + ret = WH_ERROR_BADARGS; + } + else { + /* init mldsa key */ + ret = wc_MlDsaKey_Init(key, NULL, server->crypto->devId); + if (ret == 0) { + /* Set the ML-DSA security level */ + ret = wc_MlDsaKey_SetParams(key, req->level); + if (ret == 0) { + /* generate the key */ + ret = wc_MlDsaKey_MakeKey(key, server->crypto->rng); + if (ret == 0) { + /* Check incoming flags */ + if (req->flags & WH_NVM_FLAGS_EPHEMERAL) { + /* Must serialize the key into client memory */ + ret = wh_Server_DmaProcessClientAddress( + server, req->key.addr, &clientOutAddr, req->key.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, + (whServerDmaFlags){0}); + + if (ret == 0) { + ret = wh_Crypto_MlDsaSerializeKeyDer( + key, req->key.sz, clientOutAddr, &keySize); + if (ret == 0) { + res->keyId = WH_KEYID_ERASED; + res->keySize = keySize; + } + } + + if (ret == 0) { + ret = wh_Server_DmaProcessClientAddress( + server, req->key.addr, &clientOutAddr, keySize, + WH_DMA_OPER_CLIENT_WRITE_POST, + (whServerDmaFlags){0}); + } + } + else { + /* Must import the key into the cache and return keyid + */ + whKeyId keyId = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, req->keyId); + + if (WH_KEYID_ISERASED(keyId)) { + /* Generate a new id */ + ret = hsmGetUniqueId(server, &keyId); +#ifdef DEBUG_CRYPTOCB + printf("[server] %s UniqueId: keyId:%u, ret:%d\n", + __func__, keyId, ret); +#endif + } + + if (ret == 0) { + ret = wh_Server_MlDsaKeyCacheImport( + server, key, keyId, req->flags, req->labelSize, + req->label); +#ifdef DEBUG_CRYPTOCB + printf( + "[server] %s CacheImport: keyId:%u, ret:%d\n", + __func__, keyId, ret); +#endif + if (ret == 0) { + res->keyId = WH_KEYID_ID(keyId); + res->keySize = keySize; + *size = WH_PACKET_STUB_SIZE + sizeof(res); + } + } + } + } + } + wc_MlDsaKey_Free(key); + } + } + + if (ret == WH_ERROR_ACCESS) { + res->dmaAddrStatus.badAddr = req->key; + } + + return ret; +#endif /* WOLFSSL_DILITHIUM_NO_MAKE_KEY */ +} + +static int _HandleMlDsaSignDma(whServerContext* ctx, whPacket* packet, + uint16_t* out_size) +{ +#ifdef WOLFSSL_DILITHIUM_NO_SIGN + (void)ctx; + (void)packet; + (void)out_size; + return WH_ERROR_NOHANDLER; +#else + int ret = 0; + MlDsaKey key[1]; + void* msgAddr = NULL; + void* sigAddr = NULL; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_sign_Dma32_req* req = &packet->pqMldsaSignDma32Req; + wh_Packet_pq_mldsa_sign_Dma32_res* res = &packet->pqMldsaSignDma32Res; +#else + wh_Packet_pq_mldsa_sign_Dma64_req* req = &packet->pqMldsaSignDma64Req; + wh_Packet_pq_mldsa_sign_Dma64_res* res = &packet->pqMldsaSignDma64Res; +#endif + + /* Transaction state */ + whKeyId key_id; + int evict = 0; + + if (ctx == NULL || packet == NULL || out_size == NULL) { + return WH_ERROR_BADARGS; + } + + /* Get key ID and evict flag */ + key_id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req->keyId); + evict = !!(req->options & WH_PACKET_PQ_MLDSA_SIGN_OPTIONS_EVICT); + + /* Initialize key */ + ret = wc_MlDsaKey_Init(key, NULL, ctx->crypto->devId); + if (ret != 0) { + return ret; + } + + /* Export key from cache */ + /* TODO: sanity check security level against key pulled from cache? */ + ret = wh_Server_MlDsaKeyCacheExport(ctx, key_id, key); + if (ret == 0) { + /* Process client message buffer address */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->msg.addr, &msgAddr, req->msg.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Process client signature buffer address */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->sig.addr, &sigAddr, req->sig.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Sign the message */ + word32 sigLen = req->sig.sz; + ret = wc_MlDsaKey_Sign(key, sigAddr, &sigLen, msgAddr, + req->msg.sz, ctx->crypto->rng); + + if (ret == 0) { + /* Post-write processing of signature buffer */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->sig.addr, &sigAddr, sigLen, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Set response signature length */ + res->sigLen = sigLen; + *out_size = WH_PACKET_STUB_SIZE + sizeof(*res); + } + + /* Post-read processing of message buffer */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->msg.addr, &msgAddr, req->msg.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); + } + } + } + + /* Evict key if requested */ + if (evict) { + (void)hsmEvictKey(ctx, key_id); + } + } + + wc_MlDsaKey_Free(key); + return ret; +#endif /* WOLFSSL_DILITHIUM_NO_SIGN */ +} + +static int _HandleMlDsaVerifyDma(whServerContext* ctx, whPacket* packet, + uint16_t* out_size) +{ +#ifdef WOLFSSL_DILITHIUM_NO_VERIFY + (void)ctx; + (void)packet; + (void)out_size; + return WH_ERROR_NOHANDLER; +#else + int ret = 0; + MlDsaKey key[1]; + void* msgAddr = NULL; + void* sigAddr = NULL; + int verified = 0; + +#if WH_DMA_IS_32BIT + wh_Packet_pq_mldsa_verify_Dma32_req* req = &packet->pqMldsaVerifyDma32Req; + wh_Packet_pq_mldsa_verify_Dma32_res* res = &packet->pqMldsaVerifyDma32Res; +#else + wh_Packet_pq_mldsa_verify_Dma64_req* req = &packet->pqMldsaVerifyDma64Req; + wh_Packet_pq_mldsa_verify_Dma64_res* res = &packet->pqMldsaVerifyDma64Res; +#endif + + /* Transaction state */ + whKeyId key_id; + int evict = 0; + + if (ctx == NULL || packet == NULL || out_size == NULL) { + return WH_ERROR_BADARGS; + } + + /* Get key ID and evict flag */ + key_id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req->keyId); + evict = !!(req->options & WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EVICT); + + /* Initialize key */ + ret = wc_MlDsaKey_Init(key, NULL, ctx->crypto->devId); + if (ret != 0) { + return ret; + } + + /* Export key from cache */ + ret = wh_Server_MlDsaKeyCacheExport(ctx, key_id, key); + if (ret == 0) { + /* Process client signature buffer address */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->sig.addr, &sigAddr, req->sig.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Process client message buffer address */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->msg.addr, &msgAddr, req->msg.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Verify the signature */ + ret = wc_MlDsaKey_Verify(key, sigAddr, req->sig.sz, msgAddr, + req->msg.sz, &verified); + + if (ret == 0) { + /* Post-read processing of signature buffer */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->sig.addr, &sigAddr, req->sig.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); + + if (ret == 0) { + /* Post-read processing of message buffer */ + ret = wh_Server_DmaProcessClientAddress( + ctx, (uintptr_t)req->msg.addr, &msgAddr, + req->msg.sz, WH_DMA_OPER_CLIENT_READ_POST, + (whServerDmaFlags){0}); + + if (ret == 0) { + /* Set verification result */ + res->verifyResult = verified; + *out_size = WH_PACKET_STUB_SIZE + sizeof(*res); + } + } + } + } + } + + /* Evict key if requested */ + if (evict) { + (void)hsmEvictKey(ctx, key_id); + } + } + + wc_MlDsaKey_Free(key); + return ret; +#endif /* WOLFSSL_DILITHIUM_NO_VERIFY */ +} + +static int _HandleMlDsaCheckPrivKeyDma(whServerContext* server, whPacket* packet, + uint16_t* size) +{ + return WH_ERROR_NOHANDLER; +} +#endif /* HAVE_DILITHIUM */ + +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) +static int _HandlePqcSigAlgorithmDma(whServerContext* server, whPacket* packet, + uint16_t* size) +{ + int ret = WH_ERROR_NOHANDLER; + wh_Packet_pk_pq_any_req* req = &packet->pkPqAnyReq; + + /* Dispatch the appropriate algorithm handler based on the requested PK type + * and the algorithm type. */ + switch (req->pqAlgoType) { +#ifdef HAVE_DILITHIUM + case WC_PQC_SIG_TYPE_DILITHIUM: { + switch (req->type) { + case WC_PK_TYPE_PQC_SIG_KEYGEN: + ret = _HandleMlDsaKeyGenDma(server, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_SIGN: + ret = _HandleMlDsaSignDma(server, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_VERIFY: + ret = _HandleMlDsaVerifyDma(server, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = _HandleMlDsaCheckPrivKeyDma(server, packet, size); + break; + default: + ret = WH_ERROR_NOHANDLER; + break; + } + } break; +#endif /* HAVE_DILITHIUM */ + default: + ret = WH_ERROR_NOHANDLER; + break; + } + + return ret; +} +#endif /* HAVE_DILITHIUM || HAVE_FALCON */ + int wh_Server_HandleCryptoDmaRequest(whServerContext* server, uint16_t action, uint8_t* data, uint16_t* size, uint16_t seq) { @@ -1991,12 +2377,22 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* server, #endif break; #endif /* !NO_SHA256 */ + } + break; /* WC_ALGO_TYPE_HASH */ - default: - ret = NOT_COMPILED_IN; + case WC_ALGO_TYPE_PK: + switch (packet->pkAnyReq.type) { +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) + case WC_PK_TYPE_PQC_SIG_KEYGEN: + case WC_PK_TYPE_PQC_SIG_SIGN: + case WC_PK_TYPE_PQC_SIG_VERIFY: + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = _HandlePqcSigAlgorithmDma(server, packet, size); break; +#endif /* HAVE_DILITHIUM || HAVE_FALCON */ } - break; + break; /* WC_ALGO_TYPE_PK */ + case WC_ALGO_TYPE_NONE: default: diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 807ebe3..1c9a08a 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -147,7 +147,7 @@ int hsmCacheFindSlotAndZero(whServerContext* server, uint16_t keySz, /* zero the cache slot and set the output buffers */ if (foundIndex >= 0) { - XMEMSET(&server->cache[foundIndex], 0, sizeof(whServerCacheSlot)); + memset(&server->cache[foundIndex], 0, sizeof(whServerCacheSlot)); *outBuf = server->cache[foundIndex].buffer; *outMeta = server->cache[foundIndex].meta; } @@ -171,7 +171,7 @@ int hsmCacheFindSlotAndZero(whServerContext* server, uint16_t keySz, } } if (foundIndex >= 0) { - XMEMSET(&server->bigCache[foundIndex], 0, + memset(&server->bigCache[foundIndex], 0, sizeof(whServerBigCacheSlot)); *outBuf = server->bigCache[foundIndex].buffer; *outMeta = server->bigCache[foundIndex].meta; @@ -219,8 +219,8 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) /* write key if slot found */ if (foundIndex != -1) { - XMEMCPY((uint8_t*)server->cache[foundIndex].buffer, in, meta->len); - XMEMCPY((uint8_t*)server->cache[foundIndex].meta, (uint8_t*)meta, + memcpy((uint8_t*)server->cache[foundIndex].buffer, in, meta->len); + memcpy((uint8_t*)server->cache[foundIndex].meta, (uint8_t*)meta, sizeof(whNvmMetadata)); /* check if the key is already commited */ if (wh_Nvm_GetMetadata(server->nvm, meta->id, meta) == @@ -259,9 +259,9 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) /* write key if slot found */ if (foundIndex != -1) { - XMEMCPY((uint8_t*)server->bigCache[foundIndex].buffer, in, + memcpy((uint8_t*)server->bigCache[foundIndex].buffer, in, meta->len); - XMEMCPY((uint8_t*)server->bigCache[foundIndex].meta, (uint8_t*)meta, + memcpy((uint8_t*)server->bigCache[foundIndex].meta, (uint8_t*)meta, sizeof(whNvmMetadata)); /* check if the key is already commited */ if (wh_Nvm_GetMetadata(server->nvm, meta->id, meta) == @@ -358,7 +358,7 @@ int hsmFreshenKey(whServerContext* server, whKeyId keyId, uint8_t** outBuf, if (ret == WH_ERROR_OK) { /* Copy the metadata to the cache slot if key read is * successful*/ - XMEMCPY((uint8_t*)*outMeta, (uint8_t*)tmpMeta, + memcpy((uint8_t*)*outMeta, (uint8_t*)tmpMeta, sizeof(whNvmMetadata)); } } @@ -388,11 +388,11 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, if (server->cache[i].meta->len > *outSz) return WH_ERROR_NOSPACE; if (outMeta != NULL) { - XMEMCPY((uint8_t*)outMeta, (uint8_t*)server->cache[i].meta, + memcpy((uint8_t*)outMeta, (uint8_t*)server->cache[i].meta, sizeof(whNvmMetadata)); } if (out != NULL) { - XMEMCPY(out, server->cache[i].buffer, + memcpy(out, server->cache[i].buffer, server->cache[i].meta->len); } *outSz = server->cache[i].meta->len; @@ -407,11 +407,11 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, if (server->bigCache[i].meta->len > *outSz) return WH_ERROR_NOSPACE; if (outMeta != NULL) { - XMEMCPY((uint8_t*)outMeta, (uint8_t*)server->bigCache[i].meta, + memcpy((uint8_t*)outMeta, (uint8_t*)server->bigCache[i].meta, sizeof(whNvmMetadata)); } if (out != NULL) { - XMEMCPY(out, server->bigCache[i].buffer, + memcpy(out, server->bigCache[i].buffer, server->bigCache[i].meta->len); } *outSz = server->bigCache[i].meta->len; @@ -425,7 +425,7 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, *outSz = meta->len; /* read meta */ if (outMeta != NULL) - XMEMCPY((uint8_t*)outMeta, (uint8_t*)meta, sizeof(meta)); + memcpy((uint8_t*)outMeta, (uint8_t*)meta, sizeof(meta)); /* read the object */ if (out != NULL) ret = wh_Nvm_Read(server->nvm, keyId, 0, *outSz, out); @@ -439,11 +439,11 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, if ((ret == WH_ERROR_NOTFOUND) && (WH_KEYID_TYPE(keyId) == WH_KEYTYPE_SHE) && (WH_KEYID_ID(keyId) == WH_SHE_MASTER_ECU_KEY_ID)) { - XMEMSET(out, 0, WH_SHE_KEY_SZ); + memset(out, 0, WH_SHE_KEY_SZ); *outSz = WH_SHE_KEY_SZ; if (outMeta != NULL) { /* need empty flags and correct length and id */ - XMEMSET(outMeta, 0, sizeof(meta)); + memset(outMeta, 0, sizeof(meta)); meta->len = WH_SHE_KEY_SZ; meta->id = keyId; } @@ -543,7 +543,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, ret = WH_ERROR_BADARGS; } else { - XMEMCPY(meta->label, packet->keyCacheReq.label, + memcpy(meta->label, packet->keyCacheReq.label, packet->keyCacheReq.labelSz); } /* get a new id if one wasn't provided */ @@ -575,7 +575,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, ret = WH_ERROR_BADARGS; } else { - XMEMCPY(meta->label, packet->keyCacheDma32Req.label, + memcpy(meta->label, packet->keyCacheDma32Req.label, packet->keyCacheDma32Req.labelSz); } /* get a new id if one wasn't provided */ @@ -606,7 +606,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, packet->keyExportDma32Res.len = packet->keyExportDma32Req.key.sz; /* set label */ - XMEMCPY(packet->keyExportDma32Res.label, meta->label, + memcpy(packet->keyExportDma32Res.label, meta->label, sizeof(meta->label)); *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma32Res); } @@ -626,7 +626,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, ret = WH_ERROR_BADARGS; } else { - XMEMCPY(meta->label, packet->keyCacheDma64Req.label, + memcpy(meta->label, packet->keyCacheDma64Req.label, packet->keyCacheDma64Req.labelSz); } /* get a new id if one wasn't provided */ @@ -657,7 +657,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, packet->keyExportDma64Res.len = packet->keyExportDma64Req.key.sz; /* set label */ - XMEMCPY(packet->keyExportDma64Res.label, meta->label, + memcpy(packet->keyExportDma64Res.label, meta->label, sizeof(meta->label)); *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma64Res); } @@ -689,7 +689,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, /* set key len */ packet->keyExportRes.len = field; /* set label */ - XMEMCPY(packet->keyExportRes.label, meta->label, + memcpy(packet->keyExportRes.label, meta->label, sizeof(meta->label)); *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportRes) + field; @@ -740,14 +740,14 @@ static int hsmCacheKeyDma32(whServerContext* server, whNvmMetadata* meta, } /* Copy metadata */ - XMEMCPY(slotMeta, meta, sizeof(whNvmMetadata)); + memcpy(slotMeta, meta, sizeof(whNvmMetadata)); /* Copy key data using DMA */ ret = whServerDma_CopyFromClient32(server, buffer, keyAddr, meta->len, (whServerDmaFlags){0}); if (ret != 0) { /* Clear the slot on error */ - XMEMSET(buffer, 0, meta->len); + memset(buffer, 0, meta->len); slotMeta->id = WH_KEYID_ERASED; } @@ -772,7 +772,7 @@ static int hsmExportKeyDma32(whServerContext* server, whKeyId keyId, return WH_ERROR_NOSPACE; } - XMEMCPY(outMeta, cacheMeta, sizeof(whNvmMetadata)); + memcpy(outMeta, cacheMeta, sizeof(whNvmMetadata)); /* Copy key data using DMA */ ret = whServerDma_CopyToClient32(server, keyAddr, buffer, outMeta->len, @@ -797,14 +797,14 @@ static int hsmCacheKeyDma64(whServerContext* server, whNvmMetadata* meta, } /* Copy metadata */ - XMEMCPY(slotMeta, meta, sizeof(whNvmMetadata)); + memcpy(slotMeta, meta, sizeof(whNvmMetadata)); /* Copy key data using DMA */ ret = whServerDma_CopyFromClient64(server, buffer, keyAddr, meta->len, (whServerDmaFlags){0}); if (ret != 0) { /* Clear the slot on error */ - XMEMSET(buffer, 0, meta->len); + memset(buffer, 0, meta->len); slotMeta->id = WH_KEYID_ERASED; } @@ -829,7 +829,7 @@ static int hsmExportKeyDma64(whServerContext* server, whKeyId keyId, return WH_ERROR_NOSPACE; } - XMEMCPY(outMeta, cacheMeta, sizeof(whNvmMetadata)); + memcpy(outMeta, cacheMeta, sizeof(whNvmMetadata)); /* Copy key data using DMA */ ret = whServerDma_CopyToClient64(server, keyAddr, buffer, outMeta->len, diff --git a/test/user_settings.h b/test/user_settings.h index e04eab8..f536d94 100644 --- a/test/user_settings.h +++ b/test/user_settings.h @@ -118,6 +118,21 @@ extern "C" { #define WOLFSSL_SHAKE128 #define WOLFSSL_SHAKE256 +/* The following options can be individually controlled to customize the + * ML-DSA configuration */ +#if 0 +#define WOLFSSL_DILITHIUM_VERIFY_ONLY +#endif +#if 0 +#define WOLFSSL_DILITHIUM_NO_VERIFY +#endif +#if 0 +#define WOLFSSL_DILITHIUM_NO_SIGN +#endif +#if 0 +#define WOLFSSL_DILITHIUM_NO_MAKE_KEY +#endif + /** Composite features */ #define HAVE_HKDF diff --git a/test/wh_test_check_struct_padding.c b/test/wh_test_check_struct_padding.c index fab9496..9dbe963 100644 --- a/test/wh_test_check_struct_padding.c +++ b/test/wh_test_check_struct_padding.c @@ -61,69 +61,95 @@ whMessageNvm_ReadDma64Request whMessageNvm_ReadDma64Request_test; #include "wolfhsm/wh_packet.h" whPacket whPacket_test; /* Test every variant of the nested union */ -wh_Packet_version_exchange versionExchange; -wh_Packet_key_cache_req keyCacheReq; -wh_Packet_key_evict_req keyEvictReq; -wh_Packet_key_commit_req keyCommitReq; -wh_Packet_key_export_req keyExportReq; -wh_Packet_key_erase_req keyEraseReq; -wh_Packet_counter_init_req counterInitReq; -wh_Packet_counter_increment_req counterIncrementReq; -wh_Packet_counter_read_req counterReadReq; -wh_Packet_counter_destroy_req counterDestroyReq; -wh_Packet_key_cache_res keyCacheRes; -wh_Packet_key_evict_res keyEvictRes; -wh_Packet_key_commit_res keyCommitRes; -wh_Packet_key_export_res keyExportRes; -wh_Packet_key_erase_res keyEraseRes; -wh_Packet_counter_init_res counterInitRes; -wh_Packet_counter_increment_res counterIncrementRes; -wh_Packet_counter_read_res counterReadRes; +wh_Packet_version_exchange versionExchange; +wh_Packet_key_cache_req keyCacheReq; +wh_Packet_key_evict_req keyEvictReq; +wh_Packet_key_commit_req keyCommitReq; +wh_Packet_key_export_req keyExportReq; +wh_Packet_key_erase_req keyEraseReq; +wh_Packet_counter_init_req counterInitReq; +wh_Packet_counter_increment_req counterIncrementReq; +wh_Packet_counter_read_req counterReadReq; +wh_Packet_counter_destroy_req counterDestroyReq; +wh_Packet_key_cache_res keyCacheRes; +wh_Packet_key_evict_res keyEvictRes; +wh_Packet_key_commit_res keyCommitRes; +wh_Packet_key_export_res keyExportRes; +wh_Packet_key_erase_res keyEraseRes; +wh_Packet_counter_init_res counterInitRes; +wh_Packet_counter_increment_res counterIncrementRes; +wh_Packet_counter_read_res counterReadRes; + +#if defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_32BIT +wh_Packet_key_cache_Dma32_req keyCacheDma32Req; +wh_Packet_key_cache_Dma32_res keyCacheDma32Res; +wh_Packet_key_export_Dma32_req keyExportDma32Req; +wh_Packet_key_export_Dma32_res keyExportDma32Res; +#elif defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_64BIT +wh_Packet_key_cache_Dma64_req keyCacheDma64Req; +wh_Packet_key_cache_Dma64_res keyCacheDma64Res; +wh_Packet_key_export_Dma64_req keyExportDma64Req; +wh_Packet_key_export_Dma64_res keyExportDma64Res; +#endif + #ifndef WOLFHSM_CFG_NO_CRYPTO -wh_Packet_cipher_any_req cipherAnyReq; -wh_Packet_cipher_aescbc_req cipherAesCbcReq; -wh_Packet_cipher_aesgcm_req cipherAesGcmReq; -wh_Packet_pk_any_req pkAnyReq; -wh_Packet_pk_rsakg_req pkRsakgReq; -wh_Packet_pk_rsa_req pkRsaReq; -wh_Packet_pk_rsa_get_size_req pkRsaGetSizeReq; -wh_Packet_pk_eckg_req pkEckgReq; -wh_Packet_pk_ecdh_req pkEcdhReq; -wh_Packet_pk_ecc_sign_req pkEccSignReq; -wh_Packet_pk_ecc_verify_req pkEccVerifyReq; -wh_Packet_pk_ecc_check_req pkEccCheckReq; -wh_Packet_pk_curve25519kg_req pkCurve25519kgReq; -wh_Packet_pk_curve25519kg_res pkCurve25519kgRes; -wh_Packet_pk_curve25519_req pkCurve25519Req; -wh_Packet_pk_curve25519_res pkCurve25519Res; -wh_Packet_rng_req rngReq; -wh_Packet_cmac_req cmacReq; -wh_Packet_cipher_aescbc_res cipherAesCbcRes; -wh_Packet_cipher_aesgcm_res cipherAesGcmRes; -wh_Packet_pk_rsakg_res pkRsakgRes; -wh_Packet_pk_rsa_res pkRsaRes; -wh_Packet_pk_rsa_get_size_res pkRsaGetSizeRes; -wh_Packet_pk_eckg_res pkEckgRes; -wh_Packet_pk_ecdh_res pkEcdhRes; -wh_Packet_pk_ecc_sign_res pkEccSignRes; -wh_Packet_pk_ecc_verify_res pkEccVerifyRes; -wh_Packet_pk_ecc_check_res pkEccCheckRes; -wh_Packet_rng_res rngRes; -wh_Packet_cmac_res cmacRes; -wh_Packet_hash_any_req hashAnyReq; -wh_Packet_hash_sha256_req hashSha256Req; -wh_Packet_hash_sha256_res hashSha256Res; +wh_Packet_cipher_any_req cipherAnyReq; +wh_Packet_cipher_aescbc_req cipherAesCbcReq; +wh_Packet_cipher_aesgcm_req cipherAesGcmReq; +wh_Packet_pk_any_req pkAnyReq; +wh_Packet_pk_rsakg_req pkRsakgReq; +wh_Packet_pk_rsa_req pkRsaReq; +wh_Packet_pk_rsa_get_size_req pkRsaGetSizeReq; +wh_Packet_pk_eckg_req pkEckgReq; +wh_Packet_pk_ecdh_req pkEcdhReq; +wh_Packet_pk_ecc_sign_req pkEccSignReq; +wh_Packet_pk_ecc_verify_req pkEccVerifyReq; +wh_Packet_pk_ecc_check_req pkEccCheckReq; +wh_Packet_pk_curve25519kg_req pkCurve25519kgReq; +wh_Packet_pk_curve25519kg_res pkCurve25519kgRes; +wh_Packet_pk_curve25519_req pkCurve25519Req; +wh_Packet_pk_curve25519_res pkCurve25519Res; +wh_Packet_rng_req rngReq; +wh_Packet_cmac_req cmacReq; +wh_Packet_cipher_aescbc_res cipherAesCbcRes; +wh_Packet_cipher_aesgcm_res cipherAesGcmRes; +wh_Packet_pk_rsakg_res pkRsakgRes; +wh_Packet_pk_rsa_res pkRsaRes; +wh_Packet_pk_rsa_get_size_res pkRsaGetSizeRes; +wh_Packet_pk_eckg_res pkEckgRes; +wh_Packet_pk_ecdh_res pkEcdhRes; +wh_Packet_pk_ecc_sign_res pkEccSignRes; +wh_Packet_pk_ecc_verify_res pkEccVerifyRes; +wh_Packet_pk_ecc_check_res pkEccCheckRes; +wh_Packet_rng_res rngRes; +wh_Packet_cmac_res cmacRes; +wh_Packet_hash_any_req hashAnyReq; +wh_Packet_hash_sha256_req hashSha256Req; +wh_Packet_hash_sha256_res hashSha256Res; -/* DMA crypto structs */ +/* DMA structs */ #if defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_32BIT -wh_Packet_hash_sha256_Dma32_req hashSha256Dma32Req; -wh_Packet_hash_sha256_Dma32_res hashSha256Dma32Res; +wh_Packet_hash_sha256_Dma32_req hashSha256Dma32Req; +wh_Packet_hash_sha256_Dma32_res hashSha256Dma32Res; +wh_Packet_pq_mldsa_keygen_Dma32_req pqMldsaKeygenDma32Req; +wh_Packet_pq_mldsa_Dma32_res pqMldsaDma32Res; +wh_Packet_pq_mldsa_sign_Dma32_req pqMldsaSignDma32Req; +wh_Packet_pq_mldsa_sign_Dma32_res pqMldsaSignDma32Res; +wh_Packet_pq_mldsa_verify_Dma32_req pqMldsaVerifyDma32Req; +wh_Packet_pq_mldsa_verify_Dma32_res pqMldsaVerifyDma32Res; #elif defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_64BIT -wh_Packet_hash_sha256_Dma64_req hashSha256Dma64Req; -wh_Packet_hash_sha256_Dma64_res hashSha256Dma64Res; +wh_Packet_hash_sha256_Dma64_req hashSha256Dma64Req; +wh_Packet_hash_sha256_Dma64_res hashSha256Dma64Res; +wh_Packet_pq_mldsa_keygen_Dma64_req pqMldsaKeygenDma64Req; +wh_Packet_pq_mldsa_Dma64_res pqMldsaDma64Res; +wh_Packet_pq_mldsa_sign_Dma64_req pqMldsaSignDma64Req; +wh_Packet_pq_mldsa_sign_Dma64_res pqMldsaSignDma64Res; +wh_Packet_pq_mldsa_verify_Dma64_req pqMldsaVerifyDma64Req; +wh_Packet_pq_mldsa_verify_Dma64_res pqMldsaVerifyDma64Res; #endif #endif /* !WOLFHSM_CFG_NO_CRYPTO */ + #ifdef WOLFHSM_CFG_SHE_EXTENSION wh_Packet_she_set_uid_req sheSetUidReq; wh_Packet_she_secure_boot_init_req sheSecureBootInitReq; diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 8eed6ac..0f11652 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -1384,7 +1384,11 @@ static int whTestCrypto_Cmac(whClientContext* ctx, int devId, WC_RNG* rng) #ifdef HAVE_DILITHIUM -static int whTestCrypto_MlDsa(whClientContext* ctx, int devId, WC_RNG* rng) +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && !defined(WOLFSSL_NO_ML_DSA_44) +static int whTestCrypto_MlDsaWolfCrypt(whClientContext* ctx, int devId, + WC_RNG* rng) { int ret = 0; int verified = 0; @@ -1463,12 +1467,625 @@ static int whTestCrypto_MlDsa(whClientContext* ctx, int devId, WC_RNG* rng) ret = -1; } - printf("ML DSA SUCCESS\n"); + printf("ML-DSA DEVID=0x%X SUCCESS\n", devId); wc_MlDsaKey_Free(&key); + return ret; } +static int whTestCrypto_MlDsaDmaClient(whClientContext* ctx, int devId, + WC_RNG* rng) +{ + int ret = 0; + MlDsaKey key[1]; + MlDsaKey imported_key[1]; + whKeyId keyId = WH_KEYID_ERASED; + uint8_t label[] = "ML-DSA Test Key"; + int keyImported = 0; + + /* Buffers for comparing serialized keys */ + byte key_der1[DILITHIUM_MAX_PRV_KEY_SIZE]; + byte key_der2[DILITHIUM_MAX_PRV_KEY_SIZE]; + word32 key_der1_len = sizeof(key_der1); + word32 key_der2_len = sizeof(key_der2); + + /* Initialize keys */ + ret = wc_MlDsaKey_Init(key, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize ML-DSA key: %d\n", ret); + return ret; + } + + ret = wc_MlDsaKey_Init(imported_key, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize imported ML-DSA key: %d\n", ret); + wc_MlDsaKey_Free(key); + return ret; + } + + /* Generate ephemeral key using DMA */ + if (ret == 0) { + ret = wh_Client_MlDsaMakeExportKeyDma(ctx, WC_ML_DSA_44, key); + if (ret != 0) { + WH_ERROR_PRINT("Failed to generate ML-DSA key using DMA: %d\n", + ret); + } + } + + /* Serialize the generated key for comparison */ + if (ret == 0) { + ret = wc_Dilithium_PrivateKeyToDer(key, key_der1, key_der1_len); + if (ret < 0) { + WH_ERROR_PRINT("Failed to serialize generated key: %d\n", ret); + } + else { + key_der1_len = ret; + ret = 0; + } + } + + /* Import the key to cache using DMA */ + if (ret == 0) { + ret = wh_Client_MlDsaImportKeyDma(ctx, key, &keyId, WH_NVM_FLAGS_NONE, + sizeof(label), label); + if (ret != 0) { + WH_ERROR_PRINT("Failed to import ML-DSA key using DMA: %d\n", ret); + } + keyImported = (ret == 0); + } + + /* Export the key back using DMA */ + if (ret == 0) { + ret = wh_Client_MlDsaExportKeyDma(ctx, keyId, imported_key, + sizeof(label), label); + if (ret != 0) { + WH_ERROR_PRINT("Failed to export ML-DSA key using DMA: %d\n", ret); + } + } + + /* Serialize the exported key for comparison */ + if (ret == 0) { + ret = + wc_Dilithium_PrivateKeyToDer(imported_key, key_der2, key_der2_len); + if (ret < 0) { + WH_ERROR_PRINT("Failed to serialize exported key: %d\n", ret); + } + else { + key_der2_len = ret; + ret = 0; + } + } + + /* Compare the keys */ + if (ret == 0) { + if (key_der1_len != key_der2_len || + XMEMCMP(key_der1, key_der2, key_der1_len) != 0) { + WH_ERROR_PRINT("Exported key does not match generated key\n"); + ret = -1; + } + } + /* Test signing and verification */ + if (ret == 0) { + byte msg[] = "Test message to sign"; + byte sig[DILITHIUM_MAX_SIG_SIZE]; + word32 sigLen = sizeof(sig); + int verified = 0; + + /* Sign the message */ + ret = wh_Client_MlDsaSignDma(ctx, msg, sizeof(msg), sig, &sigLen, key); + if (ret != 0) { + WH_ERROR_PRINT("Failed to sign message using ML-DSA: %d\n", ret); + } + else { + /* Verify the signature - should succeed */ + ret = wh_Client_MlDsaVerifyDma(ctx, sig, sigLen, msg, sizeof(msg), + &verified, key); + if (ret != 0) { + WH_ERROR_PRINT("Failed to verify signature using ML-DSA: %d\n", + ret); + } + else if (!verified) { + WH_ERROR_PRINT("Signature verification failed when it should " + "have succeeded\n"); + ret = -1; + } + else { + /* Modify signature and verify again - should fail */ + sig[0] ^= 0xFF; + ret = wh_Client_MlDsaVerifyDma(ctx, sig, sigLen, msg, + sizeof(msg), &verified, key); + if (ret != 0) { + WH_ERROR_PRINT("Failed to verify modified signature using " + "ML-DSA: %d\n", + ret); + } + else if (verified) { + WH_ERROR_PRINT("Signature verification succeeded when it " + "should have failed\n"); + ret = -1; + } + else { + /* Test passed - verification failed as expected */ + ret = 0; + } + } + } + } + + /* Clean up the cached key if it was imported */ + if (keyImported) { + int evict_ret = wh_Client_KeyEvict(ctx, keyId); + if (evict_ret != 0) { + WH_ERROR_PRINT("Failed to evict ML-DSA key: %d\n", evict_ret); + if (ret == 0) { + ret = evict_ret; + } + } + } + + + if (ret == 0) { + printf("ML-DSA Client DMA API SUCCESS\n"); + } + + wc_MlDsaKey_Free(key); + wc_MlDsaKey_Free(imported_key); + return ret; +} +#endif /* !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) */ + +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) +int whTestCrypto_MlDsaVerifyOnlyDma(whClientContext* ctx, int devId, + WC_RNG* rng) +{ + /* Vectors from wolfCrypt test vectors, but decoupled for isolated usage */ + const byte ml_dsa_44_pub_key[] = { + 0xd8, 0xac, 0xaf, 0xd8, 0x2e, 0x14, 0x23, 0x78, 0xf7, 0x0d, 0x9a, 0x04, + 0x2b, 0x92, 0x48, 0x67, 0x60, 0x55, 0x34, 0xd9, 0xac, 0x0b, 0xc4, 0x1f, + 0x46, 0xe8, 0x85, 0xb9, 0x2e, 0x1b, 0x10, 0x3a, 0x75, 0x7a, 0xc2, 0xbc, + 0x76, 0xf0, 0x6d, 0x05, 0xa4, 0x78, 0x48, 0x84, 0x26, 0x69, 0xbd, 0x26, + 0x1d, 0x73, 0x60, 0xaa, 0x57, 0x9d, 0x8c, 0x66, 0xb1, 0x19, 0xea, 0x11, + 0xff, 0xbb, 0xf6, 0xeb, 0x26, 0x26, 0xac, 0x78, 0x74, 0x46, 0x6d, 0x51, + 0x6e, 0x92, 0xdf, 0x6a, 0x98, 0x41, 0xe9, 0x10, 0xf2, 0xcc, 0xa8, 0x7a, + 0x50, 0xdb, 0x1f, 0x4c, 0x42, 0x19, 0xd5, 0xbc, 0x76, 0x20, 0x6f, 0x2f, + 0xbf, 0xc2, 0xc9, 0x1b, 0x02, 0xb5, 0xb1, 0x09, 0x46, 0x06, 0x87, 0x02, + 0xac, 0x3d, 0xcf, 0xc3, 0xa5, 0x1b, 0xf0, 0xce, 0xd4, 0x9e, 0x84, 0x34, + 0x3c, 0x24, 0x7d, 0x89, 0xf3, 0xbf, 0x9c, 0x18, 0x9d, 0x1b, 0x1d, 0xd4, + 0xf6, 0xda, 0xc9, 0xa4, 0x14, 0xc4, 0x6b, 0xd7, 0x05, 0x6d, 0xed, 0x54, + 0x42, 0x6b, 0x5f, 0x6d, 0x1e, 0xda, 0x6b, 0x47, 0x70, 0xe5, 0x4e, 0xe7, + 0x25, 0x06, 0xf8, 0x28, 0x24, 0x34, 0xd6, 0xe5, 0xbe, 0xc5, 0x4f, 0x9e, + 0x5d, 0x33, 0xfc, 0xef, 0xe4, 0xe9, 0x55, 0x67, 0x93, 0x1f, 0x2e, 0x11, + 0x3a, 0x2e, 0xf2, 0xbb, 0x82, 0x09, 0x8d, 0xb2, 0x09, 0xf3, 0x2f, 0xef, + 0x6f, 0x38, 0xc6, 0x56, 0xf2, 0x23, 0x08, 0x63, 0x99, 0x7f, 0x4e, 0xc0, + 0x9d, 0x08, 0x9d, 0xa1, 0x59, 0x6e, 0xe1, 0x00, 0x2c, 0x99, 0xec, 0x83, + 0x2f, 0x12, 0x97, 0x2f, 0x75, 0x04, 0x67, 0x44, 0xb5, 0x95, 0xce, 0xc6, + 0x3e, 0x7a, 0x10, 0x77, 0x5e, 0xbe, 0x9c, 0x0f, 0xb3, 0xc7, 0x38, 0xbf, + 0x9e, 0x35, 0x8f, 0xe4, 0x8d, 0x19, 0xc3, 0x41, 0xb1, 0x0b, 0x8c, 0x10, + 0x9a, 0x58, 0xec, 0x4f, 0xb3, 0xe9, 0x5b, 0x72, 0x4b, 0xb8, 0x99, 0x34, + 0x9a, 0xcd, 0xb0, 0x69, 0xd0, 0x67, 0xef, 0x96, 0xb9, 0xe5, 0x54, 0x92, + 0xb7, 0x1a, 0x52, 0xf6, 0x0a, 0xc2, 0x23, 0x8d, 0x4f, 0xad, 0x00, 0xae, + 0x0f, 0x97, 0xfa, 0xce, 0x96, 0xba, 0xe7, 0x74, 0x55, 0xd4, 0xaf, 0xbf, + 0xa1, 0x32, 0x91, 0x2d, 0x03, 0x9f, 0xe3, 0x10, 0x8c, 0x77, 0x5d, 0x26, + 0x76, 0xf1, 0x87, 0x90, 0xf0, 0x20, 0xd1, 0xea, 0xf7, 0xa4, 0xe8, 0x2c, + 0x32, 0x1c, 0x55, 0xc0, 0x5d, 0xc9, 0xcd, 0x4e, 0x8f, 0x0d, 0xef, 0x0a, + 0x27, 0xb6, 0x4f, 0xa4, 0xd3, 0xa4, 0xed, 0x33, 0x22, 0xa1, 0xd3, 0x15, + 0xac, 0x1a, 0x20, 0x4e, 0x28, 0x8c, 0x8c, 0xd0, 0x71, 0xd1, 0xf2, 0xdb, + 0x33, 0x63, 0xb6, 0xa4, 0xf2, 0x17, 0x3c, 0x12, 0xb0, 0xad, 0xef, 0x31, + 0x91, 0xfe, 0xe5, 0x53, 0x99, 0xb6, 0x85, 0x63, 0xfa, 0xe6, 0xcd, 0xf6, + 0xb9, 0xce, 0x4a, 0x7d, 0x4a, 0x49, 0x29, 0xd2, 0xd9, 0xc9, 0x47, 0x4a, + 0x8a, 0x5c, 0x14, 0x5e, 0x0f, 0x7c, 0xc3, 0x91, 0xb0, 0xab, 0x37, 0xf5, + 0x26, 0x8d, 0x46, 0x74, 0x49, 0xad, 0x51, 0xc3, 0x11, 0xfa, 0x85, 0x15, + 0xa5, 0x84, 0xc1, 0xe0, 0x3c, 0x13, 0x6d, 0x13, 0xa3, 0xe6, 0xa8, 0x3c, + 0x22, 0xac, 0x17, 0x48, 0x57, 0x7c, 0x81, 0xe2, 0x4e, 0xd8, 0x33, 0x5d, + 0x4d, 0x65, 0xf7, 0xe1, 0xb8, 0x00, 0x78, 0x09, 0x16, 0xb0, 0x0b, 0xca, + 0x15, 0x0d, 0xcd, 0x9a, 0xd8, 0x47, 0x4c, 0x9b, 0x69, 0xb2, 0xa0, 0x9d, + 0x96, 0x96, 0x52, 0x6d, 0x89, 0xad, 0xff, 0x55, 0xde, 0x7b, 0xd6, 0x3d, + 0x1d, 0x5e, 0x8d, 0xf1, 0xfc, 0x48, 0x1c, 0x50, 0x59, 0x55, 0xb9, 0x07, + 0xfd, 0x6b, 0xcb, 0x95, 0xa6, 0x14, 0x73, 0xdb, 0x40, 0x40, 0x1c, 0x44, + 0xe6, 0x79, 0x30, 0x88, 0xbd, 0xa0, 0xde, 0x9b, 0xb8, 0x76, 0xf8, 0x98, + 0x56, 0x4b, 0xb9, 0x7a, 0xf6, 0xd4, 0x73, 0x89, 0x6b, 0xf7, 0x7d, 0x05, + 0x33, 0xbe, 0xb6, 0x1c, 0x4d, 0xa7, 0x12, 0x3b, 0x3f, 0xed, 0x4a, 0x0f, + 0xae, 0xa7, 0x6a, 0x26, 0x0d, 0x01, 0x84, 0x84, 0xa8, 0x0e, 0xc1, 0xc1, + 0xfd, 0xe4, 0xa9, 0xe2, 0x3f, 0xab, 0xce, 0x20, 0x90, 0x86, 0x79, 0xa2, + 0x40, 0xd0, 0xef, 0x79, 0x34, 0x2b, 0xe8, 0xc9, 0x54, 0xa7, 0x19, 0x62, + 0xcc, 0x20, 0x79, 0x3f, 0x5b, 0x9c, 0x61, 0xc2, 0xc1, 0xd2, 0x36, 0x7c, + 0x8e, 0xe3, 0x01, 0xbe, 0xc4, 0xb2, 0xb8, 0x07, 0x51, 0x23, 0x5b, 0x5d, + 0x00, 0xe6, 0x7f, 0xd6, 0xbb, 0x32, 0xa9, 0x7e, 0xb4, 0x30, 0xeb, 0x5e, + 0x6d, 0xed, 0xb2, 0xc3, 0x88, 0x81, 0xa3, 0x3b, 0x1f, 0x1e, 0xf9, 0x48, + 0x10, 0xd6, 0x01, 0x65, 0x5f, 0x6d, 0xc5, 0xeb, 0x76, 0x5f, 0x10, 0x79, + 0xaa, 0xc0, 0x86, 0xe7, 0x44, 0x95, 0x44, 0x4b, 0x54, 0x0c, 0x46, 0x2a, + 0x98, 0x01, 0x6e, 0xc0, 0xb9, 0x59, 0x2a, 0xff, 0x8f, 0xb3, 0x80, 0x15, + 0xec, 0xcd, 0x39, 0x36, 0xd7, 0x2f, 0x20, 0x9e, 0x3a, 0xc1, 0x90, 0xe5, + 0x99, 0x27, 0x16, 0xd7, 0x6c, 0x30, 0x10, 0x12, 0x03, 0x3e, 0xdc, 0xb9, + 0x03, 0x25, 0xb0, 0x8a, 0x27, 0x4d, 0x1a, 0x32, 0x36, 0x54, 0xc0, 0xba, + 0x22, 0xb2, 0xe2, 0xf6, 0x39, 0x23, 0x03, 0xc4, 0xc9, 0xe4, 0x0d, 0x99, + 0xfb, 0x98, 0xa5, 0x9b, 0x12, 0x9b, 0x58, 0x44, 0x74, 0x9f, 0x65, 0x61, + 0x51, 0xba, 0x31, 0x60, 0x9c, 0xec, 0xf8, 0x4d, 0x36, 0x61, 0xd1, 0x33, + 0x6d, 0xa6, 0x28, 0x75, 0xba, 0x7c, 0x82, 0xcb, 0x7e, 0xbe, 0x8f, 0x2d, + 0x21, 0x84, 0xb9, 0xf2, 0x4e, 0x7b, 0x95, 0x99, 0x11, 0xf3, 0xe1, 0xc0, + 0x6a, 0x44, 0xae, 0x11, 0xcb, 0x04, 0xa0, 0xf2, 0x3e, 0x17, 0xdf, 0xb2, + 0x6a, 0xdf, 0x5c, 0xf3, 0x8a, 0xf8, 0x90, 0x86, 0x64, 0xea, 0x0a, 0x32, + 0x7f, 0x9f, 0x90, 0xa8, 0x9d, 0x33, 0x12, 0xa6, 0xa4, 0xe7, 0x74, 0xa0, + 0x75, 0xa9, 0x65, 0xf8, 0x39, 0xae, 0x14, 0x32, 0x79, 0xcc, 0xaa, 0x34, + 0x86, 0x55, 0xcc, 0x99, 0xb7, 0x00, 0x05, 0x8b, 0xe3, 0x76, 0x28, 0x12, + 0xb6, 0x2a, 0x3e, 0x44, 0x8d, 0xf4, 0xba, 0xef, 0xf6, 0xdc, 0x29, 0x08, + 0x29, 0x7d, 0xd1, 0x1d, 0x17, 0x15, 0xb6, 0xb6, 0x58, 0x67, 0xd5, 0xd3, + 0x12, 0x05, 0x4e, 0xb0, 0xc3, 0x83, 0xe0, 0x35, 0x30, 0x60, 0x59, 0xa0, + 0xc5, 0x97, 0x5b, 0x81, 0xd3, 0x68, 0x6c, 0x8c, 0x17, 0x28, 0xa9, 0x24, + 0x4f, 0x80, 0x20, 0xa5, 0x21, 0x9f, 0x8f, 0x15, 0x89, 0x2d, 0x87, 0xae, + 0x2e, 0xcc, 0x73, 0x3e, 0x06, 0x43, 0xbc, 0xb3, 0x1b, 0xa6, 0x72, 0xaa, + 0xa3, 0xaa, 0xbb, 0x6f, 0x2d, 0x68, 0x60, 0xcf, 0x05, 0x94, 0x25, 0x3e, + 0x59, 0xf3, 0x64, 0x61, 0x5e, 0x78, 0x9a, 0x7e, 0x0d, 0x50, 0x45, 0x78, + 0x51, 0xab, 0x11, 0xb1, 0xc6, 0x95, 0xfc, 0x29, 0x28, 0x10, 0x9c, 0x1a, + 0x8c, 0x37, 0xb5, 0x4f, 0x0e, 0xed, 0x4a, 0x28, 0x6c, 0xaa, 0xb7, 0x0d, + 0x12, 0xfa, 0x87, 0x5d, 0xd4, 0x9a, 0xb7, 0x2b, 0x46, 0x90, 0x58, 0x4e, + 0xd7, 0x8b, 0x41, 0x1b, 0xf8, 0xc4, 0xc2, 0xde, 0xda, 0xec, 0x61, 0xe7, + 0xbf, 0x11, 0xdd, 0x6e, 0x4e, 0x6a, 0xd4, 0x87, 0x01, 0xe4, 0xac, 0xe8, + 0xaf, 0x2b, 0x01, 0xe1, 0x09, 0x20, 0xe0, 0xbd, 0x7d, 0x03, 0x73, 0x23, + 0xdf, 0x77, 0x71, 0xa4, 0x25, 0x8b, 0x0a, 0x93, 0x49, 0x32, 0x45, 0x1a, + 0xa4, 0x94, 0x31, 0x61, 0x2e, 0x17, 0x39, 0x8a, 0x66, 0xc9, 0xf9, 0x20, + 0x2d, 0x6a, 0x97, 0x2f, 0xe7, 0x26, 0xd8, 0x01, 0x42, 0x65, 0xcf, 0xce, + 0xd4, 0x24, 0x41, 0xfb, 0x9b, 0x6f, 0xf1, 0xc2, 0x9e, 0xd5, 0x08, 0x0c, + 0xdc, 0x4d, 0x8e, 0xae, 0xcb, 0x5f, 0xd4, 0xcd, 0x7c, 0xf6, 0x82, 0xc6, + 0xee, 0xf9, 0x88, 0x3a, 0x34, 0x07, 0x04, 0xb4, 0x84, 0x69, 0xb3, 0xa4, + 0x67, 0xab, 0x09, 0xc0, 0x83, 0xfe, 0x59, 0xaf, 0x18, 0x2c, 0xc8, 0x09, + 0xc1, 0xbb, 0x13, 0x7c, 0xce, 0x01, 0x5d, 0x85, 0xaa, 0x10, 0x28, 0xa2, + 0x96, 0x98, 0x69, 0x23, 0xa3, 0xe7, 0x67, 0xbc, 0x7c, 0x7e, 0xde, 0x4b, + 0x36, 0xab, 0x94, 0xd2, 0xb8, 0xf9, 0xdf, 0xee, 0xa1, 0x69, 0xa1, 0xc8, + 0xe9, 0x83, 0x21, 0xac, 0x1b, 0x39, 0xf7, 0x6d, 0xbf, 0x8c, 0xdb, 0xd6, + 0x2f, 0xc9, 0x3c, 0x3d, 0x50, 0xcf, 0x7f, 0xbe, 0x4a, 0x8d, 0xd8, 0x14, + 0xad, 0x69, 0xb0, 0x3e, 0x8a, 0xaf, 0xeb, 0xd9, 0x1a, 0x15, 0x4a, 0xe4, + 0xdd, 0xd9, 0xb2, 0xf8, 0x6b, 0xe2, 0x42, 0x9e, 0x29, 0x16, 0xfc, 0x85, + 0x9c, 0x47, 0x4b, 0x1f, 0x3d, 0x7b, 0x8c, 0xe1, 0x6d, 0xa3, 0xb8, 0x0a, + 0xe6, 0xfa, 0x27, 0xfe, 0x52, 0x72, 0xab, 0x3a, 0xa6, 0x58, 0xd7, 0x53, + 0xaf, 0x9f, 0xee, 0x03, 0x85, 0xfc, 0xa4, 0x7a, 0x72, 0x29, 0x7e, 0x62, + 0x28, 0x08, 0x79, 0xa8, 0xb8, 0xc7, 0x51, 0x8d, 0xaa, 0x40, 0x2d, 0x4a, + 0xd9, 0x47, 0xb4, 0xa8, 0xa2, 0x0a, 0x43, 0xd0, 0xe0, 0x4a, 0x39, 0xa3, + 0x06, 0x08, 0x9a, 0xe2, 0xf3, 0xf2, 0xf8, 0xb9, 0x9f, 0x63, 0x32, 0xa0, + 0x65, 0x0b, 0xb0, 0x50, 0x96, 0xa6, 0xa8, 0x7a, 0x18, 0xdd, 0x6c, 0xd1, + 0x9b, 0xd9, 0x4e, 0x76, 0x8f, 0xfb, 0x22, 0xa6, 0x1d, 0x29, 0xfc, 0xb8, + 0x47, 0x29, 0xb6, 0xd1, 0xb1, 0x63, 0x4a, 0x36, 0x1b, 0x10, 0xe6, 0x4c, + 0x65, 0x68, 0x1f, 0xad, 0x4f, 0x7d, 0x6b, 0x01, 0x41, 0x18, 0x5f, 0xba, + 0x3d, 0xa6, 0x54, 0x28, 0x58, 0xd5, 0x81, 0x60, 0xdf, 0x84, 0x76, 0x00, + 0x21, 0x53, 0xeb, 0xd3, 0xa6, 0xec, 0x7d, 0x3c, 0xb8, 0xcd, 0x91, 0x4c, + 0x2f, 0x4b, 0x2e, 0x23, 0x4c, 0x0f, 0x0f, 0xe0, 0x14, 0xa5, 0xe7, 0xe5, + 0x70, 0x8d, 0x8b, 0x9c}; + const byte ml_dsa_44_sig[] = { + 0x27, 0x3b, 0x58, 0xa0, 0xcf, 0x00, 0x29, 0x5e, 0x1a, 0x63, 0xbf, 0xb4, + 0x97, 0x16, 0xa1, 0x9c, 0x78, 0xd1, 0x33, 0xdc, 0x72, 0xde, 0xa3, 0xfc, + 0xf4, 0x09, 0xb1, 0x09, 0x16, 0x3f, 0x80, 0x72, 0x22, 0x68, 0x65, 0x68, + 0xb9, 0x80, 0x5a, 0x4a, 0x0d, 0x73, 0x49, 0xe1, 0xc6, 0xde, 0xca, 0x08, + 0x4f, 0xca, 0xf8, 0xb2, 0xf8, 0x45, 0x3b, 0x6b, 0x8c, 0x6c, 0xfd, 0x3a, + 0xf4, 0xde, 0xde, 0x82, 0xd8, 0x04, 0xbe, 0x4f, 0x4a, 0xdb, 0x92, 0x47, + 0x83, 0x2d, 0xc4, 0x55, 0xed, 0x20, 0x4f, 0x71, 0xb1, 0x58, 0xd9, 0x70, + 0x73, 0xbd, 0xb0, 0x3a, 0xb4, 0x8f, 0xd6, 0x9e, 0x32, 0x98, 0x2b, 0x9e, + 0xff, 0x2a, 0x7c, 0xcb, 0x05, 0x1b, 0x8e, 0xe6, 0x3a, 0x45, 0xc6, 0x7a, + 0xc8, 0xaf, 0x62, 0xd3, 0x04, 0xfa, 0x69, 0x4f, 0xda, 0x1b, 0x74, 0x16, + 0x0d, 0xb3, 0x1a, 0xee, 0x71, 0xd7, 0xb0, 0xef, 0x69, 0xf5, 0xe2, 0xe9, + 0xc2, 0xcc, 0x15, 0x66, 0x28, 0x0a, 0xac, 0xe2, 0x63, 0x06, 0xb7, 0x21, + 0x0d, 0xd8, 0x5c, 0x94, 0x63, 0xfd, 0x51, 0x18, 0x9f, 0x07, 0x19, 0x3d, + 0xa2, 0x50, 0x40, 0xd3, 0xe9, 0x05, 0xd4, 0x11, 0x13, 0x15, 0xaa, 0x46, + 0xda, 0x3e, 0x5f, 0xcd, 0x3c, 0xfa, 0x42, 0xba, 0x79, 0x4a, 0xb7, 0x43, + 0x91, 0xa5, 0xcb, 0xbc, 0xeb, 0x37, 0x94, 0xf1, 0x9c, 0xb9, 0xdb, 0x41, + 0x06, 0xd8, 0x7b, 0x5e, 0x90, 0xe3, 0x3c, 0x8a, 0x10, 0x62, 0x9a, 0x15, + 0x27, 0x78, 0xed, 0x69, 0x11, 0x2c, 0xb5, 0xb4, 0xdb, 0xc8, 0x70, 0x50, + 0x62, 0x47, 0x96, 0xcb, 0xd9, 0xb2, 0x3e, 0x59, 0x2f, 0x1c, 0xac, 0xcb, + 0xcf, 0x22, 0xc2, 0x9b, 0xc7, 0x92, 0xe9, 0x4d, 0x8d, 0x5d, 0xcf, 0x06, + 0x53, 0x7e, 0xf4, 0x4e, 0xfe, 0x9e, 0x41, 0x5d, 0x00, 0x8c, 0x08, 0xf4, + 0x02, 0x79, 0x33, 0x1c, 0x27, 0x1d, 0xe3, 0x94, 0xac, 0xe6, 0x87, 0xa0, + 0x08, 0xb4, 0x60, 0x0c, 0xff, 0x47, 0xdc, 0x16, 0x3a, 0x1d, 0x89, 0xc0, + 0x6a, 0xa4, 0x3d, 0x71, 0x33, 0xdd, 0x1e, 0x70, 0xfe, 0xd4, 0x8b, 0xed, + 0x7c, 0x91, 0xe4, 0xe2, 0x15, 0x06, 0xc1, 0x83, 0x24, 0x55, 0xa7, 0x2a, + 0x9f, 0x4e, 0xd9, 0x56, 0x7a, 0x95, 0xa8, 0xdd, 0xc4, 0xf0, 0x71, 0x3a, + 0x99, 0x65, 0x31, 0x4b, 0xb7, 0x96, 0x2c, 0x53, 0x54, 0x83, 0xec, 0xc9, + 0x97, 0x2f, 0x0c, 0xa4, 0x8f, 0xbb, 0x93, 0x9d, 0xea, 0xae, 0xf9, 0xcb, + 0xb2, 0xb9, 0xa3, 0x61, 0x5f, 0x77, 0x8c, 0xb6, 0x5a, 0x56, 0xbe, 0x5f, + 0x85, 0xd1, 0xb5, 0x0a, 0x53, 0xe2, 0xc7, 0xbf, 0x76, 0x8b, 0x97, 0x6f, + 0x10, 0xdd, 0x1f, 0x44, 0x69, 0x66, 0x03, 0xc4, 0x6b, 0x59, 0xf7, 0xb4, + 0xc1, 0x12, 0xcc, 0x00, 0x70, 0xe8, 0xbd, 0x44, 0x28, 0xf5, 0xfa, 0x96, + 0xf3, 0x59, 0xed, 0x81, 0x67, 0xe0, 0xbe, 0x47, 0x75, 0xb3, 0xa8, 0x9f, + 0x21, 0x70, 0x2e, 0x6f, 0xef, 0x54, 0x11, 0x3f, 0x34, 0xaf, 0x0d, 0x73, + 0x5b, 0x9e, 0x6d, 0x86, 0x58, 0xb7, 0x34, 0xc2, 0xc2, 0xb3, 0x64, 0xd5, + 0x9b, 0x6e, 0xb9, 0x99, 0x6a, 0xe4, 0xfd, 0xc3, 0x17, 0xf3, 0x10, 0xfc, + 0x6e, 0xf5, 0x65, 0xe1, 0x9c, 0x59, 0x15, 0x11, 0x00, 0xea, 0x96, 0x81, + 0x69, 0x9b, 0x05, 0x4d, 0xf3, 0xce, 0xf3, 0xf0, 0xa9, 0x01, 0x3f, 0x13, + 0xbb, 0xb0, 0xac, 0xc3, 0x92, 0x1c, 0x2b, 0x61, 0xe3, 0x01, 0x22, 0x45, + 0x4a, 0x23, 0x19, 0x80, 0xca, 0xb9, 0xef, 0x4e, 0x76, 0x52, 0xc5, 0x9d, + 0x91, 0x33, 0x17, 0xc4, 0x28, 0x83, 0x55, 0x61, 0x49, 0x72, 0x04, 0xaa, + 0xf8, 0xe3, 0x4b, 0x20, 0xf7, 0x6a, 0x74, 0x56, 0x64, 0xf9, 0xb3, 0xc9, + 0x67, 0x5b, 0x55, 0x29, 0x9a, 0x89, 0xa5, 0x14, 0x67, 0xea, 0x6d, 0x6a, + 0xde, 0x98, 0x58, 0x73, 0x25, 0xa3, 0xdb, 0xed, 0x3d, 0x62, 0xaa, 0xe0, + 0x79, 0x7f, 0xa3, 0xd9, 0xb5, 0x4c, 0xe9, 0xa8, 0xdf, 0xfd, 0x59, 0x31, + 0x42, 0x81, 0x9e, 0xb7, 0x81, 0x3f, 0x0e, 0xfb, 0xef, 0x80, 0x71, 0x9d, + 0xb7, 0xa5, 0xfc, 0xb1, 0x80, 0xc9, 0x7e, 0x31, 0xd9, 0x47, 0xe2, 0xca, + 0x10, 0x7b, 0xd1, 0xa1, 0x1c, 0x28, 0xc7, 0x7f, 0x51, 0x26, 0xb1, 0x4e, + 0x57, 0xdd, 0x7d, 0x76, 0x5c, 0x5a, 0x85, 0xa7, 0x7b, 0x8c, 0xc5, 0x6e, + 0xac, 0x20, 0xf8, 0x49, 0x16, 0xd6, 0x64, 0xf5, 0xf4, 0x2c, 0x32, 0xa1, + 0x5d, 0xfb, 0x87, 0xb6, 0x14, 0xfe, 0x68, 0x7c, 0x4d, 0xce, 0xd7, 0x94, + 0xf9, 0x8b, 0xf0, 0x61, 0xfd, 0xe0, 0x83, 0x7f, 0x13, 0xec, 0x7a, 0xb7, + 0x41, 0x04, 0x51, 0x6e, 0x30, 0xa2, 0x01, 0xf7, 0x30, 0x12, 0xec, 0xd2, + 0x8f, 0x73, 0xe7, 0x8e, 0x12, 0xb4, 0xe5, 0xc1, 0xff, 0xdf, 0x67, 0x14, + 0xb1, 0xe9, 0xba, 0x36, 0x19, 0x18, 0xf4, 0xaa, 0xe0, 0xe4, 0x9d, 0xcd, + 0xe8, 0xe7, 0x2b, 0x33, 0xb3, 0xdc, 0xb9, 0x19, 0xd7, 0xad, 0xa4, 0x68, + 0xcd, 0x83, 0x77, 0x98, 0x36, 0x49, 0xd9, 0x32, 0x20, 0xfd, 0xfc, 0x34, + 0xe7, 0x54, 0xd9, 0xb5, 0x05, 0xab, 0x0e, 0x08, 0x0e, 0x16, 0x8a, 0x7d, + 0x91, 0x4c, 0xaa, 0x19, 0x04, 0x37, 0x35, 0xa5, 0xab, 0x6c, 0xee, 0xc4, + 0x90, 0xf0, 0x5f, 0xc7, 0xae, 0x82, 0xfd, 0x59, 0x53, 0xe5, 0x36, 0x5a, + 0x56, 0x37, 0x61, 0x69, 0xda, 0xe5, 0x8f, 0xfd, 0x2e, 0xd4, 0x9c, 0x7f, + 0xb6, 0x39, 0xa4, 0x8d, 0x0a, 0xab, 0x82, 0x0f, 0xfe, 0x84, 0x69, 0x44, + 0x8a, 0xa6, 0xd0, 0x39, 0xf9, 0x72, 0x68, 0xe7, 0x97, 0xd8, 0x6c, 0x7b, + 0xec, 0x85, 0x8c, 0x52, 0xc9, 0x97, 0xbb, 0xc4, 0x7a, 0x67, 0x22, 0x60, + 0x46, 0x9f, 0x16, 0xf1, 0x67, 0x0e, 0x1b, 0x50, 0x7c, 0xc4, 0x29, 0x15, + 0xbc, 0x55, 0x6a, 0x67, 0xf6, 0xa8, 0x85, 0x66, 0x89, 0x9f, 0xff, 0x38, + 0x28, 0xaa, 0x87, 0x91, 0xce, 0xde, 0x8d, 0x45, 0x5c, 0xa1, 0x25, 0x95, + 0xe2, 0x86, 0xdd, 0xa1, 0x87, 0x6a, 0x0a, 0xa8, 0x3e, 0x63, 0x0e, 0x21, + 0xa5, 0x6e, 0x08, 0x4d, 0x07, 0xb6, 0x26, 0xa8, 0x92, 0xdb, 0xed, 0x13, + 0x01, 0xc3, 0xba, 0xcf, 0xad, 0x01, 0xbc, 0xe5, 0xc0, 0xba, 0xbe, 0x7c, + 0x75, 0xf1, 0xb9, 0xfe, 0xd3, 0xf0, 0xa5, 0x2c, 0x8e, 0x10, 0xff, 0x99, + 0xcb, 0xe2, 0x2d, 0xdc, 0x2f, 0x76, 0x00, 0xf8, 0x51, 0x7c, 0xcc, 0x52, + 0x16, 0x0f, 0x18, 0x98, 0xea, 0x34, 0x06, 0x7f, 0xb7, 0x2e, 0xe9, 0x40, + 0xf0, 0x2d, 0x30, 0x3d, 0xc0, 0x67, 0x4c, 0xe6, 0x63, 0x40, 0x41, 0x42, + 0x96, 0xbb, 0x0b, 0xd6, 0xc9, 0x1c, 0x22, 0x7a, 0xa9, 0x4d, 0xcc, 0x5b, + 0xaa, 0x03, 0xc6, 0x3b, 0x1e, 0x2f, 0x11, 0xae, 0x34, 0x6f, 0x0c, 0xe9, + 0x16, 0x9c, 0x82, 0x3b, 0x90, 0x4c, 0x0e, 0xf0, 0xf9, 0x7f, 0x02, 0xca, + 0xb9, 0xa9, 0x49, 0x6d, 0x27, 0x73, 0xd0, 0xbf, 0x15, 0x61, 0x52, 0xbc, + 0xd6, 0x31, 0x59, 0x2b, 0x52, 0x5b, 0xaf, 0x3c, 0xc0, 0x8f, 0xdc, 0xd5, + 0x2c, 0x1d, 0xe4, 0xe9, 0x41, 0xe8, 0xd3, 0x35, 0xd6, 0xb1, 0xf3, 0x32, + 0xe0, 0x52, 0x08, 0x73, 0x99, 0xb6, 0x6b, 0xbc, 0x26, 0xfb, 0x2e, 0xa7, + 0xb7, 0xcd, 0x14, 0xf0, 0xf9, 0xe5, 0x3a, 0xd0, 0x05, 0x5b, 0x2b, 0x38, + 0xbd, 0x7c, 0xda, 0xd4, 0x15, 0x45, 0xfa, 0x3b, 0x6f, 0x94, 0x8e, 0x22, + 0xce, 0xfa, 0x53, 0xe0, 0x5f, 0xa6, 0x9d, 0x1c, 0x26, 0x91, 0x8a, 0xab, + 0x72, 0x5b, 0x18, 0x78, 0x69, 0x98, 0x3f, 0x8d, 0x33, 0x7c, 0x21, 0x93, + 0x9e, 0xf0, 0xaf, 0xb7, 0x30, 0xc8, 0xac, 0xbc, 0xdb, 0x9c, 0x29, 0x17, + 0x6b, 0x9d, 0x0f, 0x16, 0xd6, 0xc0, 0xcc, 0x3b, 0xce, 0x11, 0xe9, 0x64, + 0xc8, 0xd4, 0x4c, 0x98, 0x7c, 0x8f, 0xf1, 0x5e, 0x84, 0xe4, 0x72, 0xf9, + 0x69, 0xf5, 0x9d, 0xad, 0x95, 0x3b, 0xfb, 0x6d, 0x30, 0x7e, 0x0a, 0x47, + 0x5b, 0x26, 0xb2, 0x4e, 0xeb, 0x1a, 0xc3, 0x37, 0x16, 0x28, 0x79, 0x62, + 0xb4, 0x36, 0x85, 0x4a, 0x15, 0x5a, 0xc3, 0x6e, 0xbe, 0x7e, 0x00, 0xe9, + 0x4a, 0xa5, 0xd7, 0x90, 0xcf, 0x59, 0x63, 0x2d, 0x2b, 0xc2, 0xc6, 0x47, + 0xe6, 0x77, 0xb7, 0x6e, 0x9b, 0xc8, 0x0d, 0x18, 0x2b, 0x45, 0x2b, 0xc9, + 0x5a, 0x6e, 0xb4, 0x50, 0xa5, 0x23, 0x7d, 0x17, 0xcc, 0x49, 0xe2, 0xb3, + 0xf4, 0x6d, 0xb4, 0xb7, 0xbb, 0x9e, 0xdd, 0x20, 0x99, 0x19, 0xf5, 0x53, + 0x1f, 0xd0, 0xff, 0x67, 0xf3, 0x8e, 0x6a, 0xcd, 0x2a, 0x6e, 0x2b, 0x0a, + 0x90, 0xd7, 0xdb, 0xe1, 0xff, 0x1c, 0x40, 0xa1, 0xb0, 0x5d, 0x94, 0x4d, + 0x20, 0x14, 0x01, 0xa1, 0xa8, 0xd1, 0x15, 0xd2, 0xd9, 0x1b, 0xbf, 0xc2, + 0x8a, 0xd0, 0x02, 0xf6, 0x16, 0xa1, 0xb7, 0x40, 0xe0, 0x36, 0x88, 0xc8, + 0x17, 0x0a, 0xf0, 0xb6, 0x0d, 0x3c, 0x53, 0xb9, 0x51, 0xed, 0xef, 0x20, + 0x6f, 0xf3, 0x0c, 0xb5, 0xce, 0x0e, 0x9e, 0xfd, 0x0f, 0x5e, 0x3f, 0x8f, + 0x3c, 0xb7, 0x2a, 0xdb, 0xc6, 0xa7, 0xf2, 0x11, 0x6e, 0xdc, 0x05, 0x33, + 0xd4, 0xd8, 0xb0, 0x2d, 0x8a, 0xe5, 0x39, 0x82, 0x00, 0x49, 0x7d, 0xfd, + 0x32, 0x29, 0xbb, 0x79, 0x5d, 0xcb, 0x21, 0x7b, 0x2d, 0x36, 0x58, 0x73, + 0x52, 0x57, 0x52, 0x96, 0x4d, 0x89, 0x61, 0xf4, 0xad, 0x1f, 0x48, 0xd5, + 0x7a, 0x4a, 0xaa, 0x1c, 0xa1, 0xf4, 0xb4, 0x9c, 0x43, 0x3b, 0x95, 0x72, + 0xd0, 0x0e, 0x35, 0x82, 0x26, 0xd4, 0x2e, 0xe3, 0x83, 0x96, 0x97, 0x5a, + 0x7b, 0xfc, 0x48, 0x17, 0x3c, 0xba, 0x9e, 0x5f, 0x46, 0x1a, 0x53, 0xe3, + 0x2e, 0x78, 0x79, 0x80, 0xf6, 0x2d, 0x24, 0xcf, 0x62, 0xb6, 0x86, 0xeb, + 0xee, 0xec, 0xf2, 0x1d, 0x00, 0xc8, 0x28, 0x9d, 0x93, 0x16, 0xa7, 0xd9, + 0x11, 0x47, 0xe3, 0xc4, 0xb6, 0xc4, 0xa0, 0x99, 0x83, 0xc1, 0x17, 0xd8, + 0x8e, 0xde, 0x69, 0x1d, 0xcb, 0xdd, 0xe7, 0x86, 0x6f, 0xf2, 0x36, 0x07, + 0x23, 0x86, 0x0d, 0xe9, 0xad, 0x87, 0xae, 0x76, 0x98, 0x95, 0x51, 0xf2, + 0xb3, 0x11, 0xc5, 0x34, 0xf0, 0x0c, 0xf8, 0x29, 0x9c, 0x84, 0x4f, 0x81, + 0x49, 0x85, 0x63, 0x25, 0x16, 0xb0, 0xc3, 0xaa, 0xd7, 0x8a, 0x2e, 0x4b, + 0x97, 0x60, 0x74, 0xf8, 0xa7, 0x39, 0xec, 0x6c, 0x2c, 0x9b, 0x33, 0x3a, + 0x11, 0xbd, 0xa6, 0x90, 0x48, 0x65, 0xb1, 0xe7, 0x38, 0x53, 0x47, 0x1b, + 0x62, 0xd5, 0xb7, 0xa8, 0xd4, 0xae, 0xf5, 0x12, 0x06, 0x12, 0x54, 0xa2, + 0xce, 0xf1, 0x6b, 0x3a, 0xda, 0x63, 0x2e, 0x37, 0x2a, 0x25, 0x89, 0x30, + 0x98, 0x77, 0x1d, 0x4b, 0x5a, 0x1e, 0xb7, 0x3d, 0xed, 0x19, 0xec, 0x9f, + 0x64, 0x46, 0xa8, 0x2a, 0x79, 0xf3, 0x70, 0x39, 0x9f, 0x8c, 0xc3, 0x28, + 0xcc, 0x2a, 0xc0, 0xd0, 0xe6, 0x80, 0xf5, 0x01, 0x78, 0x72, 0x7f, 0xe7, + 0x2e, 0x7b, 0x5f, 0x05, 0xc3, 0x41, 0x33, 0x07, 0xdb, 0x9c, 0xa8, 0x96, + 0xa7, 0x21, 0x20, 0x23, 0xd0, 0x59, 0x39, 0x06, 0x19, 0xa4, 0x29, 0xe5, + 0x72, 0x39, 0x69, 0x23, 0xe3, 0xfa, 0x28, 0x63, 0xf5, 0x42, 0x3b, 0xca, + 0x88, 0x5d, 0x7e, 0x47, 0x93, 0xa8, 0x8c, 0x75, 0xf2, 0x19, 0x44, 0x43, + 0x15, 0x39, 0x03, 0x42, 0xd8, 0x1d, 0x81, 0x30, 0x8e, 0x84, 0x31, 0x24, + 0x75, 0x67, 0x4e, 0xbe, 0xfe, 0x0a, 0xd8, 0xc3, 0xe7, 0x5b, 0xe1, 0xd5, + 0x12, 0x6a, 0x69, 0x99, 0xcd, 0x35, 0xca, 0x22, 0x02, 0x65, 0xb3, 0x0f, + 0x50, 0xb6, 0xaa, 0xc6, 0x91, 0x5c, 0x4d, 0xd4, 0x07, 0x93, 0x46, 0xf0, + 0xcc, 0xe1, 0x92, 0x14, 0x91, 0x21, 0x43, 0xc4, 0xba, 0x45, 0x1c, 0x47, + 0x29, 0xdf, 0xff, 0x89, 0x60, 0xee, 0x89, 0x1e, 0xc3, 0xb4, 0xb9, 0x0b, + 0xc9, 0x7e, 0xd9, 0x15, 0xb0, 0x80, 0x91, 0xbe, 0xb9, 0x43, 0x48, 0x12, + 0x86, 0x8e, 0x79, 0x38, 0x4d, 0xce, 0x36, 0x7f, 0xc3, 0xe8, 0xb7, 0xb9, + 0x92, 0xbf, 0x27, 0x20, 0x54, 0xc8, 0x05, 0x63, 0x3b, 0xf5, 0x48, 0x1a, + 0xa9, 0x04, 0x6c, 0xb6, 0x0e, 0x11, 0xea, 0xf3, 0x59, 0xb9, 0xa6, 0xf6, + 0xf8, 0x0b, 0x15, 0xed, 0x30, 0xf9, 0xe4, 0xe5, 0x26, 0x2d, 0xbb, 0xc6, + 0x5b, 0x36, 0xbb, 0x73, 0xa6, 0x4f, 0xf5, 0x43, 0x9f, 0xd7, 0xb9, 0x0f, + 0xbc, 0x4f, 0x8d, 0xb8, 0xec, 0x1d, 0x42, 0x19, 0x56, 0x37, 0xc4, 0xcb, + 0xd0, 0x16, 0x85, 0xff, 0xd3, 0x9b, 0xef, 0xc8, 0x75, 0x37, 0xd1, 0x92, + 0xad, 0x21, 0x94, 0x1e, 0x9a, 0xf6, 0x2f, 0x6d, 0x30, 0xba, 0x37, 0xc3, + 0xdc, 0x11, 0xe0, 0x79, 0xa4, 0x92, 0x1f, 0xe4, 0xaa, 0x7a, 0x6b, 0x2a, + 0xe4, 0x04, 0xb7, 0xf9, 0x86, 0x95, 0xdb, 0xa8, 0xfc, 0x8a, 0x53, 0x21, + 0x31, 0x14, 0xf7, 0x40, 0x01, 0x78, 0x4e, 0x73, 0x18, 0xb3, 0x54, 0xd7, + 0xa6, 0x93, 0xf0, 0x70, 0x04, 0x1c, 0xe0, 0x2b, 0xef, 0xee, 0xd4, 0x64, + 0xa7, 0xd9, 0x9f, 0x81, 0x4f, 0xe5, 0x1e, 0xbe, 0x6e, 0xd2, 0xf6, 0x3a, + 0xba, 0xcf, 0x8c, 0x96, 0x2a, 0x3d, 0xf7, 0xe5, 0x5c, 0x59, 0x40, 0x9c, + 0xe3, 0xf9, 0x2b, 0x6d, 0x3d, 0xf2, 0x6f, 0x81, 0xd6, 0xab, 0x9c, 0xab, + 0xc6, 0xf7, 0x8f, 0xaa, 0xe5, 0x71, 0xe3, 0xc9, 0x8c, 0x1a, 0xeb, 0xc5, + 0x87, 0xe7, 0xb0, 0xde, 0x18, 0xba, 0xaa, 0x1e, 0xda, 0x12, 0x32, 0x16, + 0x94, 0x3a, 0x6e, 0x4f, 0x84, 0x06, 0x8e, 0x33, 0xf7, 0xfa, 0x35, 0xb8, + 0x45, 0xe4, 0x5e, 0x9e, 0x46, 0x05, 0x7a, 0xf7, 0xf4, 0x99, 0xad, 0xb9, + 0xdd, 0x55, 0xd9, 0x52, 0x3b, 0x93, 0xe3, 0x9b, 0x54, 0x1b, 0xe6, 0xa9, + 0x70, 0xd3, 0x48, 0xf9, 0x3d, 0xdb, 0x88, 0x63, 0x66, 0xa0, 0xab, 0x72, + 0x83, 0x6e, 0x8f, 0x78, 0x9d, 0x55, 0x46, 0x21, 0xca, 0x7c, 0xb7, 0x5d, + 0x16, 0xe8, 0x66, 0x3b, 0x7b, 0xaa, 0xfe, 0x9c, 0x9c, 0x33, 0xc9, 0xc2, + 0xa4, 0x3c, 0x78, 0x97, 0xf3, 0x5b, 0xc2, 0x29, 0x36, 0x98, 0x68, 0x28, + 0xfe, 0x0a, 0xae, 0x6f, 0xe5, 0xf7, 0xfb, 0x9d, 0xf8, 0x8c, 0xd9, 0xd0, + 0x4d, 0xfe, 0xc7, 0xd0, 0xb0, 0xe3, 0x9c, 0xdb, 0xac, 0x9e, 0x1b, 0x55, + 0x7e, 0x24, 0xfe, 0xc4, 0x12, 0xcb, 0xc2, 0xdd, 0x0a, 0xda, 0x31, 0x40, + 0x41, 0xb7, 0xfc, 0x3f, 0x6d, 0xe2, 0xd3, 0x8a, 0x0f, 0x21, 0x33, 0x3a, + 0xbc, 0xa7, 0x62, 0x18, 0xb3, 0xaf, 0x48, 0xc6, 0xe2, 0xa3, 0xdd, 0x1d, + 0x20, 0x62, 0xe4, 0x4b, 0x81, 0x6b, 0x3a, 0xc5, 0xb1, 0x07, 0xe1, 0xf1, + 0xe1, 0xba, 0xf6, 0x01, 0xc6, 0xf2, 0xea, 0xc0, 0x97, 0x73, 0x79, 0x19, + 0x06, 0xaa, 0x62, 0x42, 0xcb, 0x21, 0x5f, 0x08, 0x97, 0x7d, 0x72, 0xb5, + 0x39, 0x4d, 0x99, 0xe3, 0xa2, 0x3f, 0xb9, 0xb4, 0xed, 0xf4, 0x61, 0x35, + 0xe1, 0x50, 0xfb, 0x56, 0x7c, 0x35, 0xfd, 0x44, 0x8a, 0x57, 0x22, 0xed, + 0x30, 0x33, 0xc3, 0x0b, 0xf1, 0x88, 0xe4, 0x44, 0x46, 0xf5, 0x73, 0x6d, + 0x9b, 0x98, 0x88, 0x92, 0xf5, 0x34, 0x85, 0x18, 0x66, 0xef, 0x70, 0xbe, + 0x7b, 0xc1, 0x0f, 0x1c, 0x78, 0x2d, 0x42, 0x13, 0x2d, 0x2f, 0x4d, 0x40, + 0x8e, 0xe2, 0x6f, 0xe0, 0x04, 0xdb, 0x58, 0xbc, 0x65, 0x80, 0xba, 0xfc, + 0x89, 0xee, 0xf3, 0x78, 0xb2, 0xd9, 0x78, 0x93, 0x6d, 0xbf, 0xd4, 0x74, + 0x24, 0xf4, 0x5c, 0x37, 0x89, 0x0c, 0x14, 0xd5, 0xbd, 0xc5, 0xfc, 0x37, + 0xe8, 0x8b, 0xe0, 0xc5, 0x89, 0xc9, 0x70, 0xb3, 0x76, 0x46, 0xce, 0x0d, + 0x7c, 0x3d, 0xa4, 0x5d, 0x02, 0x95, 0x03, 0xba, 0x24, 0xaa, 0xf7, 0xd0, + 0x75, 0x35, 0x78, 0x27, 0x9c, 0x6d, 0x2a, 0xef, 0xaa, 0xac, 0x85, 0xef, + 0x8d, 0xfc, 0xc0, 0xfc, 0x72, 0x02, 0xf4, 0xa3, 0xd3, 0x87, 0xfc, 0x4d, + 0xce, 0x3d, 0xcb, 0xc2, 0x74, 0x5b, 0xb0, 0x83, 0xc5, 0x72, 0x72, 0xd6, + 0xa1, 0x67, 0x4d, 0xa1, 0xd6, 0xaa, 0xe7, 0x9b, 0xe7, 0xc0, 0xfd, 0x86, + 0x91, 0x08, 0xfa, 0x48, 0x2f, 0x50, 0xce, 0x17, 0xea, 0x1c, 0xe3, 0x90, + 0x35, 0xe6, 0x6c, 0xc9, 0x66, 0x7d, 0x51, 0x32, 0x20, 0x0c, 0x2d, 0x4b, + 0xa1, 0xbf, 0x78, 0x87, 0xe1, 0x5a, 0x28, 0x0e, 0x9a, 0x85, 0xf6, 0x7e, + 0x39, 0x60, 0xbc, 0x64, 0x42, 0x5d, 0xf0, 0x0a, 0xd7, 0x3e, 0xbb, 0xa0, + 0x6d, 0x7c, 0xfa, 0x75, 0xee, 0x34, 0x39, 0x23, 0x0e, 0xbd, 0x50, 0x19, + 0x7a, 0x2a, 0xb7, 0x17, 0x3a, 0x8b, 0xb7, 0xb6, 0xf4, 0xd8, 0x47, 0x71, + 0x6b, 0x21, 0x1b, 0x56, 0xcc, 0xfb, 0x7b, 0x81, 0x99, 0x46, 0x88, 0x23, + 0x40, 0x49, 0x66, 0x8b, 0xac, 0x84, 0x16, 0x8a, 0x86, 0xae, 0x38, 0xc4, + 0x5b, 0x1f, 0x2b, 0xfa, 0xf2, 0x8b, 0x81, 0xc1, 0x22, 0x61, 0x61, 0x6c, + 0x43, 0x16, 0x8c, 0x1d, 0x37, 0xb2, 0xaf, 0x3c, 0x3a, 0x90, 0x33, 0xed, + 0xf5, 0x08, 0x78, 0xfd, 0x5a, 0xde, 0xd3, 0x38, 0x6d, 0xd7, 0x1c, 0x23, + 0xeb, 0xb4, 0x9b, 0x8e, 0xc2, 0x48, 0x47, 0x8e, 0x84, 0xbb, 0xc4, 0xd0, + 0xcc, 0xf9, 0x55, 0x5a, 0x57, 0xb9, 0x99, 0x52, 0x82, 0x21, 0x3b, 0x83, + 0xda, 0x8f, 0xa3, 0x88, 0x9c, 0x57, 0xe0, 0x4b, 0xc1, 0xce, 0xbe, 0xd3, + 0xea, 0xdd, 0xf2, 0x07, 0xc1, 0x73, 0x6f, 0xc0, 0x5e, 0x8e, 0x85, 0x72, + 0xab, 0x2f, 0xa9, 0xac, 0x39, 0xee, 0x05, 0x34, 0x13, 0x16, 0x1b, 0x1c, + 0x21, 0x24, 0x41, 0x49, 0x78, 0x87, 0x8b, 0x97, 0x9c, 0x9f, 0xa3, 0xa8, + 0xb9, 0xbc, 0xc6, 0xcc, 0xf2, 0xfd, 0x18, 0x2a, 0x46, 0x58, 0x5a, 0x88, + 0xa2, 0xb5, 0xcc, 0xd2, 0xda, 0xe1, 0xe3, 0x0d, 0x20, 0x23, 0x2b, 0x2f, + 0x47, 0x57, 0x5e, 0x64, 0x87, 0x97, 0x9c, 0xa7, 0xaa, 0xbc, 0xc1, 0xe4, + 0xe5, 0xea, 0x0b, 0x16, 0x3b, 0x3c, 0x3e, 0x45, 0x58, 0x63, 0x6a, 0x6f, + 0x7c, 0x8c, 0x8d, 0x92, 0x99, 0x9c, 0xad, 0xb5, 0xb7, 0xce, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x23, 0x36, 0x4a}; + static byte test_msg[512] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, + 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, + 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, + 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}; + + int ret; + MlDsaKey key[1]; + whNvmId keyId = WH_KEYID_ERASED; + int evictKey = 0; + + /* Initialize keys */ + ret = wc_MlDsaKey_Init(key, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize ML-DSA key: %d\n", ret); + return ret; + } + else { + ret = wc_dilithium_set_level(key, WC_ML_DSA_44); + if (ret != 0) { + WH_ERROR_PRINT("Failed to set ML-DSA level: %d\n", ret); + } + } + + /* make dummy msg */ + int i = 0; + for (i = 0; i < (int)sizeof(test_msg); i++) { + test_msg[i] = (byte)i; + } + + /* Import the raw public key into the wolfCrypt structure */ + if (ret == 0) { + ret = wc_MlDsaKey_ImportPubRaw(key, ml_dsa_44_pub_key, + sizeof(ml_dsa_44_pub_key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to import ML-DSA public key: %d\n", ret); + } + } + /* Import the key into wolfHSM via the wolfCrypt structure */ + if (ret == 0) { + if (devId == WH_DEV_ID_DMA) { + ret = wh_Client_MlDsaImportKeyDma(ctx, key, &keyId, 0, 0, NULL); + } + else { + ret = wh_Client_MlDsaImportKey(ctx, key, &keyId, 0, 0, NULL); + } + if (ret == WH_ERROR_OK) { + evictKey = 1; + } + else { + WH_ERROR_PRINT("Failed to import ML-DSA key: %d\n", ret); + } + } + + /* Cache the key using DMA and set the key ID */ + if (ret == 0) { + ret = wh_Client_MlDsaSetKeyId(key, keyId); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to set key ID: %d\n", ret); + } + } + + /* Verify the message signature */ + if (ret == 0) { + int verifyResult; + ret = wc_MlDsaKey_Verify(key, ml_dsa_44_sig, sizeof(ml_dsa_44_sig), + test_msg, sizeof(test_msg), &verifyResult); + if (ret != 0) { + WH_ERROR_PRINT("Signature did not verify\n"); + } + } + + if (evictKey) { + if (WH_ERROR_OK != wh_Client_KeyEvict(ctx, keyId)) { + WH_ERROR_PRINT("Failed to evict key\n"); + } + } + wc_MlDsaKey_Free(key); + + if (ret == WH_ERROR_OK) { + printf("ML-DSA VERIFY ONLY: SUCCESS\n"); + } + + return ret; +} + +#endif /* !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) */ + #endif /* HAVE_DILITHIUM */ @@ -1539,8 +2156,7 @@ int whTest_CryptoClientConfig(whClientConfig* config) #ifndef NO_SHA256 i = 0; - while ( (ret == WH_ERROR_OK) && - (i < WH_NUM_DEVIDS)) { + while ((ret == WH_ERROR_OK) && (i < WH_NUM_DEVIDS)) { ret = whTest_CryptoSha256(client, WH_DEV_IDS_ARRAY[i], rng); if (ret == WH_ERROR_OK) { i++; @@ -1549,9 +2165,41 @@ int whTest_CryptoClientConfig(whClientConfig* config) #endif /* !NO_SHA256 */ #ifdef HAVE_DILITHIUM + +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) + + i = 0; + while (ret == WH_ERROR_OK && i < WH_NUM_DEVIDS) { +#ifdef WOLFHSM_CFG_TEST_CLIENT_LARGE_DATA_DMA_ONLY + if (WH_DEV_IDS_ARRAY[i] != WH_DEV_ID_DMA) { + i++; + continue; + } +#endif /* WOLFHSM_CFG_TEST_CLIENT_LARGE_DATA_DMA_ONLY */ + ret = whTestCrypto_MlDsaWolfCrypt(client, WH_DEV_IDS_ARRAY[i], rng); + if (ret == WH_ERROR_OK) { + i++; + } + } if (ret == 0) { - ret = whTestCrypto_MlDsa(client, WH_DEV_ID, rng); + ret = whTestCrypto_MlDsaDmaClient(client, WH_DEV_ID_DMA, rng); } +#endif /* !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) */ + +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) + if (ret == 0) { + ret = whTestCrypto_MlDsaVerifyOnlyDma(client, WH_DEV_ID_DMA, rng); + } +#endif /* !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_NO_ML_DSA_44) */ + #endif /* HAVE_DILITHIUM */ #ifdef WOLFHSM_CFG_TEST_VERBOSE diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index b9423d1..4d99eaf 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -542,13 +542,12 @@ int wh_Client_MlDsaExportKey(whClientContext* ctx, whKeyId keyId, MlDsaKey* key, * * @param[in] ctx Pointer to the client context structure. * @param[in] type The ML-DSA algorithm type. - * @param[in,out] key Pointer to the ML-DSA key structure to store the key. * @param[in] size Size of the key in bits. - * @param[in] rng Pointer to initialized RNG structure. + * @param[in,out] key Pointer to the ML-DSA key structure to store the key. * @return int Returns 0 on success, or a negative error code on failure. */ -int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int type, MlDsaKey* key, - int size, WC_RNG* rng); +int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int type, int size, + MlDsaKey* key); /** * @brief Create and cache a new ML-DSA key on the server. * @@ -564,23 +563,6 @@ int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int type, MlDsaKey* key, int wh_Client_MlDsaMakeCacheKey(whClientContext* ctx, int size, int level, whKeyId* inout_key_id, whNvmFlags flags, uint16_t label_len, uint8_t* label); - -/** - * @brief Generate a new ML-DSA key pair and export it. - * - * This function generates a new ML-DSA key pair in the HSM and exports both - * the public and private key components to the client. - * - * @param[in] ctx Pointer to the client context structure. - * @param[in] level The ML-DSA security level. - * @param[out] key Pointer to the ML-DSA key structure to store the key. - * @param[in] size Size of the key in bits. - * @param[in] rng Pointer to initialized RNG structure. - * @return int Returns 0 on success, or a negative error code on failure. - */ -int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, MlDsaKey* key, - int size, WC_RNG* rng); - /** * @brief Sign a message using a ML-DSA private key. * @@ -593,12 +575,11 @@ int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, MlDsaKey* key, * @param[out] out Buffer to store the signature. * @param[in,out] out_len Pointer to size of output buffer, updated with actual * size. - * @param[in] rng Pointer to initialized RNG structure. * @param[in] key Pointer to the ML-DSA key structure. * @return int Returns 0 on success, or a negative error code on failure. */ int wh_Client_MlDsaSign(whClientContext* ctx, const byte* in, word32 in_len, - byte* out, word32* out_len, WC_RNG* rng, MlDsaKey* key); + byte* out, word32* out_len, MlDsaKey* key); /** * @brief Verify a ML-DSA signature. @@ -632,6 +613,109 @@ int wh_Client_MlDsaVerify(whClientContext* ctx, const byte* sig, word32 sig_len, */ int wh_Client_MlDsaCheckPrivKey(whClientContext* ctx, MlDsaKey* key, const byte* pubKey, word32 pubKeySz); + + +#ifdef WOLFHSM_CFG_DMA +/** + * @brief Import a ML-DSA key using DMA. + * + * This function imports a ML-DSA key into the HSM using DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] key Pointer to the ML-DSA key structure representing the key to + * import. + * @param[in,out] inout_keyId Pointer to store/provide the key ID. + * @param[in] flags NVM flags for key storage. + * @param[in] label_len Length of the key label in bytes. + * @param[in] label Pointer to the key label. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaImportKeyDma(whClientContext* ctx, MlDsaKey* key, + whKeyId* inout_keyId, whNvmFlags flags, + uint16_t label_len, uint8_t* label); + +/** + * @brief Export a ML-DSA key using DMA. + * + * This function exports a ML-DSA key from the HSM using DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] keyId ID of the key to export. + * @param[out] key Pointer to the ML-DSA key structure to hold the exported key. + * @param[in] label_len Length of the key label in bytes. + * @param[in] label Pointer to the key label. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaExportKeyDma(whClientContext* ctx, whKeyId keyId, + MlDsaKey* key, uint16_t label_len, + uint8_t* label); + +/** + * @brief Generate a new ML-DSA key pair and export it using DMA. + * + * This function generates a new ML-DSA key pair in the HSM and exports it using + * DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] level The ML-DSA security level. + * @param[out] key Pointer to the ML-DSA key structure to store the key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaMakeExportKeyDma(whClientContext* ctx, int level, + MlDsaKey* key); + + +/** + * @brief Sign a message using ML-DSA with DMA. + * + * This function signs a message using ML-DSA with DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] in Pointer to the message to sign. + * @param[in] in_len Length of the message in bytes. + * @param[out] out Pointer to store the signature. + * @param[in,out] out_len On input, size of out buffer. On output, length of + * signature. + * @param[in] key Pointer to the ML-DSA key structure. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaSignDma(whClientContext* ctx, const byte* in, word32 in_len, + byte* out, word32* out_len, MlDsaKey* key); + +/** + * @brief Verify a ML-DSA signature with DMA. + * + * This function verifies a ML-DSA signature with DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] sig Pointer to the signature to verify. + * @param[in] sig_len Length of the signature in bytes. + * @param[in] msg Pointer to the message that was signed. + * @param[in] msg_len Length of the message in bytes. + * @param[out] res Result of verification (1 = success, 0 = failure). + * @param[in] key Pointer to the ML-DSA key structure. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaVerifyDma(whClientContext* ctx, const byte* sig, + word32 sig_len, const byte* msg, word32 msg_len, + int* res, MlDsaKey* key); + +/** + * @brief Check a ML-DSA private key against public key with DMA. + * + * This function checks if a ML-DSA private key matches a public key with DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] key Pointer to the ML-DSA private key structure. + * @param[in] pubKey Pointer to the public key to check against. + * @param[in] pubKeySz Size of the public key in bytes. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_MlDsaCheckPrivKeyDma(whClientContext* ctx, MlDsaKey* key, + const byte* pubKey, word32 pubKeySz); + +#endif /* WOLFHSM_CFG_DMA */ + #endif /* HAVE_DILITHIUM */ #endif /* !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/wolfhsm/wh_packet.h b/wolfhsm/wh_packet.h index 8a3d097..8324893 100644 --- a/wolfhsm/wh_packet.h +++ b/wolfhsm/wh_packet.h @@ -651,6 +651,115 @@ typedef struct wh_Packet_hash_sha256_Dma64_res { wh_Packet_Dma64_addr_status dmaAddrStatus; } wh_Packet_hash_sha256_Dma64_res; +/* ML-DSA DMA key generation messages */ +typedef struct wh_Packet_pq_mldsa_keygen_Dma32_req { + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + wh_Packet_Dma32_buffer key; /* Key output buffer (pub or pub+priv) */ + uint32_t level; /* ML-DSA security level */ + uint32_t flags; /* Key generation flags */ + uint32_t keyId; /* Output keyId if successful */ + uint32_t access; /* Key access permissions */ + uint32_t labelSize; /* Size of label */ + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD2[4]; /* Final padding for 8-byte alignment */ +} wh_Packet_pq_mldsa_keygen_Dma32_req; + +typedef struct wh_Packet_pq_mldsa_Dma32_res { + wh_Packet_Dma32_addr_status dmaAddrStatus; + uint32_t keyId; /* Assigned key ID */ + uint32_t keySize; /* Actual size of generated key */ +} wh_Packet_pq_mldsa_Dma32_res; + +/* 64-bit version */ +typedef struct wh_Packet_pq_mldsa_keygen_Dma64_req { + uint32_t type; + uint32_t pqAlgoType; + wh_Packet_Dma64_buffer key; + uint32_t level; + uint32_t flags; + uint32_t keyId; + uint32_t access; /* Key access permissions */ + uint32_t labelSize; + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD2[4]; /* Final padding for 8-byte alignment */ +} wh_Packet_pq_mldsa_keygen_Dma64_req; + +typedef struct wh_Packet_pq_mldsa_Dma64_res { + wh_Packet_Dma64_addr_status dmaAddrStatus; + uint32_t keyId; /* Assigned key ID */ + uint32_t keySize; /* Actual size of generated key */ +} wh_Packet_pq_mldsa_Dma64_res; + +/* ML-DSA DMA sign request structures */ +typedef struct wh_Packet_pq_mldsa_sign_Dma32_req { + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + wh_Packet_Dma32_buffer msg; /* Message buffer */ + wh_Packet_Dma32_buffer sig; /* Signature buffer */ + uint32_t options; /* Same options as non-DMA version */ + uint32_t level; /* ML-DSA security level */ + uint32_t keyId; /* Key ID to use for signing */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_sign_Dma32_req; + +typedef struct wh_Packet_pq_mldsa_sign_Dma64_req { + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + wh_Packet_Dma64_buffer msg; /* Message buffer */ + wh_Packet_Dma64_buffer sig; /* Signature buffer */ + uint32_t options; /* Same options as non-DMA version */ + uint32_t level; /* ML-DSA security level */ + uint32_t keyId; /* Key ID to use for signing */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_sign_Dma64_req; + +typedef struct wh_Packet_pq_mldsa_sign_Dma32_res { + wh_Packet_Dma32_addr_status dmaAddrStatus; + uint32_t sigLen; /* Actual signature length */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_sign_Dma32_res; + +typedef struct wh_Packet_pq_mldsa_sign_Dma64_res { + wh_Packet_Dma64_addr_status dmaAddrStatus; + uint32_t sigLen; /* Actual signature length */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_sign_Dma64_res; + +/* ML-DSA DMA verify request/response structures */ +typedef struct wh_Packet_pq_mldsa_verify_Dma32_req { + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + wh_Packet_Dma32_buffer sig; /* Signature buffer */ + wh_Packet_Dma32_buffer msg; /* Message buffer */ + uint32_t options; /* Same options as non-DMA version */ + uint32_t level; /* ML-DSA security level */ + uint32_t keyId; /* Key ID to use for verification */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_verify_Dma32_req; + +typedef struct wh_Packet_pq_mldsa_verify_Dma64_req { + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + wh_Packet_Dma64_buffer sig; /* Signature buffer */ + wh_Packet_Dma64_buffer msg; /* Message buffer */ + uint32_t options; /* Same options as non-DMA version */ + uint32_t level; /* ML-DSA security level */ + uint32_t keyId; /* Key ID to use for verification */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_verify_Dma64_req; + +typedef struct wh_Packet_pq_mldsa_verify_Dma32_res { + wh_Packet_Dma32_addr_status dmaAddrStatus; + int32_t verifyResult; /* Result of verification */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_verify_Dma32_res; + +typedef struct wh_Packet_pq_mldsa_verify_Dma64_res { + wh_Packet_Dma64_addr_status dmaAddrStatus; + int32_t verifyResult; /* Result of verification */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_pq_mldsa_verify_Dma64_res; /** SHE Packets */ #ifdef WOLFHSM_CFG_SHE_EXTENSION @@ -953,21 +1062,34 @@ typedef struct whPacket /* DMA messages*/ #if defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_32BIT - wh_Packet_hash_sha256_Dma32_req hashSha256Dma32Req; - wh_Packet_hash_sha256_Dma32_res hashSha256Dma32Res; - wh_Packet_key_cache_Dma32_req keyCacheDma32Req; - wh_Packet_key_cache_Dma32_res keyCacheDma32Res; - wh_Packet_key_export_Dma32_req keyExportDma32Req; - wh_Packet_key_export_Dma32_res keyExportDma32Res; + wh_Packet_hash_sha256_Dma32_req hashSha256Dma32Req; + wh_Packet_hash_sha256_Dma32_res hashSha256Dma32Res; + wh_Packet_key_cache_Dma32_req keyCacheDma32Req; + wh_Packet_key_cache_Dma32_res keyCacheDma32Res; + wh_Packet_key_export_Dma32_req keyExportDma32Req; + wh_Packet_key_export_Dma32_res keyExportDma32Res; + wh_Packet_pq_mldsa_keygen_Dma32_req pqMldsaKeygenDma32Req; + wh_Packet_pq_mldsa_Dma32_res pqMldsaDma32Res; + wh_Packet_pq_mldsa_sign_Dma32_req pqMldsaSignDma32Req; + wh_Packet_pq_mldsa_sign_Dma32_res pqMldsaSignDma32Res; + wh_Packet_pq_mldsa_verify_Dma32_req pqMldsaVerifyDma32Req; + wh_Packet_pq_mldsa_verify_Dma32_res pqMldsaVerifyDma32Res; #elif defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_64BIT - wh_Packet_hash_sha256_Dma64_req hashSha256Dma64Req; - wh_Packet_hash_sha256_Dma64_res hashSha256Dma64Res; - wh_Packet_key_cache_Dma64_req keyCacheDma64Req; - wh_Packet_key_cache_Dma64_res keyCacheDma64Res; - wh_Packet_key_export_Dma64_req keyExportDma64Req; - wh_Packet_key_export_Dma64_res keyExportDma64Res; + wh_Packet_hash_sha256_Dma64_req hashSha256Dma64Req; + wh_Packet_hash_sha256_Dma64_res hashSha256Dma64Res; + wh_Packet_key_cache_Dma64_req keyCacheDma64Req; + wh_Packet_key_cache_Dma64_res keyCacheDma64Res; + wh_Packet_key_export_Dma64_req keyExportDma64Req; + wh_Packet_key_export_Dma64_res keyExportDma64Res; + wh_Packet_pq_mldsa_keygen_Dma64_req pqMldsaKeygenDma64Req; + wh_Packet_pq_mldsa_Dma64_res pqMldsaDma64Res; + wh_Packet_pq_mldsa_sign_Dma64_req pqMldsaSignDma64Req; + wh_Packet_pq_mldsa_sign_Dma64_res pqMldsaSignDma64Res; + wh_Packet_pq_mldsa_verify_Dma64_req pqMldsaVerifyDma64Req; + wh_Packet_pq_mldsa_verify_Dma64_res pqMldsaVerifyDma64Res; #endif + #ifdef WOLFHSM_CFG_SHE_EXTENSION wh_Packet_she_set_uid_req sheSetUidReq; wh_Packet_she_secure_boot_init_req sheSecureBootInitReq;