From caf937deb2cb18ebae0d2841ca0f68b48a64b6f9 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:31:23 -0700 Subject: [PATCH 1/3] Initial support for ML-DSA --- src/wh_client_crypto.c | 493 +++++++++++++++++++++++++++++++++++++ src/wh_client_cryptocb.c | 144 +++++++++++ src/wh_comm.c | 10 + src/wh_crypto.c | 34 +++ src/wh_server_crypto.c | 342 +++++++++++++++++++++++++ src/wh_transport_mem.c | 10 + test/Makefile | 4 +- test/user_settings.h | 11 +- test/wh_test_crypto.c | 106 +++++++- test/wolfhsm_cfg.h | 4 +- wolfhsm/wh_client_crypto.h | 156 ++++++++++++ wolfhsm/wh_crypto.h | 10 + wolfhsm/wh_packet.h | 92 +++++++ wolfhsm/wh_server_crypto.h | 10 + 14 files changed, 1416 insertions(+), 10 deletions(-) diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index fd7f6c63..81196185 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -2072,4 +2072,497 @@ int wh_Client_CmacCancelableResponse(whClientContext* c, Cmac* cmac, return ret; } #endif /* WOLFSSL_CMAC */ + +#ifdef HAVE_DILITHIUM + +int wh_Client_MlDsaSetKeyId(MlDsaKey* key, whKeyId keyId) +{ + if (key == NULL) { + return WH_ERROR_BADARGS; + } + + key->devCtx = (void*)((intptr_t)keyId); + return WH_ERROR_OK; +} + +int wh_Client_MlDsaGetKeyId(MlDsaKey* key, whKeyId* outId) +{ + if (key == NULL || outId == NULL) { + return WH_ERROR_BADARGS; + } + + *outId = (whKeyId)((intptr_t)key->devCtx); + return WH_ERROR_OK; +} + +int wh_Client_MlDsaImportKey(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; + } + + ret = wh_Crypto_MlDsaSerializeKeyDer(key, sizeof(buffer), buffer, + &buffer_len); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s serialize ret:%d, key:%p, max_size:%u, buffer:%p, " + "outlen:%u\n", + __func__, ret, key, (unsigned int)sizeof(buffer), buffer, + buffer_len); +#endif + if (ret == WH_ERROR_OK) { + /* Cache the key and get the keyID */ + ret = wh_Client_KeyCache(ctx, flags, label, label_len, buffer, + buffer_len, &key_id); + if ((ret == WH_ERROR_OK) && (inout_keyId != NULL)) { + *inout_keyId = key_id; + } + } + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s label:%.*s ret:%d keyid:%u\n", __func__, label_len, + label, ret, key_id); +#endif + return ret; +} + +int wh_Client_MlDsaExportKey(whClientContext* ctx, whKeyId keyId, MlDsaKey* key, + uint16_t label_len, uint8_t* label) +{ + int ret = WH_ERROR_OK; + /* buffer cannot be larger than MTU */ + 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; + } + + /* Now export the DER key from the server */ + ret = + wh_Client_KeyExport(ctx, keyId, label, label_len, buffer, &buffer_len); + if (ret == WH_ERROR_OK) { + /* Update the key structure */ + ret = wh_Crypto_MlDsaDeserializeKeyDer(buffer, buffer_len, key); + if (ret == WH_ERROR_OK) { + /* DILITHIUM-TODO: need to set securitly level. Hardcode level for + * now */ + ret = wc_MlDsaKey_SetParams(key, WC_ML_DSA_44); + } + } + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s keyid:%x key:%p ret:%d label:%.*s\n", __func__, keyId, + key, ret, (int)label_len, label); +#endif + return ret; +} + +static int _MlDsaMakeKey(whClientContext* ctx, int size, 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; + + 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; + } + + /* No other calls before here, so this is always true */ + if (ret == WH_ERROR_OK) { + /* Request Message */ + uint16_t group = WH_MESSAGE_GROUP_CRYPTO; + uint16_t action = WC_ALGO_TYPE_PK; + uint32_t type = WC_PK_TYPE_PQC_SIG_KEYGEN; + + wh_Packet_pq_mldsa_kg_req* req = &packet->pqMldsaKgReq; + 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 = type; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->level = level; + req->sz = size; + req->flags = flags; + req->keyId = key_id; + 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); + } + + ret = wh_Client_SendRequest(ctx, group, action, req_len, + (uint8_t*)packet); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s Req sent:size:%u, ret:%d\n", __func__, req->sz, + ret); +#endif + if (ret == 0) { + /* Response Message */ + wh_Packet_pq_mldsa_kg_res* res = &packet->pqMldsaKgRes; + uint8_t* key_der = (uint8_t*)(res + 1); + uint16_t res_len; + + do { + ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s Res recv:keyid:%u, len:%u, rc:%d, ret:%d\n", + __func__, res->keyId, res->len, packet->rc, ret); +#endif + + 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) { + uint16_t der_size = (uint16_t)(res->len); + /* 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( + key_der, der_size, key); +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump( + "[client] ML-DSA KeyGen export:", key_der, + der_size); +#endif + } + } + } + else { + /* Server detected a problem with generation */ + ret = packet->rc; + } + } + } + } + else { + ret = WH_ERROR_BADARGS; + } + } + return ret; +} + +int wh_Client_MlDsaMakeCacheKey(whClientContext* ctx, int size, int level, + whKeyId* inout_key_id, whNvmFlags flags, + uint16_t label_len, uint8_t* label) +{ + if (inout_key_id == NULL) { + return WH_ERROR_BADARGS; + } + + return _MlDsaMakeKey(ctx, size, level, inout_key_id, flags, label_len, + label, NULL); +} + +int wh_Client_MlDsaMakeExportKey(whClientContext* ctx, int level, MlDsaKey* key, + int size, WC_RNG* rng) +{ + if (key == NULL) { + return WH_ERROR_BADARGS; + } + + return _MlDsaMakeKey(ctx, size, level, NULL, WH_NVM_FLAGS_EPHEMERAL, 0, + NULL, key); +} + + +int wh_Client_MlDsaSign(whClientContext* ctx, const byte* in, word32 in_len, + byte* out, word32* inout_len, WC_RNG* rng, + MlDsaKey* key) +{ + int ret = 0; + whPacket* packet; + + /* Transaction state */ + whKeyId key_id; + int evict = 0; + +#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); +#endif + + if ( (ctx == NULL) || + (key == NULL) || + ((in == NULL) && (in_len > 0)) || + (out == NULL) || (inout_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, inout_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_MlDsaImportKey(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; + uint16_t action = WC_ALGO_TYPE_PK; + uint32_t type = WC_PK_TYPE_PQC_SIG_SIGN; + + wh_Packet_pq_mldsa_sign_req* req = &packet->pqMldsaSignReq; + uint8_t* req_hash = (uint8_t*)(req + 1); + uint16_t req_len = WH_PACKET_STUB_SIZE + sizeof(*req) + in_len; + 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 = type; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->options = options; + req->level = key->level; + req->keyId = key_id; + req->sz = in_len; + if ((in != NULL) && (in_len > 0)) { + memcpy(req_hash, in, in_len); + } + + /* 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. Reset evict */ + evict = 0; + + /* Response Message */ + wh_Packet_pk_ecc_sign_res* res = &packet->pkEccSignRes; + uint8_t* res_sig = (uint8_t*)(res + 1); + 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) { + uint16_t sig_len = res->sz; + /* check inoutlen and read out */ + if (inout_len != NULL) { + if (sig_len > *inout_len) { + /* Silently truncate the signature */ + sig_len = *inout_len; + } + *inout_len = sig_len; + if ((out != NULL) && (sig_len > 0)) { + memcpy(out, res_sig, sig_len); + } + } + } + else { + ret = packet->rc; + } + } + } + } + else { + /* Request length is too long */ + ret = WH_ERROR_BADARGS; + } + } + /* Evict the key manually on error */ + if (evict != 0) { + (void)wh_Client_KeyEvict(ctx, key_id); + } +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s ret:%d\n", __func__, ret); +#endif + return ret; +} + +int wh_Client_MlDsaVerify(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; + + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s ctx:%p key:%p, sig:%p sig_len:%u, msg:%p msg_len:%u " + "out_res:%p\n", + __func__, ctx, key, sig, sig_len, msg, msg_len, out_res); +#endif + + if ( (ctx == NULL) || + (key == NULL) || + ((sig == NULL) && (sig_len > 0)) || + ((msg == NULL) && (msg_len > 0)) ) { + 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_MlDsaImportKey(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; + uint16_t action = WC_ALGO_TYPE_PK; + uint16_t type = WC_PK_TYPE_PQC_SIG_VERIFY; + + wh_Packet_pq_mldsa_verify_req* req = &packet->pqMldsaVerifyReq; + uint32_t options = 0; + /* sig and hash are after the fixed size fields */ + uint8_t* req_sig = (uint8_t*)(req + 1); + uint8_t* req_hash = req_sig + sig_len; + uint16_t req_len = + WH_PACKET_STUB_SIZE + sizeof(*req) + sig_len + msg_len; + + if (req_len <= WOLFHSM_CFG_COMM_DATA_LEN) { + /* Set request packet members */ + if (evict != 0) { + options |= WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EVICT; + } + + memset(req, 0, sizeof(*req)); + req->type = type; + req->pqAlgoType = WC_PQC_SIG_TYPE_DILITHIUM; + req->options = options; + req->level = key->level; + req->keyId = key_id; + req->sigSz = sig_len; + if ((sig != NULL) && (sig_len > 0)) { + XMEMCPY(req_sig, sig, sig_len); + } + req->hashSz = msg_len; + if ((msg != NULL) && (msg_len > 0)) { + XMEMCPY(req_hash, msg, msg_len); + } + + /* write request */ + ret = wh_Client_SendRequest(ctx, group, action, req_len, + (uint8_t*)packet); + + if (ret == WH_ERROR_OK) { + /* Server will evict at this point. Reset evict */ + evict = 0; + /* Response Message */ + wh_Packet_pq_mldsa_verify_res* res = &packet->pqMldsaVerifyRes; + 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 == 0) { + if (packet->rc == 0) { + *out_res = res->res; + } + else { + ret = packet->rc; + } + } + } + } + else { + /* Request length is too long */ + ret = WH_ERROR_BADARGS; + } + } + /* Evict the key manually on error */ + if (evict != 0) { + (void)wh_Client_KeyEvict(ctx, key_id); + } +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s ret:%d\n", __func__, ret); +#endif + return ret; +} + +int wh_Client_MlDsaCheckPrivKey(whClientContext* ctx, MlDsaKey* key, + const byte* pubKey, word32 pubKeySz) +{ + /* TODO */ + return WH_ERROR_NOHANDLER; +} + + +#endif /* HAVE_DILITHIUM */ + #endif /* !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index bbc7571c..70aac9f9 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -59,6 +59,11 @@ static int _xferSha256BlockAndUpdateDigest(whClientContext* ctx, 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 */ @@ -331,6 +336,25 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) } break; #endif /* HAVE_CURVE25519 */ +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) + case WC_PK_TYPE_PQC_SIG_KEYGEN: + ret = _handlePqcSigKeyGen(ctx, info); + break; + + case WC_PK_TYPE_PQC_SIG_SIGN: + ret = _handlePqcSign(ctx, info); + break; + + case WC_PK_TYPE_PQC_SIG_VERIFY: + ret = _handlePqcVerify(ctx, info); + break; + + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = _handlePqcSigCheckPrivKey(ctx, info); + break; + +#endif /* HAVE_DILITHIUM || HAVE_FALCON */ + case WC_PK_TYPE_NONE: default: ret = CRYPTOCB_UNAVAILABLE; @@ -634,6 +658,126 @@ static int _xferSha256BlockAndUpdateDigest(whClientContext* ctx, return ret; } + +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) +static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info) +{ + 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; + + 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); + } break; +#endif /* HAVE_DILITHIUM */ + + /* Support for additional PQC algorithms should be added here */ + + default: + ret = CRYPTOCB_UNAVAILABLE; + break; + } + + return ret; +} + +static int _handlePqcSign(whClientContext* ctx, wc_CryptoInfo* info) +{ + int ret = CRYPTOCB_UNAVAILABLE; + + /* Extract info parameters */ + const byte* in = info->pk.pqc_sign.in; + 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; + + switch (type) { +#ifdef HAVE_DILITHIUM + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = wh_Client_MlDsaSign(ctx, in, in_len, out, out_len, rng, key); + break; +#endif /* HAVE_DILITHIUM */ + + /* Support for additional PQC algorithms should be added here */ + + default: + ret = CRYPTOCB_UNAVAILABLE; + break; + } + + return ret; +} + +static int _handlePqcVerify(whClientContext* ctx, wc_CryptoInfo* info) +{ + int ret = CRYPTOCB_UNAVAILABLE; + + /* Extract info parameters */ + const byte* sig = info->pk.pqc_verify.sig; + word32 sig_len = info->pk.pqc_verify.siglen; + const byte* msg = info->pk.pqc_verify.msg; + word32 msg_len = info->pk.pqc_verify.msglen; + int* res = info->pk.pqc_verify.res; + void* key = info->pk.pqc_verify.key; + int type = info->pk.pqc_verify.type; + + switch (type) { +#ifdef HAVE_DILITHIUM + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = wh_Client_MlDsaVerify(ctx, sig, sig_len, msg, msg_len, res, + key); + break; +#endif /* HAVE_DILITHIUM */ + + /* Support for additional PQC algorithms should be added here */ + + default: + ret = CRYPTOCB_UNAVAILABLE; + break; + } + + return ret; +} + +static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info) +{ + int ret = CRYPTOCB_UNAVAILABLE; + + /* Extract info parameters */ + void* key = info->pk.pqc_sig_check.key; + const byte* pubKey = info->pk.pqc_sig_check.pubKey; + word32 pubKeySz = info->pk.pqc_sig_check.pubKeySz; + int type = info->pk.pqc_sig_check.type; + + switch (type) { +#ifdef HAVE_DILITHIUM + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = wh_Client_MlDsaCheckPrivKey(ctx, key, pubKey, pubKeySz); + break; +#endif /* HAVE_DILITHIUM */ + + /* Support for additional PQC algorithms should be added here */ + + default: + ret = CRYPTOCB_UNAVAILABLE; + break; + } + + return ret; +} +#endif /* HAVE_FALCON || HAVE_DILITHIUM */ + + #ifdef WOLFHSM_CFG_DMA static int _handleSha256Dma(wc_CryptoInfo* info, void* inCtx, whPacket* packet) diff --git a/src/wh_comm.c b/src/wh_comm.c index 474dc7eb..1538c3ea 100644 --- a/src/wh_comm.c +++ b/src/wh_comm.c @@ -108,6 +108,11 @@ int wh_CommClient_SendRequest(whCommClient* context, uint16_t magic, return WH_ERROR_BADARGS; } + /* Check if the data size is within allowed limits */ + if (data_size > WOLFHSM_CFG_COMM_DATA_LEN) { + return WH_ERROR_BADARGS; + } + context->hdr->magic = magic; context->hdr->kind = wh_Translate16(magic, kind); context->hdr->seq = wh_Translate16(magic, context->seq + 1); @@ -298,6 +303,11 @@ int wh_CommServer_SendResponse(whCommServer* context, return WH_ERROR_BADARGS; } + /* Check if the data size is within allowed limits */ + if (data_size > WOLFHSM_CFG_COMM_DATA_LEN) { + return WH_ERROR_BADARGS; + } + context->hdr->magic = magic; context->hdr->kind = wh_Translate16(magic, kind); context->hdr->seq = wh_Translate16(magic, seq); diff --git a/src/wh_crypto.c b/src/wh_crypto.c index 9c1ed51a..c8e225a3 100644 --- a/src/wh_crypto.c +++ b/src/wh_crypto.c @@ -39,6 +39,7 @@ #include "wolfssl/wolfcrypt/rsa.h" #include "wolfssl/wolfcrypt/curve25519.h" #include "wolfssl/wolfcrypt/ecc.h" +#include "wolfssl/wolfcrypt/dilithium.h" #include "wolfhsm/wh_error.h" #include "wolfhsm/wh_utils.h" @@ -246,4 +247,37 @@ int wh_Crypto_Curve25519DeserializeKey(const uint8_t* derBuffer, } #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_DILITHIUM +int wh_Crypto_MlDsaSerializeKeyDer(MlDsaKey* key, uint16_t max_size, + uint8_t* buffer, uint16_t* out_size) +{ + int ret = 0; + + if ((key == NULL) || (buffer == NULL) || (out_size == NULL)) { + return WH_ERROR_BADARGS; + } + + ret = wc_Dilithium_KeyToDer(key, buffer, max_size); + + /* ASN.1 functions return the size of the DER encoded key on success */ + if (ret > 0) { + *out_size = ret; + ret = WH_ERROR_OK; + } + return ret; +} + +int wh_Crypto_MlDsaDeserializeKeyDer(const uint8_t* buffer, uint16_t size, + MlDsaKey* key) +{ + word32 idx = 0; + + if ((buffer == NULL) || (key == NULL)) { + return WH_ERROR_BADARGS; + } + + return wc_Dilithium_PrivateKeyDecode(buffer, &idx, key, size); +} +#endif /* HAVE_DILITHIUM */ + #endif /* !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 794529ff..ae7377d3 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -41,6 +41,7 @@ #include "wolfssl/wolfcrypt/aes.h" #include "wolfssl/wolfcrypt/sha256.h" #include "wolfssl/wolfcrypt/cmac.h" +#include "wolfssl/wolfcrypt/dilithium.h" #include "wolfhsm/wh_error.h" #include "wolfhsm/wh_packet.h" @@ -105,6 +106,21 @@ static int _HandleCurve25519SharedSecret(whServerContext* ctx, whPacket* packet, uint16_t *out_size); #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_DILITHIUM +/* Process a Dilithium KeyGen request packet and produce a response packet */ +static int _HandleMlDsaKeyGen(whServerContext* ctx, whPacket* packet, + uint16_t *out_size); +/* Process a Dilithium Sign request packet and produce a response packet */ +static int _HandleMlDsaSign(whServerContext* ctx, whPacket* packet, + uint16_t *out_size); +/* Process a Dilithium Verify request packet and produce a response packet */ +static int _HandleMlDsaVerify(whServerContext* ctx, whPacket* packet, + uint16_t *out_size); +/* Process a Dilithium Check PrivKey request packet and produce a response + * packet */ +static int _HandleMlDsaCheckPrivKey(whServerContext* ctx, whPacket* packet, + uint16_t *out_size); +#endif /* HAVE_DILITHIUM */ /** Public server crypto functions */ @@ -497,6 +513,70 @@ int wh_Server_CacheExportCurve25519Key(whServerContext* server, whKeyId keyId, } #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_DILITHIUM +int wh_Server_MlDsaKeyCacheImport(whServerContext* ctx, MlDsaKey* key, + whKeyId keyId, whNvmFlags flags, + uint16_t label_len, uint8_t* label) +{ + int ret = WH_ERROR_OK; + uint8_t* cacheBuf; + whNvmMetadata* cacheMeta; + uint16_t der_size; + + const uint16_t MAX_MLDSA_DER_SIZE = 5000; + + if ((ctx == NULL) || (key == NULL) || (WH_KEYID_ISERASED(keyId)) || + ((label != NULL) && (label_len > sizeof(cacheMeta->label)))) { + return WH_ERROR_BADARGS; + } + + ret = + hsmCacheFindSlotAndZero(ctx, MAX_MLDSA_DER_SIZE, &cacheBuf, &cacheMeta); + if (ret == WH_ERROR_OK) { + ret = wh_Crypto_MlDsaSerializeKeyDer(key, MAX_MLDSA_DER_SIZE, cacheBuf, + &der_size); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[server] %s keyId:%u, ret:%d\n", __func__, keyId, ret); +#endif + } + + if (ret == WH_ERROR_OK) { + cacheMeta->id = keyId; + cacheMeta->len = der_size; + cacheMeta->flags = flags; + cacheMeta->access = WH_NVM_ACCESS_ANY; + + if ((label != NULL) && (label_len > 0)) { + memcpy(cacheMeta->label, label, label_len); + } + } + + return ret; +} + +int wh_Server_MlDsaKeyCacheExport(whServerContext* ctx, whKeyId keyId, + MlDsaKey* key) +{ + uint8_t* cacheBuf; + whNvmMetadata* cacheMeta; + int ret = WH_ERROR_OK; + + if ((ctx == NULL) || (key == NULL) || (WH_KEYID_ISERASED(keyId))) { + return WH_ERROR_BADARGS; + } + + ret = hsmFreshenKey(ctx, keyId, &cacheBuf, &cacheMeta); + + if (ret == WH_ERROR_OK) { + ret = wh_Crypto_MlDsaDeserializeKeyDer(cacheBuf, cacheMeta->len, key); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[server] %s keyId:%u, ret:%d\n", __func__, keyId, ret); +#endif + } + return ret; +} +#endif /* HAVE_DILITHIUM */ + /** Request/Response Handling functions */ @@ -1317,6 +1397,7 @@ static int _HandleSha256(whServerContext* server, whPacket* packet, ret = wc_InitSha256_ex(sha256, NULL, server->crypto->devId); } else { + /* HAVE_DILITHIUM */ XMEMCPY(sha256->digest, req->resumeState.hash, WC_SHA256_DIGEST_SIZE); sha256->loLen = req->resumeState.loLen; sha256->hiLen = req->resumeState.hiLen; @@ -1348,6 +1429,250 @@ static int _HandleSha256(whServerContext* server, whPacket* packet, } #endif /* !NO_SHA256 */ +#ifdef HAVE_DILITHIUM +/* 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) { + case WC_ML_DSA_44: + case WC_ML_DSA_65: + case WC_ML_DSA_87: + ret = 1; + break; + } + + return ret; +} + +static int _HandleMlDsaKeyGen(whServerContext* ctx, whPacket* packet, + uint16_t* out_size) +{ + int ret = WH_ERROR_OK; + MlDsaKey key[1]; + wh_Packet_pq_mldsa_kg_req* req = &packet->pqMldsaKgReq; + wh_Packet_pq_mldsa_kg_res* res = &packet->pqMldsaKgRes; + + /* Request message */ + int key_size = req->sz; + whKeyId key_id = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req->keyId); + int level = req->level; + whNvmFlags flags = req->flags; + uint8_t* label = req->label; + uint16_t label_size = WH_NVM_LABEL_LEN; + + /* Response message */ + uint8_t* res_out = (uint8_t*)(res + 1); + uint16_t max_size = (uint16_t)(WOLFHSM_CFG_COMM_DATA_LEN - + (res_out - (uint8_t*)packet)); + uint16_t res_size = 0; + + /* TODO key_sz is not used. Should this instead be used as max_size? Figure + * out the relation between all three */ + (void)key_size; + + /* Check the ML-DSA security level is valid and supported */ + if (0 ==_IsMlDsaLevelSupported(level)) { + ret = WH_ERROR_BADARGS; + } + else { + /* init mldsa key */ + ret = wc_MlDsaKey_Init(key, NULL, ctx->crypto->devId); + if (ret == 0) { + /* Set the ML-DSA security level */ + ret = wc_MlDsaKey_SetParams(key, level); + if (ret == 0) { + /* generate the key */ + ret = wc_MlDsaKey_MakeKey(key, ctx->crypto->rng); + if (ret == 0) { + /* Check incoming flags */ + if (flags & WH_NVM_FLAGS_EPHEMERAL) { + /* Must serialize the key into the response message. */ + key_id = WH_KEYID_ERASED; + ret = wh_Crypto_MlDsaSerializeKeyDer( + key, max_size, res_out, &res_size); + } + else { + /* Must import the key into the cache and return keyid + */ + res_size = 0; + if (WH_KEYID_ISERASED(key_id)) { + /* Generate a new id */ + ret = hsmGetUniqueId(ctx, &key_id); +#ifdef DEBUG_CRYPTOCB + printf("[server] %s UniqueId: keyId:%u, ret:%d\n", + __func__, key_id, ret); +#endif + } + ret = wh_Server_MlDsaKeyCacheImport( + ctx, key, key_id, flags, label_size, label); +#ifdef DEBUG_CRYPTOCB + printf("[server] %s CacheImport: keyId:%u, ret:%d\n", + __func__, key_id, ret); +#endif + } + } + } + wc_MlDsaKey_Free(key); + } + + if (ret == WH_ERROR_OK) { + res->keyId = WH_KEYID_ID(key_id); + res->len = res_size; + *out_size = WH_PACKET_STUB_SIZE + sizeof(*res) + res_size; + } + } + return ret; +} + +static int _HandleMlDsaSign(whServerContext* ctx, whPacket* packet, + uint16_t *out_size) +{ + int ret; + MlDsaKey key[1]; + wh_Packet_pq_mldsa_sign_req* req = &packet->pqMldsaSignReq; + wh_Packet_pq_mldsa_sign_res* res = &packet->pqMldsaSignRes; + + /* Request message */ + byte* in = (uint8_t*)(req + 1); + whKeyId key_id = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req->keyId); + word32 in_len = req->sz; + uint32_t options = req->options; + int evict = !!(options & WH_PACKET_PQ_MLDSA_SIGN_OPTIONS_EVICT); + + /* Response message */ + byte* res_out = (uint8_t*)(res + 1); + const word32 max_len = + (word32)(WOLFHSM_CFG_COMM_DATA_LEN - (res_out - (uint8_t*)packet)); + word32 res_len; + + /* init private key */ + ret = wc_MlDsaKey_Init(key, NULL, ctx->crypto->devId); + if (ret == 0) { + /* load the private key */ + ret = wh_Server_MlDsaKeyCacheExport(ctx, key_id, key); + if (ret == WH_ERROR_OK) { + /* sign the input */ + res_len = max_len; + ret = wc_MlDsaKey_Sign(key, res_out, &res_len, in, in_len, + ctx->crypto->rng); + } + wc_MlDsaKey_Free(key); + } + if (evict != 0) { + (void)hsmEvictKey(ctx, key_id); + } + if (ret == 0) { + res->sz = res_len; + *out_size = WH_PACKET_STUB_SIZE + sizeof(*res) + res_len; + } + return ret; +} + +static int _HandleMlDsaVerify(whServerContext* ctx, whPacket* packet, + uint16_t *out_size) +{ + int ret; + MlDsaKey key[1]; + wh_Packet_pq_mldsa_verify_req* req = &packet->pqMldsaVerifyReq; + wh_Packet_pq_mldsa_verify_res* res = &packet->pqMldsaVerifyRes; + + /* Request Message */ + uint32_t options = req->options; + whKeyId key_id = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req->keyId); + uint32_t hash_len = req->hashSz; + uint32_t sig_len = req->sigSz; + byte* req_sig = (uint8_t*)(req + 1); + byte* req_hash = req_sig + sig_len; + int evict = !!(options & WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EVICT); + + /* Response message */ + int result; + + /* init public key */ + ret = wc_MlDsaKey_Init(key, NULL, ctx->crypto->devId); + if (ret == 0) { + /* load the public key */ + ret = wh_Server_MlDsaKeyCacheExport(ctx, key_id, key); + if (ret == WH_ERROR_OK) { + /* verify the signature */ + ret = wc_MlDsaKey_Verify(key, req_sig, sig_len, req_hash, hash_len, + &result); + } + wc_MlDsaKey_Free(key); + } + if (evict != 0) { + /* User requested to evict from cache, even if the call failed */ + (void)hsmEvictKey(ctx, key_id); + } + if (ret == 0) { + res->res = result; + *out_size = WH_PACKET_STUB_SIZE + sizeof(*res); + } + return ret; +} + +static int _HandleMlDsaCheckPrivKey(whServerContext* ctx, whPacket* packet, + uint16_t *out_size) +{ + return WH_ERROR_NOHANDLER; +} +#endif /* HAVE_DILITHIUM */ + +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) +static int _HandlePqcSigAlgorithm(whServerContext* ctx, 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 = _HandleMlDsaKeyGen(ctx, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_SIGN: + ret = _HandleMlDsaSign(ctx, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_VERIFY: + ret = _HandleMlDsaVerify(ctx, packet, size); + break; + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = _HandleMlDsaCheckPrivKey(ctx, packet, size); + break; + default: + ret = WH_ERROR_NOHANDLER; + break; + } + } break; +#endif /* HAVE_DILITHIUM */ + default: + ret = WH_ERROR_NOHANDLER; + break; + } + + return ret; +} +#endif + +#if defined(HAVE_KYBER) +static int _HandlePqcKemAlgorithm(whServerContext* ctx, whPacket* packet, + uint16_t* size) +{ + /* Placeholder for KEM algorithm handling */ + return WH_ERROR_NOHANDLER; +} +#endif + int wh_Server_HandleCryptoRequest(whServerContext* ctx, uint16_t action, uint8_t* data, uint16_t *inout_size, uint16_t seq) { @@ -1439,6 +1764,23 @@ int wh_Server_HandleCryptoRequest(whServerContext* ctx, break; #endif /* HAVE_CURVE25519 */ +#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 = _HandlePqcSigAlgorithm(ctx, packet, inout_size); + break; +#endif + +#if defined(HAVE_KYBER) + case WC_PK_TYPE_PQC_KEM_KEYGEN: + case WC_PK_TYPE_PQC_KEM_ENCAPS: + case WC_PK_TYPE_PQC_KEM_DECAPS: + ret = _HandlePqcKemAlgorithm(ctx, packet, inout_size); + break; +#endif + default: ret = NOT_COMPILED_IN; break; diff --git a/src/wh_transport_mem.c b/src/wh_transport_mem.c index 73314d7d..bf632639 100644 --- a/src/wh_transport_mem.c +++ b/src/wh_transport_mem.c @@ -106,6 +106,11 @@ int wh_TransportMem_SendRequest(void* c, uint16_t len, const void* data) return WH_ERROR_BADARGS; } + /* Don't send more data than we have space for in the request buffer */ + if (len > (context->req_size - sizeof(whTransportMemCsr))) { + return WH_ERROR_BADARGS; + } + /* Read current CSR's. ctx_req does not need to be invalidated */ XMEMFENCE(); XCACHEINVLD(ctx_resp); @@ -180,6 +185,11 @@ int wh_TransportMem_SendResponse(void* c, uint16_t len, const void* data) return WH_ERROR_BADARGS; } + /* Check against available data space (total size minus CSR size) */ + if (len > (context->resp_size - sizeof(whTransportMemCsr))) { + return WH_ERROR_BADARGS; + } + /* Read both CSR's. ctx_resp does not need to be invalidated */ XMEMFENCE(); XCACHEINVLD(ctx_req); diff --git a/test/Makefile b/test/Makefile index cfacbf09..ed649b59 100644 --- a/test/Makefile +++ b/test/Makefile @@ -98,7 +98,9 @@ SRC_C += \ $(WOLFSSL_DIR)/wolfcrypt/src/sha256.c \ $(WOLFSSL_DIR)/wolfcrypt/src/aes.c \ $(WOLFSSL_DIR)/wolfcrypt/src/ecc.c \ - $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c + $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/dilithium.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/sha3.c endif ifeq ($(TESTWOLFCRYPT),1) diff --git a/test/user_settings.h b/test/user_settings.h index 150dc409..e04eab8a 100644 --- a/test/user_settings.h +++ b/test/user_settings.h @@ -52,7 +52,7 @@ extern "C" { #define USE_FAST_MATH /** wolfHSM recommended */ -#define WOLFSSL_NO_MALLOC +/* #define WOLFSSL_NO_MALLOC */ #define WOLFSSL_USE_ALIGN #define WOLFSSL_IGNORE_FILE_WARN #define TFM_TIMING_RESISTANT @@ -111,6 +111,13 @@ extern "C" { /* #define WOLFSSL_SHA384 */ /* #define WOLFSSL_SHA512 */ +/* Dilithium Options */ +#define HAVE_DILITHIUM +#define WOLFSSL_WC_DILITHIUM /* use wolfCrypt implementation, not libOQS */ +#define WOLFSSL_SHA3 +#define WOLFSSL_SHAKE128 +#define WOLFSSL_SHAKE256 + /** Composite features */ #define HAVE_HKDF @@ -121,8 +128,6 @@ extern "C" { #define NO_MD4 #define NO_MD5 #define NO_DES3 -#define WOLFSSL_NO_SHAKE128 -#define WOLFSSL_NO_SHAKE256 #define NO_PWDBASED diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index afba52f2..30417d0e 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -55,10 +55,14 @@ #endif enum { - REQ_SIZE = 32, - RESP_SIZE = 64, - BUFFER_SIZE = 4096, - }; + /* Total size needs to fit: + * - Transport CSR (whTransportMemCsr) + * - Comm header (whCommHeader) + * - Max data size (WOLFHSM_CFG_COMM_DATA_LEN) + */ + BUFFER_SIZE = sizeof(whTransportMemCsr) + sizeof(whCommHeader) + + WOLFHSM_CFG_COMM_DATA_LEN, +}; #define PLAINTEXT "mytextisbigplain" @@ -1324,6 +1328,95 @@ static int whTestCrypto_Cmac(whClientContext* ctx, int devId, WC_RNG* rng) } #endif /* WOLFSSL_CMAC && !NO_AES && WOLFSSL_AES_DIRECT */ +#ifdef HAVE_DILITHIUM + +static int whTestCrypto_MlDsa(whClientContext* ctx, int devId, WC_RNG* rng) +{ + int ret = 0; + int verified = 0; + + /* Test ML DSA key generation, signing and verification */ + MlDsaKey key; + byte msg[] = "Test message for ML DSA signing"; + byte sig[DILITHIUM_ML_DSA_44_SIG_SIZE]; + word32 sigSz = sizeof(sig); + + /* Initialize key */ + ret = wc_MlDsaKey_Init(&key, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize ML DSA key: %d\n", ret); + return ret; + } + + /* Set security level to 44-bit */ + ret = wc_MlDsaKey_SetParams(&key, WC_ML_DSA_44); + if (ret != 0) { + WH_ERROR_PRINT("Failed to set ML DSA params: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + /* Generate key pair */ + ret = wc_MlDsaKey_MakeKey(&key, rng); + if (ret != 0) { + WH_ERROR_PRINT("Failed to generate ML DSA key: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + /* Get the signature size */ + ret = wc_MlDsaKey_GetSigLen(&key, (int*)&sigSz); + if (ret != 0) { + WH_ERROR_PRINT("Failed to get ML DSA signature length: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + /* Sign message */ + ret = wc_MlDsaKey_Sign(&key, sig, &sigSz, msg, sizeof(msg), rng); + if (ret != 0) { + WH_ERROR_PRINT("Failed to sign with ML DSA: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + /* Verify signature */ + ret = wc_MlDsaKey_Verify(&key, sig, sigSz, msg, sizeof(msg), &verified); + if (ret != 0) { + WH_ERROR_PRINT("Failed to verify ML DSA signature: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + if (!verified) { + WH_ERROR_PRINT("ML DSA signature verification failed\n"); + ret = -1; + } + + /* Modify signature to ensure verification fails */ + sig[0] ^= 1; + + ret = wc_MlDsaKey_Verify(&key, sig, sigSz, msg, sizeof(msg), &verified); + if (ret != 0) { + WH_ERROR_PRINT("Failed to verify modified ML DSA signature: %d\n", ret); + wc_MlDsaKey_Free(&key); + return ret; + } + + if (verified) { + WH_ERROR_PRINT("ML DSA signature verification succeeded when it should " + "have failed\n"); + ret = -1; + } + + printf("ML DSA SUCCESS\n"); + + wc_MlDsaKey_Free(&key); + return ret; +} + +#endif /* HAVE_DILITHIUM */ + int whTest_CryptoClientConfig(whClientConfig* config) { @@ -1401,6 +1494,11 @@ int whTest_CryptoClientConfig(whClientConfig* config) } #endif /* !NO_SHA256 */ +#ifdef HAVE_DILITHIUM + if (ret == 0) { + ret = whTestCrypto_MlDsa(client, WH_DEV_ID, rng); + } +#endif /* HAVE_DILITHIUM */ #ifdef WOLFHSM_CFG_TEST_VERBOSE if (ret == 0) { diff --git a/test/wolfhsm_cfg.h b/test/wolfhsm_cfg.h index 83cb5012..ae4baa5d 100644 --- a/test/wolfhsm_cfg.h +++ b/test/wolfhsm_cfg.h @@ -30,13 +30,13 @@ /* #define WOLFHSM_CFG_NO_CRYPTO */ /* #define WOLFHSM_CFG_SHE_EXTENSION */ -#define WOLFHSM_CFG_COMM_DATA_LEN 1280 +#define WOLFHSM_CFG_COMM_DATA_LEN (1280 * 4) #define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 #define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9 #define WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE 300 #define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 2 -#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 1280 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE WOLFHSM_CFG_COMM_DATA_LEN #define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8 #define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6 diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index 22bf45d1..b9423d10 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -48,6 +48,7 @@ #include "wolfssl/wolfcrypt/curve25519.h" #include "wolfssl/wolfcrypt/rsa.h" #include "wolfssl/wolfcrypt/ecc.h" +#include "wolfssl/wolfcrypt/dilithium.h" /** * @brief Generate random bytes @@ -478,5 +479,160 @@ int wh_Client_CmacSetKeyId(Cmac* key, whNvmId keyId); int wh_Client_CmacGetKeyId(Cmac* key, whNvmId* outId); #endif /* WOLFSSL_CMAC */ +#ifdef HAVE_DILITHIUM + +/** + * @brief Associates a ML-DSA key with a specific key ID. + * + * This function sets the device context of a ML-DSA key to the specified + * key ID. On the server side, this key ID is used to reference the key stored + * in the HSM + * + * @param[in] key Pointer to the ML-DSA key structure. + * @param[in] keyId Key ID to be associated with the ML-DSA key. + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_MlDsaSetKeyId(MlDsaKey* key, whKeyId keyId); + +/** + * @brief Gets the wolfHSM keyId being used by the wolfCrypt struct. + * + * This function gets the device context of a ML-DSA key that was previously + * set by either the crypto callback layer or wh_Client_MlDsaSetKeyId. + * + * @param[in] key Pointer to the ML-DSA key structure. + * @param[out] outId Pointer to the key ID to return. + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_MlDsaGetKeyId(MlDsaKey* key, whKeyId* outId); + +/** + * @brief Import a ML-DSA key to the server key cache. + * + * @param[in] ctx Pointer to the client context + * @param[in] key Pointer to the key to import + * @param[in,out] inout_keyId Pointer to key ID to use/receive + * @param[in] flags Flags to control key persistence + * @param[in] label_len Length of optional label + * @param[in] label Optional label to associate with key + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_MlDsaImportKey(whClientContext* ctx, MlDsaKey* key, + whKeyId* inout_keyId, whNvmFlags flags, + uint16_t label_len, uint8_t* label); + +/** + * @brief Export a ML-DSA key from the server. + * + * @param[in] ctx Pointer to the client context + * @param[in] keyId ID of key to export + * @param[out] key Pointer to receive exported key + * @param[in] label_len Length of optional label buffer + * @param[in] label Optional buffer to receive key label + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_MlDsaExportKey(whClientContext* ctx, whKeyId keyId, MlDsaKey* key, + uint16_t label_len, uint8_t* label); + +/** + * @brief Generate a new ML-DSA key pair and export the public key. + * + * This function generates a new ML-DSA key pair in the HSM and exports the + * public key to the client. The private key remains securely stored in the HSM. + * + * @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. + * @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); +/** + * @brief Create and cache a new ML-DSA key on the server. + * + * @param[in] ctx Pointer to the client context + * @param[in] size Size of key to generate + * @param[in] level ML-DSA security level of the key to generate + * @param[in,out] inout_key_id Pointer to key ID to use/receive + * @param[in] flags Flags to control key persistence + * @param[in] label_len Length of optional label + * @param[in] label Optional label to associate with key + * @return int Returns 0 on success or a negative error code on failure. + */ +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. + * + * This function signs a message using a ML-DSA private key stored in the + * HSM. + * + * @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 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); + +/** + * @brief Verify a ML-DSA signature. + * + * This function verifies a ML-DSA signature using the HSM. + * + * @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 original message. + * @param[in] msg_len Length of the message in bytes. + * @param[out] res Pointer to store verification result (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_MlDsaVerify(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. + * + * This function validates a ML-DSA private key against its public key using + * the HSM. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] key Pointer to the ML-DSA key structure. + * @param[in] pubKey Pointer to the public key data. + * @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_MlDsaCheckPrivKey(whClientContext* ctx, MlDsaKey* key, + const byte* pubKey, word32 pubKeySz); +#endif /* HAVE_DILITHIUM */ + #endif /* !WOLFHSM_CFG_NO_CRYPTO */ #endif /* !WOLFHSM_WH_CLIENT_CRYPTO_H_ */ diff --git a/wolfhsm/wh_crypto.h b/wolfhsm/wh_crypto.h index c3a29be5..c6419a05 100644 --- a/wolfhsm/wh_crypto.h +++ b/wolfhsm/wh_crypto.h @@ -40,6 +40,7 @@ #include "wolfssl/wolfcrypt/rsa.h" #include "wolfssl/wolfcrypt/curve25519.h" #include "wolfssl/wolfcrypt/ecc.h" +#include "wolfssl/wolfcrypt/dilithium.h" #ifndef NO_AES int wh_Crypto_SerializeAesKey(Aes* key, uint16_t max_size, @@ -84,6 +85,15 @@ int wh_Crypto_Curve25519DeserializeKey(const uint8_t* derBuffer, uint16_t derSize, curve25519_key* key); #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_DILITHIUM +/* Store a MlDsaKey to a byte sequence */ +int wh_Crypto_MlDsaSerializeKeyDer(MlDsaKey* key, uint16_t max_size, + uint8_t* buffer, uint16_t* out_size); +/* Restore a MlDsaKey from a byte sequence */ +int wh_Crypto_MlDsaDeserializeKeyDer(const uint8_t* buffer, uint16_t size, + MlDsaKey* key); +#endif /* HAVE_DILITHIUM */ + #endif /* !WOLFHSM_CFG_NO_CRYPTO */ #endif /* WOLFHSM_WH_CRYPTO_H_ */ diff --git a/wolfhsm/wh_packet.h b/wolfhsm/wh_packet.h index d7596727..b3828144 100644 --- a/wolfhsm/wh_packet.h +++ b/wolfhsm/wh_packet.h @@ -101,6 +101,29 @@ typedef struct wh_Packet_pk_any_req uint8_t WH_PAD[4]; } wh_Packet_pk_any_req; +/* Special instance of PK packets is needed for PQC algorithms */ +typedef struct wh_Packet_pk_pq_any_req { + /* enum wc_PkType. For PQ algorithms there is an additional layer of + * dispatch/algorithm identification needed since the PQ type used by crypto + * callbacks doesn't actually indicate the algorithm, only the general algorithm + * "Type" (e.g. Signature or Key Encapsulation). + * + * Valid values indicating this is a PQ PK type are: + * - WC_PK_TYPE_PQC_KEM_KEYGEN + * - WC_PK_TYPE_PQC_KEM_ENCAPS + * - WC_PK_TYPE_PQC_KEM_DECAPS + * - WC_PK_TYPE_PQC_SIG_KEYGEN + * - WC_PK_TYPE_PQC_SIG_SIGN + * - WC_PK_TYPE_PQC_SIG_VERIFY + * - WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY + */ + uint32_t type; /* enum wc_PkType */ + /* enum wc_PqcSignatureType OR enum wc_PqcKemType depending on the value of + * the type field above This field will actually indicate the specific + * algorithm (e.g. ML-DSA, Kyber, etc.) */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType or enum wc_PqcKemType */ +} wh_Packet_pk_pq_any_req; + typedef struct wh_Packet_pk_rsakg_req { uint32_t type; @@ -340,6 +363,65 @@ typedef struct wh_Packet_hash_sha256_res { uint8_t hash[32]; /* TODO WC_SHA256_DIGEST_SIZE */ } wh_Packet_hash_sha256_res; +typedef struct wh_Packet_pq_mldsa_kg_req +{ + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + uint32_t sz; + uint32_t level; + uint32_t keyId; + uint32_t flags; + uint32_t access; + uint8_t label[WH_NVM_LABEL_LEN]; +} wh_Packet_pq_mldsa_kg_req; + +typedef struct wh_Packet_pq_mldsa_kg_res +{ + uint32_t keyId; + uint32_t len; + /* uint8_t out[] */ +} wh_Packet_pq_mldsa_kg_res; + + +typedef struct wh_Packet_pq_mldsa_sign_req +{ + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + uint32_t options; +#define WH_PACKET_PQ_MLDSA_SIGN_OPTIONS_EVICT (1 << 0) + uint32_t level; + uint32_t keyId; + uint32_t sz; + /* uint8_t in[] */ +} wh_Packet_pq_mldsa_sign_req; + +typedef struct wh_Packet_pq_mldsa_sign_res +{ + uint32_t sz; + uint8_t WH_PAD[4]; + /* uint8_t out[] */ +} wh_Packet_pq_mldsa_sign_res; + +typedef struct wh_Packet_pq_mldsa_verify_req +{ + uint32_t type; /* enum wc_PkType */ + uint32_t pqAlgoType; /* enum wc_PqcSignatureType */ + uint32_t options; +#define WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EVICT (1 << 0) +#define WH_PACKET_PQ_MLDSAVERIFY_OPTIONS_EXPORTPUB (1 << 1) + uint32_t level; + uint32_t keyId; + uint32_t sigSz; + uint32_t hashSz; + uint8_t WH_PAD[4]; + /* uint8_t sig[] */ + /* uint8_t hash[] */ +} wh_Packet_pq_mldsa_verify_req; + +typedef struct wh_Packet_pq_mldsa_verify_res +{ + uint32_t res; +} wh_Packet_pq_mldsa_verify_res; /** Key Management Packets */ typedef struct wh_Packet_key_cache_req @@ -735,6 +817,16 @@ typedef struct whPacket wh_Packet_pk_curve25519kg_res pkCurve25519kgRes; wh_Packet_pk_curve25519_req pkCurve25519Req; wh_Packet_pk_curve25519_res pkCurve25519Res; + /* Special PK case: PQC algorithms need additional algorithm type */ + wh_Packet_pk_pq_any_req pkPqAnyReq; + /* ML-DSA/Dilithium */ + wh_Packet_pq_mldsa_kg_req pqMldsaKgReq; + wh_Packet_pq_mldsa_kg_res pqMldsaKgRes; + wh_Packet_pq_mldsa_sign_req pqMldsaSignReq; + wh_Packet_pq_mldsa_sign_res pqMldsaSignRes; + wh_Packet_pq_mldsa_verify_req pqMldsaVerifyReq; + wh_Packet_pq_mldsa_verify_res pqMldsaVerifyRes; + /* rng */ wh_Packet_rng_req rngReq; /* cmac */ diff --git a/wolfhsm/wh_server_crypto.h b/wolfhsm/wh_server_crypto.h index 0b5a2137..dc35934b 100644 --- a/wolfhsm/wh_server_crypto.h +++ b/wolfhsm/wh_server_crypto.h @@ -78,6 +78,16 @@ int wh_Server_CacheExportCurve25519Key(whServerContext* ctx, whKeyId keyId, curve25519_key* key); #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_DILITHIUM +/* Store a MlDsaKey into a server key cache with optional metadata */ +int wh_Server_MlDsaKeyCacheImport(whServerContext* ctx, MlDsaKey* key, + whKeyId keyId, whNvmFlags flags, + uint16_t label_len, uint8_t* label); +/* Restore a MlDsaKey from a server key cache */ +int wh_Server_MlDsaKeyCacheExport(whServerContext* ctx, whKeyId keyId, + MlDsaKey* key); +#endif /* HAVE_DILITHIUM */ + #endif /* !WOLFHSM_CFG_NO_CRYPTO */ #endif /* !WOLFHSM_WH_SERVER_CRYPTO_H_ */ From ad1ac54e75b7368335088ce7b0216a4532f12f53 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:32:47 -0700 Subject: [PATCH 2/3] fix erroneous macro guard of MLDSA inside !NO_SHA256 --- src/wh_client_cryptocb.c | 185 +++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 93 deletions(-) diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 70aac9f9..dc2a4f0b 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -658,6 +658,98 @@ static int _xferSha256BlockAndUpdateDigest(whClientContext* ctx, return ret; } +#ifdef WOLFHSM_CFG_DMA + +static int _handleSha256Dma(wc_CryptoInfo* info, void* inCtx, whPacket* packet) +{ + int ret = WH_ERROR_OK; + whClientContext* ctx = inCtx; + wc_Sha256* sha256 = info->hash.sha256; + uint16_t respSz = 0; + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + +#if WH_DMA_IS_32BIT + wh_Packet_hash_sha256_Dma32_req* req = &packet->hashSha256Dma32Req; + wh_Packet_hash_sha256_Dma32_res* resp = &packet->hashSha256Dma32Res; +#else + wh_Packet_hash_sha256_Dma64_req* req = &packet->hashSha256Dma64Req; + wh_Packet_hash_sha256_Dma64_res* resp = &packet->hashSha256Dma64Res; +#endif + + /* Caller invoked SHA Update: + * wc_CryptoCb_Sha256Hash(sha256, data, len, NULL) */ + if (info->hash.in != NULL) { + req->type = WC_HASH_TYPE_SHA256; + req->finalize = 0; + req->state.addr = (uintptr_t)sha256; + req->state.sz = sizeof(*sha256); + req->input.addr = (uintptr_t)info->hash.in; + req->input.sz = info->hash.inSz; + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] SHA256 DMA UPDATE: inAddr=%p, inSz=%u\n", + info->hash.in, info->hash.inSz); +#endif + ret = wh_Client_SendRequest(ctx, group, WC_ALGO_TYPE_HASH, + WH_PACKET_STUB_SIZE + sizeof(*req), + (uint8_t*)packet); + if (ret == WH_ERROR_OK) { + do { + ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + } + + if (ret == WH_ERROR_OK) { + if (packet->rc != WH_ERROR_OK) { + ret = packet->rc; + } + /* Nothing to do on success, as server will have updated the context + * in client memory */ + } + } + + /* Caller invoked SHA finalize: + * wc_CryptoCb_Sha256Hash(sha256, NULL, 0, * hash) */ + if ((ret == WH_ERROR_OK) && (info->hash.digest != NULL)) { + /* Packet will have been trashed, so re-populate all fields */ + req->type = WC_HASH_TYPE_SHA256; + req->finalize = 1; + req->state.addr = (uintptr_t)sha256; + req->state.sz = sizeof(*sha256); + req->output.addr = (uintptr_t)info->hash.digest; + req->output.sz = WC_SHA256_DIGEST_SIZE; /* not needed, but YOLO */ + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] SHA256 DMA FINAL: outAddr=%p\n", info->hash.digest); +#endif + /* send the request to the server */ + ret = wh_Client_SendRequest(ctx, group, WC_ALGO_TYPE_HASH, + WH_PACKET_STUB_SIZE + sizeof(*req), + (uint8_t*)packet); + if (ret == WH_ERROR_OK) { + do { + ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, + (uint8_t*)packet); + } while (ret == WH_ERROR_NOTREADY); + } + + /* Copy out the final hash value */ + if (ret == WH_ERROR_OK) { + if (packet->rc != WH_ERROR_OK) { + ret = packet->rc; + (void)resp; + } + /* Nothing to do on success, as server will have updated the output + * hash in client memory */ + } + } + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ +#endif /* ! NO_SHA256 */ + #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) static int _handlePqcSigKeyGen(whClientContext* ctx, wc_CryptoInfo* info) @@ -778,99 +870,6 @@ static int _handlePqcSigCheckPrivKey(whClientContext* ctx, wc_CryptoInfo* info) #endif /* HAVE_FALCON || HAVE_DILITHIUM */ -#ifdef WOLFHSM_CFG_DMA - -static int _handleSha256Dma(wc_CryptoInfo* info, void* inCtx, whPacket* packet) -{ - int ret = WH_ERROR_OK; - whClientContext* ctx = inCtx; - wc_Sha256* sha256 = info->hash.sha256; - uint16_t respSz = 0; - uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; - -#if WH_DMA_IS_32BIT - wh_Packet_hash_sha256_Dma32_req* req = &packet->hashSha256Dma32Req; - wh_Packet_hash_sha256_Dma32_res* resp = &packet->hashSha256Dma32Res; -#else - wh_Packet_hash_sha256_Dma64_req* req = &packet->hashSha256Dma64Req; - wh_Packet_hash_sha256_Dma64_res* resp = &packet->hashSha256Dma64Res; -#endif - - /* Caller invoked SHA Update: - * wc_CryptoCb_Sha256Hash(sha256, data, len, NULL) */ - if (info->hash.in != NULL) { - req->type = WC_HASH_TYPE_SHA256; - req->finalize = 0; - req->state.addr = (uintptr_t)sha256; - req->state.sz = sizeof(*sha256); - req->input.addr = (uintptr_t)info->hash.in; - req->input.sz = info->hash.inSz; - -#ifdef DEBUG_CRYPTOCB_VERBOSE - printf("[client] SHA256 DMA UPDATE: inAddr=%p, inSz=%u\n", - info->hash.in, info->hash.inSz); -#endif - ret = wh_Client_SendRequest(ctx, group, WC_ALGO_TYPE_HASH, - WH_PACKET_STUB_SIZE + sizeof(*req), - (uint8_t*)packet); - if (ret == WH_ERROR_OK) { - do { - ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, - (uint8_t*)packet); - } while (ret == WH_ERROR_NOTREADY); - } - - if (ret == WH_ERROR_OK) { - if (packet->rc != WH_ERROR_OK) { - ret = packet->rc; - } - /* Nothing to do on success, as server will have updated the context - * in client memory */ - } - } - - /* Caller invoked SHA finalize: - * wc_CryptoCb_Sha256Hash(sha256, NULL, 0, * hash) */ - if ((ret == WH_ERROR_OK) && (info->hash.digest != NULL)) { - /* Packet will have been trashed, so re-populate all fields */ - req->type = WC_HASH_TYPE_SHA256; - req->finalize = 1; - req->state.addr = (uintptr_t)sha256; - req->state.sz = sizeof(*sha256); - req->output.addr = (uintptr_t)info->hash.digest; - req->output.sz = WC_SHA256_DIGEST_SIZE; /* not needed, but YOLO */ - -#ifdef DEBUG_CRYPTOCB_VERBOSE - printf("[client] SHA256 DMA FINAL: outAddr=%p\n", info->hash.digest); -#endif - /* send the request to the server */ - ret = wh_Client_SendRequest(ctx, group, WC_ALGO_TYPE_HASH, - WH_PACKET_STUB_SIZE + sizeof(*req), - (uint8_t*)packet); - if (ret == WH_ERROR_OK) { - do { - ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, - (uint8_t*)packet); - } while (ret == WH_ERROR_NOTREADY); - } - - /* Copy out the final hash value */ - if (ret == WH_ERROR_OK) { - if (packet->rc != WH_ERROR_OK) { - ret = packet->rc; - (void)resp; - } - /* Nothing to do on success, as server will have updated the output - * hash in client memory */ - } - } - - return ret; -} -#endif /* WOLFHSM_CFG_DMA */ -#endif /* ! NO_SHA256 */ - - #ifdef WOLFHSM_CFG_DMA int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) { From c975fa205e1c98ee52e0fc3484d878123985ce17 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:35:34 -0700 Subject: [PATCH 3/3] Removed erroneous MLDSA setParams after deserialization --- src/wh_client_crypto.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index 81196185..faca7045 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -2155,11 +2155,6 @@ int wh_Client_MlDsaExportKey(whClientContext* ctx, whKeyId keyId, MlDsaKey* key, if (ret == WH_ERROR_OK) { /* Update the key structure */ ret = wh_Crypto_MlDsaDeserializeKeyDer(buffer, buffer_len, key); - if (ret == WH_ERROR_OK) { - /* DILITHIUM-TODO: need to set securitly level. Hardcode level for - * now */ - ret = wc_MlDsaKey_SetParams(key, WC_ML_DSA_44); - } } #ifdef DEBUG_CRYPTOCB_VERBOSE