From f99717aedfba5300b78654716bde094239436077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Mon, 16 Feb 2026 13:22:21 +0100 Subject: [PATCH] Support for ML-DSA in PKCS#11 Offload ML-DSA operations onto a PKCS#11 token via the cryptoCb interface: * Key generation * Signature generation * Signature verification * Key import Both the pure and pre-hash versions are supported. Not yet supported are the pre-hash versions that also offload the hashing onto the token. This also fixes casting errors introduced in #9780 due to usage of uintptr_t, which is unavailable without including stdint.h on some platforms. Use the wolfssl own wc_ptr_t instead. --- .wolfssl_known_macro_extras | 1 + wolfcrypt/src/aes.c | 2 +- wolfcrypt/src/cryptocb.c | 5 +- wolfcrypt/src/dilithium.c | 8 + wolfcrypt/src/ecc.c | 2 +- wolfcrypt/src/sha.c | 2 +- wolfcrypt/src/sha256.c | 4 +- wolfcrypt/src/sha3.c | 2 +- wolfcrypt/src/sha512.c | 4 +- wolfcrypt/src/wc_pkcs11.c | 1361 +++++++++++++++++++++++++++++---- wolfssl/wolfcrypt/cryptocb.h | 4 +- wolfssl/wolfcrypt/dilithium.h | 15 +- wolfssl/wolfcrypt/pkcs11.h | 37 + wolfssl/wolfcrypt/wc_pkcs11.h | 1 + 14 files changed, 1281 insertions(+), 167 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 24552e1037..e736bec35c 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -418,6 +418,7 @@ NO_PKCS11_ECC NO_PKCS11_ECDH NO_PKCS11_EC_KEYGEN NO_PKCS11_HMAC +NO_PKCS11_MLDSA NO_PKCS11_RNG NO_PKCS11_RSA NO_PKCS11_RSA_PKCS diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 7c4b3277ce..63e5080d35 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -13601,7 +13601,7 @@ void wc_AesFree(Aes* aes) #endif { int ret = wc_CryptoCb_Free(aes->devId, WC_ALGO_TYPE_CIPHER, - WC_CIPHER_AES, aes); + WC_CIPHER_AES, 0, aes); #ifdef WOLF_CRYPTO_CB_AES_SETKEY aes->devCtx = NULL; /* Clear device context handle */ #endif diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index f9df067264..3066c819dc 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -2120,11 +2120,13 @@ int wc_CryptoCb_Copy(int devId, int algo, int type, void* src, void* dst) * WC_ALGO_TYPE_CIPHER, etc * type: Specific type - for HASH: enum wc_HashType, for CIPHER: * enum wc_CipherType + * subType: Specific subtype - for PQC: enum wc_PqcKemType, + * enum wc_PqcSignatureType * obj: Pointer to object structure to free * Returns: 0 on success, negative on error, CRYPTOCB_UNAVAILABLE if not * handled */ -int wc_CryptoCb_Free(int devId, int algo, int type, void* obj) +int wc_CryptoCb_Free(int devId, int algo, int type, int subType, void* obj) { int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; @@ -2137,6 +2139,7 @@ int wc_CryptoCb_Free(int devId, int algo, int type, void* obj) cryptoInfo.algo_type = WC_ALGO_TYPE_FREE; cryptoInfo.free.algo = algo; cryptoInfo.free.type = type; + cryptoInfo.free.subType = subType; cryptoInfo.free.obj = obj; ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index dfd9ac4f6c..afa088f2a8 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -10834,6 +10834,14 @@ int wc_dilithium_get_level(dilithium_key* key, byte* level) void wc_dilithium_free(dilithium_key* key) { if (key != NULL) { +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) + if (key->devId != INVALID_DEVID) { + wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK, + WC_PK_TYPE_PQC_SIG_KEYGEN, + WC_PQC_SIG_TYPE_DILITHIUM, + (void*)key); + } +#endif #ifdef WOLFSSL_WC_DILITHIUM #ifndef WC_DILITHIUM_FIXED_ARRAY /* Dispose of cached items. */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index d7acd0bdaf..5af9891b08 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -7894,7 +7894,7 @@ int wc_ecc_free(ecc_key* key) #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) if (key->devId != INVALID_DEVID) { wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK, - WC_PK_TYPE_EC_KEYGEN, key); + WC_PK_TYPE_EC_KEYGEN, 0, key); } #endif diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 590a06104d..c8f1ab927c 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1062,7 +1062,7 @@ void wc_ShaFree(wc_Sha* sha) #endif { ret = wc_CryptoCb_Free(sha->devId, WC_ALGO_TYPE_HASH, - WC_HASH_TYPE_SHA, (void*)sha); + WC_HASH_TYPE_SHA, 0, (void*)sha); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 745eb13673..9fc6ba573e 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -2305,7 +2305,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, #endif { ret = wc_CryptoCb_Free(sha224->devId, WC_ALGO_TYPE_HASH, - WC_HASH_TYPE_SHA224, (void*)sha224); + WC_HASH_TYPE_SHA224, 0, (void*)sha224); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ @@ -2382,7 +2382,7 @@ void wc_Sha256Free(wc_Sha256* sha256) #endif { ret = wc_CryptoCb_Free(sha256->devId, WC_ALGO_TYPE_HASH, - WC_HASH_TYPE_SHA256, (void*)sha256); + WC_HASH_TYPE_SHA256, 0, (void*)sha256); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 8b02cffb49..4cfe64ae38 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -1252,7 +1252,7 @@ static void wc_Sha3Free(wc_Sha3* sha3) #endif { ret = wc_CryptoCb_Free(sha3->devId, WC_ALGO_TYPE_HASH, - sha3->hashType, (void*)sha3); + sha3->hashType, 0, (void*)sha3); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index a50e2ebd6a..68db4ad012 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -1635,7 +1635,7 @@ void wc_Sha512Free(wc_Sha512* sha512) #endif { ret = wc_CryptoCb_Free(sha512->devId, WC_ALGO_TYPE_HASH, - WC_HASH_TYPE_SHA512, (void*)sha512); + WC_HASH_TYPE_SHA512, 0, (void*)sha512); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ @@ -2117,7 +2117,7 @@ void wc_Sha384Free(wc_Sha384* sha384) #endif { ret = wc_CryptoCb_Free(sha384->devId, WC_ALGO_TYPE_HASH, - WC_HASH_TYPE_SHA384, (void*)sha384); + WC_HASH_TYPE_SHA384, 0, (void*)sha384); /* If they want the standard free, they can call it themselves */ /* via their callback setting devId to INVALID_DEVID */ /* otherwise assume the callback handled it */ diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 37a741b595..9632479b73 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -66,6 +66,9 @@ #if defined(NO_PKCS11_RNG) && !defined(WC_NO_RNG) #define WC_NO_RNG #endif +#if defined(NO_PKCS11_MLDSA) && defined(HAVE_DILITHIUM) + #undef HAVE_DILITHIUM +#endif #if defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH) @@ -80,13 +83,17 @@ static CK_BBOOL ckTrue = CK_TRUE; #ifndef NO_RSA /* Pointer to RSA key type required for templates. */ -static CK_KEY_TYPE rsaKeyType = CKK_RSA; +static CK_KEY_TYPE rsaKeyType = CKK_RSA; #endif #ifdef HAVE_ECC /* Pointer to EC key type required for templates. */ -static CK_KEY_TYPE ecKeyType = CKK_EC; +static CK_KEY_TYPE ecKeyType = CKK_EC; +#endif +#if defined(HAVE_DILITHIUM) +/* Pointer to ML-DSA key type required for templates. */ +static CK_KEY_TYPE mldsaKeyType = CKK_ML_DSA; #endif -#if !defined(NO_RSA) || defined(HAVE_ECC) +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_DILITHIUM) /* Pointer to public key class required for templates. */ static CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY; /* Pointer to private key class required for templates. */ @@ -292,6 +299,9 @@ static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ, case CKK_SHA224_HMAC: XSNPRINTF(line, sizeof(line), "%25s: SHA224_HMAC", type); break; + case CKK_ML_DSA: + XSNPRINTF(line, sizeof(line), "%25s: ML_DSA", type); + break; default: XSNPRINTF(line, sizeof(line), "%25s: UNKNOWN (%08lx)", type, keyType); @@ -1536,8 +1546,181 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey, } #endif +#ifdef HAVE_DILITHIUM +/** + * Create a PKCS#11 object containing the ML-DSA public key data. + * @param handle [out] Handle to public key object. + * @param session [in] Session object. + * @param key [in] ML-DSA key. + * @param mechInfo [in] Pointer to a filled MECHANISM_INFO object. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11CreateMldsaPublicKey(CK_OBJECT_HANDLE* handle, + Pkcs11Session* session, + MlDsaKey* key, + CK_MECHANISM_INFO_PTR mechInfo) +{ + int ret = 0; + CK_RV rv; + CK_ULONG publicKeyLen = 0; + CK_ML_DSA_PARAMETER_SET_TYPE param_set = 0; + /* Empty entries for optional label/ID. */ + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, NULL, 0 }, + { CKA_PARAMETER_SET, ¶m_set, sizeof(param_set) }, + { 0, NULL, 0 }, + { 0, NULL, 0 }, + }; + /* Mandatory entries + 2 optional. */ + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate) - 2; + + if (!key->pubKeySet) { + ret = BAD_FUNC_ARG; + } + + if (key->labelLen > 0) { + keyTemplate[keyTmplCnt].type = CKA_LABEL; + keyTemplate[keyTmplCnt].pValue = key->label; + keyTemplate[keyTmplCnt].ulValueLen = key->labelLen; + keyTmplCnt++; + } + if (key->idLen > 0) { + keyTemplate[keyTmplCnt].type = CKA_ID; + keyTemplate[keyTmplCnt].pValue = key->id; + keyTemplate[keyTmplCnt].ulValueLen = key->idLen; + keyTmplCnt++; + } + + if ((key->level == WC_ML_DSA_44) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL2_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL2_PUB_KEY_SIZE)) { + publicKeyLen = ML_DSA_LEVEL2_PUB_KEY_SIZE; + param_set = CKP_ML_DSA_44; + } + else if ((key->level == WC_ML_DSA_65) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL3_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL3_PUB_KEY_SIZE)) { + publicKeyLen = ML_DSA_LEVEL3_PUB_KEY_SIZE; + param_set = CKP_ML_DSA_65; + } + else if ((key->level == WC_ML_DSA_87) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL5_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL5_PUB_KEY_SIZE)) { + publicKeyLen = ML_DSA_LEVEL5_PUB_KEY_SIZE; + param_set = CKP_ML_DSA_87; + } + else { + ret = WC_KEY_SIZE_E; + } + + if (ret == 0) { + keyTemplate[3].pValue = (byte*) key->p; + keyTemplate[3].ulValueLen = publicKeyLen; + + PKCS11_DUMP_TEMPLATE("ML-DSA Public Key", keyTemplate, keyTmplCnt); + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, handle); + PKCS11_RV("C_CreateObject", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + return ret; +} + +/** +* Create a PKCS#11 object containing the ML-DSA private key data. +* +* @param handle [out] Handle to private key object. +* @param session [in] Session object. +* @param key [in] ML-DSA key. +* @param mechInfo [in] Pointer to a filled MECHANISM_INFO object. +* @return WC_HW_E when a PKCS#11 library call fails. +* @return 0 on success. +*/ +static int Pkcs11CreateMldsaPrivateKey(CK_OBJECT_HANDLE* privateKey, + Pkcs11Session* session, + MlDsaKey* key, + CK_MECHANISM_INFO_PTR mechInfo) +{ + int ret = 0; + CK_RV rv; + CK_ULONG privateKeyLen = 0; + CK_ML_DSA_PARAMETER_SET_TYPE param_set = 0; + /* Empty entries for optional label/ID. */ + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, NULL, 0 }, + { CKA_PARAMETER_SET, ¶m_set, sizeof(param_set) }, + { 0, NULL, 0 }, + { 0, NULL, 0 } + }; + /* Mandatory entries + 2 optional. */ + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate) - 2; + + if (key->labelLen > 0) { + keyTemplate[keyTmplCnt].type = CKA_LABEL; + keyTemplate[keyTmplCnt].pValue = key->label; + keyTemplate[keyTmplCnt].ulValueLen = key->labelLen; + keyTmplCnt++; + } + if (key->idLen > 0) { + keyTemplate[keyTmplCnt].type = CKA_ID; + keyTemplate[keyTmplCnt].pValue = key->id; + keyTemplate[keyTmplCnt].ulValueLen = key->idLen; + keyTmplCnt++; + } + + if ((key->level == WC_ML_DSA_44) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL2_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL2_PUB_KEY_SIZE)) { + privateKeyLen = ML_DSA_LEVEL2_KEY_SIZE; + param_set = CKP_ML_DSA_44; + } + else if ((key->level == WC_ML_DSA_65) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL3_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL3_PUB_KEY_SIZE)) { + privateKeyLen = ML_DSA_LEVEL3_KEY_SIZE; + param_set = CKP_ML_DSA_65; + } + else if ((key->level == WC_ML_DSA_87) && + (mechInfo->ulMinKeySize <= ML_DSA_LEVEL5_PUB_KEY_SIZE) && + (mechInfo->ulMaxKeySize >= ML_DSA_LEVEL5_PUB_KEY_SIZE)) { + privateKeyLen = ML_DSA_LEVEL5_KEY_SIZE; + param_set = CKP_ML_DSA_87; + } + else { + ret = WC_KEY_SIZE_E; + } + + if (ret == 0) { + keyTemplate[3].pValue = (byte*) key->k; + keyTemplate[3].ulValueLen = privateKeyLen; + + PKCS11_DUMP_TEMPLATE("ML-DSA Private Key", keyTemplate, keyTmplCnt); + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, privateKey); + PKCS11_RV("C_CreateObject", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + return ret; +} +#endif /* HAVE_DILITHIUM */ + #if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ - (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \ + !defined(NO_HMAC) || defined(HAVE_DILITHIUM) /** * Check if mechanism is available in session on token. * @@ -1761,6 +1944,13 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) /* Store public key for validation with cert. */ ret2 = Pkcs11CreateEccPublicKey(&pubKey, &session, eccKey, CKA_VERIFY); + if (ret2 != 0) { + /* Delete the private key if the public key + * creation failed to avoid leaving an orphaned + * private key on the token. */ + session.func->C_DestroyObject(session.handle, + privKey); + } } } /* OK for this to fail if set for ECDH. */ @@ -1772,6 +1962,40 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) break; } #endif + #if defined(HAVE_DILITHIUM) + case PKCS11_KEY_TYPE_MLDSA: { + MlDsaKey* mldsaKey = (MlDsaKey*) key; + CK_MECHANISM_INFO mechInfo; + + ret = Pkcs11MechAvail(&session, CKM_ML_DSA, &mechInfo); + if (ret == 0 && mldsaKey->prvKeySet) { + ret = Pkcs11CreateMldsaPrivateKey(&privKey, + &session, + mldsaKey, + &mechInfo); + } + if (ret == 0 && mldsaKey->pubKeySet) { + CK_OBJECT_HANDLE pubKey = NULL_PTR; + /* Store public key for validation with cert. */ + ret = Pkcs11CreateMldsaPublicKey(&pubKey, + &session, + mldsaKey, + &mechInfo); + if (ret != 0) { + /* Delete the private key if the public key creation + * failed to avoid leaving an orphaned private key + * on the token. */ + session.func->C_DestroyObject(session.handle, privKey); + } + } + #ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY + if (ret == 0 && clear) { + ForceZero(mldsaKey->k, sizeof(mldsaKey->k)); + } + #endif + break; + } + #endif /* HAVE_DILITHIUM*/ default: ret = NOT_COMPILED_IN; break; @@ -2924,7 +3148,7 @@ static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) if (pubKey != NULL_PTR) session->func->C_DestroyObject(session->handle, pubKey); if (ret == 0 && privKey != NULL_PTR) { - key->devCtx = (void*)(uintptr_t)privKey; + key->devCtx = (void*)(wc_ptr_t)privKey; } else if (ret != 0 && privKey != NULL_PTR) { session->func->C_DestroyObject(session->handle, privKey); @@ -3025,7 +3249,7 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) WOLFSSL_MSG("PKCS#11: EC Key Derivation Operation"); if (info->pk.ecdh.private_key->devCtx != NULL) { - privateKey = (CK_OBJECT_HANDLE)(uintptr_t) + privateKey = (CK_OBJECT_HANDLE)(wc_ptr_t) info->pk.ecdh.private_key->devCtx; } else if ((sessionKey = !mp_iszero( @@ -3326,7 +3550,7 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) WOLFSSL_MSG("PKCS#11: EC Signing Operation"); if (info->pk.eccsign.key->devCtx != NULL) { - privateKey = (CK_OBJECT_HANDLE)(uintptr_t) + privateKey = (CK_OBJECT_HANDLE)(wc_ptr_t) info->pk.eccsign.key->devCtx; } else if ((sessionKey = !mp_iszero( @@ -3731,184 +3955,966 @@ static int Pkcs11EccCheckPrivKey(Pkcs11Session* session, wc_CryptoInfo* info) return ret; } -#endif -#if !defined(NO_AES) && defined(HAVE_AESGCM) /** - * Performs the AES-GCM encryption operation. + * Deletes the ECC private key. * * @param [in] session Session object. - * @param [in] info Cryptographic operation data. - * @return WC_HW_E when a PKCS#11 library call fails. - * @return MEMORY_E when a memory allocation fails. + * @param [in] key ECC key. * @return 0 on success. */ -static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +static int Pkcs11EccDeletePrivKey(Pkcs11Session* session, ecc_key* key) { - int ret = 0; - CK_RV rv; - Aes* aes = info->cipher.aesgcm_enc.aes; - CK_GCM_PARAMS params; - CK_MECHANISM_INFO mechInfo; - CK_OBJECT_HANDLE key = NULL_PTR; - CK_MECHANISM mech; - CK_ULONG outLen; + CK_OBJECT_HANDLE privateKey; - /* Check operation is supported. */ - ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo); - if (ret == 0 && (mechInfo.flags & CKF_ENCRYPT) == 0) { - ret = NOT_COMPILED_IN; - } - if (ret == 0) { - WOLFSSL_MSG("PKCS#11: AES-GCM Encryption Operation"); + if (key != NULL && key->devCtx != NULL) { + privateKey = (CK_OBJECT_HANDLE)(wc_ptr_t)key->devCtx; - /* Create a private key object or find by label or id. */ - if (aes->idLen == 0 && aes->labelLen == 0) { - ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, - (unsigned char*)aes->devKey, - aes->keylen, NULL, 0, NULL, 0, - CKA_ENCRYPT); - } - else if (aes->labelLen != 0) { - ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, CKK_AES, session, - aes->label, aes->labelLen); - } - else { - ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, - aes->id, aes->idLen); - } + session->func->C_DestroyObject(session->handle, privateKey); + + key->devCtx = NULL; } - if (ret == 0) { - params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_enc.iv; - params.ulIvLen = info->cipher.aesgcm_enc.ivSz; - params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_enc.authIn; - params.ulAADLen = info->cipher.aesgcm_enc.authInSz; - params.ulTagBits = info->cipher.aesgcm_enc.authTagSz * 8; + return 0; +} +#endif - mech.mechanism = CKM_AES_GCM; - mech.ulParameterLen = sizeof(params); - mech.pParameter = ¶ms; +#if defined(HAVE_DILITHIUM) +/** + * Find the PKCS#11 object containing the ML-DSA public or private key data. + * + * @param handle [out] Handle to key object. + * @param keyClass [in] Public or private key class. + * @param session [in] Session object. + * @param key [in] ML-DSA key. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11FindMldsaKey(CK_OBJECT_HANDLE* handle, + CK_OBJECT_CLASS keyClass, + Pkcs11Session* session, + MlDsaKey* key) +{ + int ret = 0; + CK_ULONG count = 0; + CK_ML_DSA_PARAMETER_SET_TYPE param_set = 0; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_PARAMETER_SET, ¶m_set, sizeof(param_set) }, + }; + CK_ULONG attrCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); - rv = session->func->C_EncryptInit(session->handle, &mech, key); - PKCS11_RV("C_EncryptInit", rv); - if (rv != CKR_OK) { - ret = WC_HW_E; - } + if (key->level == WC_ML_DSA_44) { + param_set = CKP_ML_DSA_44; } - if (ret == 0) { - outLen = info->cipher.aesgcm_enc.sz; - rv = session->func->C_EncryptUpdate(session->handle, - (CK_BYTE_PTR)info->cipher.aesgcm_enc.in, - info->cipher.aesgcm_enc.sz, - info->cipher.aesgcm_enc.out, - &outLen); - PKCS11_RV("C_EncryptUpdate", rv); - if (rv != CKR_OK) { - ret = WC_HW_E; - } + else if (key->level == WC_ML_DSA_65) { + param_set = CKP_ML_DSA_65; } - if (ret == 0) { - /* Authentication tag comes out in final block. */ - outLen = info->cipher.aesgcm_enc.authTagSz; - rv = session->func->C_EncryptFinal(session->handle, - info->cipher.aesgcm_enc.authTag, - &outLen); - PKCS11_RV("C_EncryptFinal", rv); - if (rv != CKR_OK) { - ret = WC_HW_E; - } + else if (key->level == WC_ML_DSA_87) { + param_set = CKP_ML_DSA_87; + } + else { + ret = NOT_COMPILED_IN; } - if (aes->idLen == 0 && aes->labelLen == 0 && key != NULL_PTR) - session->func->C_DestroyObject(session->handle, key); + if (ret == 0) { + ret = Pkcs11FindKeyByTemplate(handle, session, keyTemplate, + attrCnt, &count); + } + if (ret == 0 && count == 0) { + ret = WC_HW_E; + } return ret; } /** - * Performs the AES-GCM decryption operation. + * Gets the public key data from the PKCS#11 object and puts into the ML-DSA + * key. * - * @param [in] session Session object. - * @param [in] info Cryptographic operation data. + * @param key [in] ML-DSA key. + * @param session [in] Session object. + * @param keyHandle [in] ML-DSA public key PKCS#11 object handle. * @return WC_HW_E when a PKCS#11 library call fails. * @return MEMORY_E when a memory allocation fails. * @return 0 on success. */ -static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +static int Pkcs11GetMldsaPublicKey(MlDsaKey* key, + Pkcs11Session* session, + CK_OBJECT_HANDLE keyHandle) { - int ret = 0; - CK_RV rv; - Aes* aes = info->cipher.aesgcm_enc.aes; - CK_GCM_PARAMS params; - CK_MECHANISM_INFO mechInfo; - CK_OBJECT_HANDLE key = NULL_PTR; - CK_MECHANISM mech; - CK_ULONG outLen; - word32 len; + int ret = 0; + CK_ULONG pubKeySize; + unsigned char* pubKey = NULL; + CK_ATTRIBUTE tmpl[] = { + { CKA_VALUE, NULL, 0 } + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + CK_RV rv; - /* Check operation is supported. */ - ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo); - if (ret == 0 && (mechInfo.flags & CKF_DECRYPT) == 0) { - ret = NOT_COMPILED_IN; + PKCS11_DUMP_TEMPLATE("Get ML-DSA Public Key Length", tmpl, tmplCnt); + rv = session->func->C_GetAttributeValue(session->handle, keyHandle, + tmpl, tmplCnt); + PKCS11_RV("C_GetAttributeValue", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; } - if (ret == 0) { - WOLFSSL_MSG("PKCS#11: AES-GCM Decryption Operation"); + PKCS11_DUMP_TEMPLATE("ML-DSA Public Key Length", tmpl, tmplCnt); - /* Create a private key object or find by id. */ - if (aes->idLen == 0 && aes->labelLen == 0) { - ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, - (unsigned char*)aes->devKey, - aes->keylen, NULL, 0, NULL, 0, - CKA_DECRYPT); - } - else if (aes->labelLen != 0) { - ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, CKK_AES, session, - aes->label, aes->labelLen); - } - else { - ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, - aes->id, aes->idLen); - } + if (ret == 0) { + pubKeySize = tmpl[0].ulValueLen; + pubKey = (unsigned char*)XMALLOC(pubKeySize, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) + ret = MEMORY_E; } - if (ret == 0) { - params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_dec.iv; - params.ulIvLen = info->cipher.aesgcm_dec.ivSz; - params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_dec.authIn; - params.ulAADLen = info->cipher.aesgcm_dec.authInSz; - params.ulTagBits = info->cipher.aesgcm_dec.authTagSz * 8; - - mech.mechanism = CKM_AES_GCM; - mech.ulParameterLen = sizeof(params); - mech.pParameter = ¶ms; + tmpl[0].pValue = pubKey; - rv = session->func->C_DecryptInit(session->handle, &mech, key); - PKCS11_RV("C_DecryptInit", rv); + PKCS11_DUMP_TEMPLATE("Get ML-DSA Public Key", tmpl, tmplCnt); + rv = session->func->C_GetAttributeValue(session->handle, keyHandle, + tmpl, tmplCnt); + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } + PKCS11_DUMP_TEMPLATE("ML-DSA Public Key", tmpl, tmplCnt); } if (ret == 0) { - outLen = len = info->cipher.aesgcm_dec.sz; - rv = session->func->C_DecryptUpdate(session->handle, - (CK_BYTE_PTR)info->cipher.aesgcm_dec.in, - info->cipher.aesgcm_dec.sz, - info->cipher.aesgcm_dec.out, - &outLen); - PKCS11_RV("C_DecryptUpdate", rv); - if (rv != CKR_OK) { - ret = WC_HW_E; - } + if (pubKeySize == ML_DSA_LEVEL2_PUB_KEY_SIZE) + wc_MlDsaKey_SetParams(key, WC_ML_DSA_44); + else if (pubKeySize == ML_DSA_LEVEL3_PUB_KEY_SIZE) + wc_MlDsaKey_SetParams(key, WC_ML_DSA_65); + else if (pubKeySize == ML_DSA_LEVEL5_PUB_KEY_SIZE) + wc_MlDsaKey_SetParams(key, WC_ML_DSA_87); + else + ret = WC_KEY_SIZE_E; } - if (ret == 0) { - /* Put authentication tag in as encrypted data. */ - outLen = len = (len + info->cipher.aesgcm_dec.authTagSz - - (word32)outLen); - rv = session->func->C_DecryptUpdate(session->handle, - (CK_BYTE_PTR)info->cipher.aesgcm_dec.authTag, - info->cipher.aesgcm_dec.authTagSz, - info->cipher.aesgcm_dec.out, + if (ret == 0) + ret = wc_MlDsaKey_ImportPubRaw(key, pubKey, pubKeySize); + + if (pubKey != NULL) + XFREE(pubKey, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/** + * Convert the wolfCrypt hash type to a digest mechanism. + * + * @param hashType [in] Hash type. + * @param hashMech [out] Pointer to digest mechanism. + + * @return BAD_FUNC_ARG when the hash type is not recognized. + * 0 on success. + */ +static int Pkcs11GetMldsaPreHash(int hashType, + CK_MECHANISM_TYPE_PTR hashMech) +{ + int ret = 0; + + if (hashMech == NULL) { + return BAD_FUNC_ARG; + } + + switch (hashType) { + case WC_HASH_TYPE_SHA256: + *hashMech = CKM_SHA256; + break; + case WC_HASH_TYPE_SHA384: + *hashMech = CKM_SHA384; + break; + case WC_HASH_TYPE_SHA512: + *hashMech = CKM_SHA512; + break; + #ifndef WOLFSSL_NOSHA512_256 + case WC_HASH_TYPE_SHA512_256: + *hashMech = CKM_SHA512_256; + break; + #endif + case WC_HASH_TYPE_SHA3_256: + *hashMech = CKM_SHA3_256; + break; + case WC_HASH_TYPE_SHA3_384: + *hashMech = CKM_SHA3_384; + break; + case WC_HASH_TYPE_SHA3_512: + *hashMech = CKM_SHA3_512; + break; + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + +/** + * Perform an ML-DSA key generation operation. + * The private key data stays on the device. + * + * @param [in] session Session object. + * @param [in] key ML-DSA key. Already configured with the desired + * level and parameters. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return 0 on success. + */ +static int Pkcs11MldsaKeyGen(Pkcs11Session* session, MlDsaKey* key) +{ + int ret = 0; + CK_RV rv; + CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_ML_DSA_PARAMETER_SET_TYPE param_set = 0; + + /* Empty entries for optional label/ID. */ + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_PARAMETER_SET, ¶m_set, sizeof(param_set) }, + { 0, NULL, 0 }, + { 0, NULL, 0 } + }; + /* Mandatory entries + 2 optional. */ + CK_ULONG pubTmplCnt = sizeof(pubKeyTmpl)/sizeof(*pubKeyTmpl) - 2; + + /* Empty entries for optional label/ID. */ + CK_ATTRIBUTE privKeyTmpl[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_PARAMETER_SET, ¶m_set, sizeof(param_set) }, + { 0, NULL, 0 }, + { 0, NULL, 0 } + }; + /* Mandatory entries + 2 optional. */ + CK_ULONG privTmplCnt = sizeof(privKeyTmpl)/sizeof(*privKeyTmpl) - 2; + + ret = Pkcs11MechAvail(session, CKM_ML_DSA_KEY_PAIR_GEN, &mechInfo); + if (ret == 0) { + if ((key->level == WC_ML_DSA_44) && + (mechInfo.ulMinKeySize <= ML_DSA_LEVEL2_PUB_KEY_SIZE) && + (mechInfo.ulMaxKeySize >= ML_DSA_LEVEL2_PUB_KEY_SIZE)) { + param_set = CKP_ML_DSA_44; + } + else if ((key->level == WC_ML_DSA_65) && + (mechInfo.ulMinKeySize <= ML_DSA_LEVEL3_PUB_KEY_SIZE) && + (mechInfo.ulMaxKeySize >= ML_DSA_LEVEL3_PUB_KEY_SIZE)) { + param_set = CKP_ML_DSA_65; + } + else if ((key->level == WC_ML_DSA_87) && + (mechInfo.ulMinKeySize <= ML_DSA_LEVEL5_PUB_KEY_SIZE) && + (mechInfo.ulMaxKeySize >= ML_DSA_LEVEL5_PUB_KEY_SIZE)) { + param_set = CKP_ML_DSA_87; + } + else { + ret = WC_KEY_SIZE_E; + } + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: ML-DSA Key Generation Operation"); + + if (key->labelLen != 0) { + privKeyTmpl[privTmplCnt].type = CKA_LABEL; + privKeyTmpl[privTmplCnt].pValue = key->label; + privKeyTmpl[privTmplCnt].ulValueLen = key->labelLen; + privTmplCnt++; + + pubKeyTmpl[pubTmplCnt].type = CKA_LABEL; + pubKeyTmpl[pubTmplCnt].pValue = key->label; + pubKeyTmpl[pubTmplCnt].ulValueLen = key->labelLen; + pubTmplCnt++; + } + if (key->idLen != 0) { + privKeyTmpl[privTmplCnt].type = CKA_ID; + privKeyTmpl[privTmplCnt].pValue = key->id; + privKeyTmpl[privTmplCnt].ulValueLen = key->idLen; + privTmplCnt++; + + pubKeyTmpl[pubTmplCnt].type = CKA_ID; + pubKeyTmpl[pubTmplCnt].pValue = key->id; + pubKeyTmpl[pubTmplCnt].ulValueLen = key->idLen; + pubTmplCnt++; + } + + mech.mechanism = CKM_ML_DSA_KEY_PAIR_GEN; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + PKCS11_DUMP_TEMPLATE("Private Key", privKeyTmpl, privTmplCnt); + PKCS11_DUMP_TEMPLATE("Public Key", pubKeyTmpl, pubTmplCnt); + + rv = session->func->C_GenerateKeyPair(session->handle, &mech, + pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, + &pubKey, &privKey); + PKCS11_RV("C_GenerateKeyPair", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + if (ret == 0) + ret = Pkcs11GetMldsaPublicKey(key, session, pubKey); + + if (pubKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, pubKey); + if (ret == 0 && privKey != NULL_PTR) { + key->devCtx = (void*)(wc_ptr_t)privKey; + } + else if (ret != 0 && privKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, privKey); + + return ret; +} + +/** + * Performs the ML-DSA signing operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return 0 on success. + */ +static int Pkcs11MldsaSign(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + CK_RV rv; + CK_ULONG outLen; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + MlDsaKey* key = (MlDsaKey*) info->pk.pqc_sign.key; + + union { + CK_SIGN_ADDITIONAL_CONTEXT pure; + CK_HASH_SIGN_ADDITIONAL_CONTEXT preHash; + } paramSet; + XMEMSET(¶mSet, 0, sizeof(paramSet)); + + /* Check operation is supported. */ + if (info->pk.pqc_sign.preHashType != WC_HASH_TYPE_NONE) { + ret = Pkcs11MechAvail(session, CKM_HASH_ML_DSA, &mechInfo); + } + else { + ret = Pkcs11MechAvail(session, CKM_ML_DSA, &mechInfo); + } + if (ret == 0 && (mechInfo.flags & CKF_SIGN) == 0) { + ret = NOT_COMPILED_IN; + } + if (ret == 0 && info->pk.pqc_sign.outlen == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0 && info->pk.pqc_sign.out == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: ML-DSA Signing Operation"); + + if (key->devCtx != NULL) { + privateKey = (CK_OBJECT_HANDLE)(wc_ptr_t)key->devCtx; + } + else if ((sessionKey = key->prvKeySet)) + ret = Pkcs11CreateMldsaPrivateKey(&privateKey, session, + key, &mechInfo); + else if (key->labelLen > 0) { + ret = Pkcs11FindKeyByLabel(&privateKey, CKO_PRIVATE_KEY, CKK_ML_DSA, + session, key->label, key->labelLen); + } + else if (key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_ML_DSA, + session, key->id, key->idLen); + } + else { + ret = Pkcs11FindMldsaKey(&privateKey, CKO_PRIVATE_KEY, session, + key); + } + } + if (ret == 0) { + /* Prepare mechanism structure */ + mech.mechanism = CKM_ML_DSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + if (info->pk.pqc_sign.preHashType != WC_HASH_TYPE_NONE) { + /* Set the preHash algorithm */ + ret = Pkcs11GetMldsaPreHash(info->pk.pqc_sign.preHashType, + ¶mSet.preHash.hash); + if (ret == 0) { + mech.mechanism = CKM_HASH_ML_DSA; + mech.pParameter = ¶mSet.preHash; + mech.ulParameterLen = sizeof(paramSet.preHash); + } + + /* Set the context data */ + if (info->pk.pqc_sign.context != NULL && + info->pk.pqc_sign.contextLen > 0) { + paramSet.preHash.pContext = (byte*)info->pk.pqc_sign.context; + paramSet.preHash.ulContextLen = info->pk.pqc_sign.contextLen; + } + else { + paramSet.preHash.pContext = NULL; + paramSet.preHash.ulContextLen = 0; + } + paramSet.preHash.hedgeVariant = CKH_HEDGE_REQUIRED; + } + else { + /* Set the context data */ + if (info->pk.pqc_sign.context != NULL && + info->pk.pqc_sign.contextLen > 0) { + paramSet.pure.pContext = (byte*) info->pk.pqc_sign.context; + paramSet.pure.ulContextLen = info->pk.pqc_sign.contextLen; + + paramSet.pure.hedgeVariant = CKH_HEDGE_REQUIRED; + + mech.pParameter = ¶mSet.pure; + mech.ulParameterLen = sizeof(paramSet.pure); + } + } + } + if (ret == 0) { + rv = session->func->C_SignInit(session->handle, &mech, privateKey); + PKCS11_RV("C_SignInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + if (ret == 0) { + outLen = *info->pk.pqc_sign.outlen; + rv = session->func->C_Sign(session->handle, + (CK_BYTE_PTR)info->pk.pqc_sign.in, + info->pk.pqc_sign.inlen, + info->pk.pqc_sign.out, + &outLen); + PKCS11_RV("C_Sign", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + if (ret == 0) { + *info->pk.pqc_sign.outlen = outLen; + } + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + return ret; +} + +/** + * Performs the ML-DSA verification operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11MldsaVerify(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE publicKey = NULL_PTR; + MlDsaKey* key = (MlDsaKey*) info->pk.pqc_verify.key; + + union { + CK_SIGN_ADDITIONAL_CONTEXT pure; + CK_HASH_SIGN_ADDITIONAL_CONTEXT preHash; + } paramSet; + XMEMSET(¶mSet, 0, sizeof(paramSet)); + + /* Check operation is supported. */ + if (info->pk.pqc_verify.preHashType != WC_HASH_TYPE_NONE) { + ret = Pkcs11MechAvail(session, CKM_HASH_ML_DSA, &mechInfo); + } + else { + ret = Pkcs11MechAvail(session, CKM_ML_DSA, &mechInfo); + } + if (ret == 0 && (mechInfo.flags & CKF_VERIFY) == 0) { + ret = NOT_COMPILED_IN; + } + if (ret == 0 && info->pk.pqc_verify.res == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: ML-DSA Verification Operation"); + + if (key->labelLen > 0) { + ret = Pkcs11FindKeyByLabel(&publicKey, CKO_PUBLIC_KEY, CKK_ML_DSA, + session, key->label, key->labelLen); + } + else if (key->idLen > 0) { + ret = Pkcs11FindKeyById(&publicKey, CKO_PUBLIC_KEY, CKK_ML_DSA, + session, key->id, key->idLen); + } + else if (key->pubKeySet) { + ret = Pkcs11CreateMldsaPublicKey(&publicKey, session, + key, &mechInfo); + sessionKey = 1; + } + else { + ret = Pkcs11FindMldsaKey(&publicKey, CKO_PUBLIC_KEY, session, + key); + } + } + if (ret == 0) { + /* Prepare mechanism structure */ + mech.mechanism = CKM_ML_DSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + if (info->pk.pqc_verify.preHashType != WC_HASH_TYPE_NONE) { + /* Set the preHash algorithm */ + ret = Pkcs11GetMldsaPreHash(info->pk.pqc_verify.preHashType, + ¶mSet.preHash.hash); + if (ret == 0) { + mech.mechanism = CKM_HASH_ML_DSA; + mech.pParameter = ¶mSet.preHash; + mech.ulParameterLen = sizeof(paramSet.preHash); + } + + /* Set the context data */ + if (info->pk.pqc_verify.context != NULL && + info->pk.pqc_verify.contextLen > 0) { + paramSet.preHash.pContext = (byte*) info->pk.pqc_verify.context; + paramSet.preHash.ulContextLen = info->pk.pqc_verify.contextLen; + } + else { + paramSet.preHash.pContext = NULL; + paramSet.preHash.ulContextLen = 0; + } + } + else { + /* Set the context data */ + if (info->pk.pqc_verify.context != NULL && + info->pk.pqc_verify.contextLen > 0) { + paramSet.pure.pContext = (byte*) info->pk.pqc_verify.context; + paramSet.pure.ulContextLen = info->pk.pqc_verify.contextLen; + + mech.pParameter = ¶mSet.pure; + mech.ulParameterLen = sizeof(paramSet.pure); + } + } + } + if (ret == 0) { + rv = session->func->C_VerifyInit(session->handle, &mech, publicKey); + PKCS11_RV("C_VerifyInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + if (ret == 0) { + *info->pk.pqc_verify.res = 0; + rv = session->func->C_Verify(session->handle, + (CK_BYTE_PTR)info->pk.pqc_verify.msg, + info->pk.pqc_verify.msglen, + (CK_BYTE_PTR)info->pk.pqc_verify.sig, + info->pk.pqc_verify.siglen); + PKCS11_RV("C_Verify", rv); + if (rv == CKR_SIGNATURE_INVALID) + ret = SIG_VERIFY_E; + else if (rv != CKR_OK) + ret = WC_HW_E; + else + *info->pk.pqc_verify.res = 1; + } + + if (sessionKey && publicKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, publicKey); + + return ret; +} + +/** + * Checks whether the stored ML-DSA private key matches the given public key. + * Do this by looking up the public key data from the associated private key. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return MP_CMP_E when the public parts are different. + * @return 0 on success. + */ +static int Pkcs11MldsaCheckPrivKey(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + byte key_level = 0; + word32 storedKeySize = 0; + word32 idx = 0; + CK_OBJECT_HANDLE privKeyHandle; + MlDsaKey* privKey = (MlDsaKey*) info->pk.pqc_sig_check.key; + WC_DECLARE_VAR(pubKey, MlDsaKey, 1, privKey->heap); + + WC_ALLOC_VAR_EX(pubKey, MlDsaKey, 1, privKey->heap, DYNAMIC_TYPE_DILITHIUM, + ret = MEMORY_E); + + /* Get the ML-DSA public key object. */ + if (ret == 0 && privKey->labelLen > 0) + ret = Pkcs11FindKeyByLabel(&privKeyHandle, CKO_PUBLIC_KEY, CKK_ML_DSA, + session, privKey->label, privKey->labelLen); + else if (ret == 0 && privKey->idLen > 0) + ret = Pkcs11FindKeyById(&privKeyHandle, CKO_PUBLIC_KEY, CKK_ML_DSA, + session, privKey->id, privKey->idLen); + else if (ret == 0) + ret = Pkcs11FindMldsaKey(&privKeyHandle, CKO_PUBLIC_KEY, + session, privKey); + if (ret == 0) { + /* Extract the public key components. */ + ret = Pkcs11GetMldsaPublicKey(privKey, session, privKeyHandle); + } + + /* Get the security level of the private key */ + if (ret == 0) + ret = wc_MlDsaKey_GetParams(privKey, &key_level); + + if (ret == 0) { + if (key_level == WC_ML_DSA_44) + storedKeySize = ML_DSA_LEVEL2_PUB_KEY_SIZE; + else if (key_level == WC_ML_DSA_65) + storedKeySize = ML_DSA_LEVEL3_PUB_KEY_SIZE; + else if (key_level == WC_ML_DSA_87) + storedKeySize = ML_DSA_LEVEL5_PUB_KEY_SIZE; + else + ret = WC_KEY_SIZE_E; + } + + if ((ret == 0) && + ((ret = wc_MlDsaKey_Init(pubKey, privKey->heap, INVALID_DEVID)) == 0)) { + ret = wc_MlDsaKey_SetParams(pubKey, key_level); + if (ret == 0) { + ret = wc_MlDsaKey_PublicKeyDecode(pubKey, + info->pk.pqc_sig_check.pubKey, + info->pk.pqc_sig_check.pubKeySz, + &idx); + } + if (ret == 0) { + /* Compare the data of the provided public key with the data + * stored in the private key object */ + ret = XMEMCMP(privKey->p, pubKey->p, storedKeySize); + if (ret != 0) + ret = MP_CMP_E; + } + wc_MlDsaKey_Free(pubKey); + } + + WC_FREE_VAR_EX(pubKey, privKey->heap, DYNAMIC_TYPE_DILITHIUM); + + return ret; +} + +/** + * Deletes the ML-DSA private key. + * + * @param [in] session Session object. + * @param [in] key ML-DSA key. + * @return 0 on success. + */ +static int Pkcs11MldsaDeletePrivKey(Pkcs11Session* session, MlDsaKey* key) +{ + CK_OBJECT_HANDLE privateKey; + + if (key != NULL && key->devCtx != NULL) { + privateKey = (CK_OBJECT_HANDLE)(wc_ptr_t)key->devCtx; + + session->func->C_DestroyObject(session->handle, privateKey); + + key->devCtx = NULL; + } + + return 0; +} + +/** + * Perform a PQC key generation operation. + * The private key data stays on the device. + * + * @param [in] session Session object. + * @param [in] info Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return 0 on success. + */ +static int Pkcs11PqcSigKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + + switch (info->pk.pqc_sig_kg.type) { + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = Pkcs11MldsaKeyGen(session, + (MlDsaKey*)info->pk.pqc_sig_kg.key); + break; + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} + +/** + * Performs the signing operation with the PQC algorithm. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return 0 on success. + */ +static int Pkcs11PqcSigSign(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + + switch (info->pk.pqc_sign.type) { + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = Pkcs11MldsaSign(session, info); + break; + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} + +/** + * Performs the verification operation with the PQC algorithm. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11PqcSigVerify(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + + switch (info->pk.pqc_verify.type) { + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = Pkcs11MldsaVerify(session, info); + break; + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} + +/** + * Checks whether the stored PQC private key matches the given PQC public key. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return MP_CMP_E when the public parts are different. + * @return 0 on success. + */ +static int Pkcs11PqcSigCheckPrivKey(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + + switch (info->pk.pqc_sig_check.type) { + case WC_PQC_SIG_TYPE_DILITHIUM: + ret = Pkcs11MldsaCheckPrivKey(session, info); + break; + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} +#endif /* HAVE_DILITHIUM */ + +#if !defined(NO_AES) && defined(HAVE_AESGCM) +/** + * Performs the AES-GCM encryption operation. + * + * @param [in] session Session object. + * @param [in] info Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo); + if (ret == 0 && (mechInfo.flags & CKF_ENCRYPT) == 0) { + ret = NOT_COMPILED_IN; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Encryption Operation"); + + /* Create a private key object or find by label or id. */ + if (aes->idLen == 0 && aes->labelLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, NULL, 0, NULL, 0, + CKA_ENCRYPT); + } + else if (aes->labelLen != 0) { + ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, CKK_AES, session, + aes->label, aes->labelLen); + } + else { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, + aes->id, aes->idLen); + } + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_enc.iv; + params.ulIvLen = info->cipher.aesgcm_enc.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_enc.authIn; + params.ulAADLen = info->cipher.aesgcm_enc.authInSz; + params.ulTagBits = info->cipher.aesgcm_enc.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + PKCS11_RV("C_EncryptInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + outLen = info->cipher.aesgcm_enc.sz; + rv = session->func->C_EncryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.out, + &outLen); + PKCS11_RV("C_EncryptUpdate", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + /* Authentication tag comes out in final block. */ + outLen = info->cipher.aesgcm_enc.authTagSz; + rv = session->func->C_EncryptFinal(session->handle, + info->cipher.aesgcm_enc.authTag, + &outLen); + PKCS11_RV("C_EncryptFinal", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + + if (aes->idLen == 0 && aes->labelLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} + +/** + * Performs the AES-GCM decryption operation. + * + * @param [in] session Session object. + * @param [in] info Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return MEMORY_E when a memory allocation fails. + * @return 0 on success. + */ +static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + word32 len; + + /* Check operation is supported. */ + ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo); + if (ret == 0 && (mechInfo.flags & CKF_DECRYPT) == 0) { + ret = NOT_COMPILED_IN; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Decryption Operation"); + + /* Create a private key object or find by id. */ + if (aes->idLen == 0 && aes->labelLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, NULL, 0, NULL, 0, + CKA_DECRYPT); + } + else if (aes->labelLen != 0) { + ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, CKK_AES, session, + aes->label, aes->labelLen); + } + else { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, + aes->id, aes->idLen); + } + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_dec.iv; + params.ulIvLen = info->cipher.aesgcm_dec.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_dec.authIn; + params.ulAADLen = info->cipher.aesgcm_dec.authInSz; + params.ulTagBits = info->cipher.aesgcm_dec.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + PKCS11_RV("C_DecryptInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + outLen = len = info->cipher.aesgcm_dec.sz; + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.out, + &outLen); + PKCS11_RV("C_DecryptUpdate", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + /* Put authentication tag in as encrypted data. */ + outLen = len = (len + info->cipher.aesgcm_dec.authTagSz - + (word32)outLen); + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.out, &outLen); PKCS11_RV("C_DecryptUpdate", rv); if (rv != CKR_OK) { @@ -4547,7 +5553,7 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) */ if (ret == 0) { if (info->algo_type == WC_ALGO_TYPE_PK) { -#if !defined(NO_RSA) || defined(HAVE_ECC) +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_DILITHIUM) switch (info->pk.type) { #ifndef NO_RSA case WC_PK_TYPE_RSA: @@ -4626,6 +5632,36 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) Pkcs11CloseSession(token, &session); } break; + #endif + #if defined(HAVE_DILITHIUM) + case WC_PK_TYPE_PQC_SIG_KEYGEN: + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11PqcSigKeyGen(&session, info); + Pkcs11CloseSession(token, &session); + } + break; + case WC_PK_TYPE_PQC_SIG_SIGN: + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11PqcSigSign(&session, info); + Pkcs11CloseSession(token, &session); + } + break; + case WC_PK_TYPE_PQC_SIG_VERIFY: + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11PqcSigVerify(&session, info); + Pkcs11CloseSession(token, &session); + } + break; + case WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY: + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11PqcSigCheckPrivKey(&session, info); + Pkcs11CloseSession(token, &session); + } + break; #endif default: ret = NOT_COMPILED_IN; @@ -4633,7 +5669,7 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) } #else ret = NOT_COMPILED_IN; -#endif /* !NO_RSA || HAVE_ECC */ +#endif /* !NO_RSA || HAVE_ECC || HAVE_DILITHIUM */ } else if (info->algo_type == WC_ALGO_TYPE_CIPHER) { #ifndef NO_AES @@ -4745,18 +5781,31 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) #ifdef HAVE_ECC if (info->free.algo == WC_ALGO_TYPE_PK && info->free.type == WC_PK_TYPE_EC_KEYGEN) { - ecc_key* key = (ecc_key*)info->free.obj; - if (key != NULL && key->devCtx != NULL) { - if (token->handle != NULL_PTR) { - CK_OBJECT_HANDLE handle = - (CK_OBJECT_HANDLE)(uintptr_t)key->devCtx; - token->func->C_DestroyObject(token->handle, handle); - } - key->devCtx = NULL; + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11EccDeletePrivKey(&session, + (ecc_key*)info->free.obj); + Pkcs11CloseSession(token, &session); + } + } + else + #endif + #ifdef HAVE_DILITHIUM + if (info->free.algo == WC_ALGO_TYPE_PK && + info->free.type == WC_PK_TYPE_PQC_SIG_KEYGEN && + info->free.subType == WC_PQC_SIG_TYPE_DILITHIUM) { + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + ret = Pkcs11MldsaDeletePrivKey(&session, + (MlDsaKey*)info->free.obj); + Pkcs11CloseSession(token, &session); } - ret = 0; } + else #endif + { + ret = NOT_COMPILED_IN; + } } else { ret = NOT_COMPILED_IN; diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 4af6785f38..d4f30642f5 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -488,6 +488,7 @@ typedef struct wc_CryptoInfo { struct { /* uses wc_AlgoType=WC_ALGO_TYPE_FREE */ int algo; /* enum wc_AlgoType - HASH, CIPHER, etc */ int type; /* For HASH: wc_HashType, CIPHER: wc_CipherType */ + int subType; /* For PQC: wc_PqcKemType, wc_PqcSignatureType */ void *obj; /* Object structure to free */ } free; #endif /* WOLF_CRYPTO_CB_FREE */ @@ -768,7 +769,8 @@ WOLFSSL_LOCAL int wc_CryptoCb_Copy(int devId, int algo, int type, void* src, void* dst); #endif /* WOLF_CRYPTO_CB_COPY */ #ifdef WOLF_CRYPTO_CB_FREE -WOLFSSL_LOCAL int wc_CryptoCb_Free(int devId, int algo, int type, void* obj); +WOLFSSL_LOCAL int wc_CryptoCb_Free(int devId, int algo, int type, int subType, + void* obj); #endif /* WOLF_CRYPTO_CB_FREE */ #endif /* WOLF_CRYPTO_CB */ diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index 9e1a9a782c..166bbb432f 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -1078,6 +1078,10 @@ WOLFSSL_LOCAL void wc_mldsa_poly_make_pos_avx2(sword32* a); wc_dilithium_sign_msg(msg, msgSz, sig, sigSz, key, rng) #define wc_MlDsaKey_SignCtx(key, ctx, ctxSz, sig, sigSz, msg, msgSz, rng) \ wc_dilithium_sign_ctx_msg(ctx, ctxSz, msg, msgSz, sig, sigSz, key, rng) +#define wc_MlDsaKey_SignCtxHash(key, ctx, ctxSz, sig, sigSz, hash, hashSz, \ + hashAlg, rng) \ + wc_dilithium_sign_ctx_hash(ctx, ctxSz, hashAlg, hash, hashSz, sig, sigSz, \ + key, rng) #define wc_MlDsaKey_Free(key) \ wc_dilithium_free(key) #define wc_MlDsaKey_ExportPubRaw(key, out, outLen) \ @@ -1087,7 +1091,11 @@ WOLFSSL_LOCAL void wc_mldsa_poly_make_pos_avx2(sword32* a); #define wc_MlDsaKey_Verify(key, sig, sigSz, msg, msgSz, res) \ wc_dilithium_verify_msg(sig, sigSz, msg, msgSz, res, key) #define wc_MlDsaKey_VerifyCtx(key, sig, sigSz, ctx, ctxSz, msg, msgSz, res) \ - wc_dilithium_verify_msg_ctx(sig, sigSz, ctx, ctxSz, msg, msgSz, res, key) + wc_dilithium_verify_ctx_msg(sig, sigSz, ctx, ctxSz, msg, msgSz, res, key) +#define wc_MlDsaKey_VerifyCtxHash(key, sig, sigSz, ctx, ctxSz, hash, hashSz, \ + hashAlg, res) \ + wc_dilithium_verify_ctx_hash(sig, sigSz, ctx, ctxSz, hashAlg, hash, \ + hashSz, res, key) #define wc_MlDsaKey_PublicKeyToDer(key, output, len, withAlg) \ wc_Dilithium_PublicKeyToDer(key, output, len, withAlg) @@ -1095,6 +1103,11 @@ WOLFSSL_LOCAL void wc_mldsa_poly_make_pos_avx2(sword32* a); #define wc_MlDsaKey_PrivateKeyToDer(key, output, len) \ wc_Dilithium_PrivateKeyToDer(key, output, len) +#define wc_MlDsaKey_PrivateKeyDecode(key, input, sz, idx) \ + wc_Dilithium_PrivateKeyDecode(input, idx, key, sz) +#define wc_MlDsaKey_PublicKeyDecode(key, input, sz, idx) \ + wc_Dilithium_PublicKeyDecode(input, idx, key, sz) + WOLFSSL_API int wc_MlDsaKey_GetPrivLen(MlDsaKey* key, int* len); WOLFSSL_API int wc_MlDsaKey_GetPubLen(MlDsaKey* key, int* len); diff --git a/wolfssl/wolfcrypt/pkcs11.h b/wolfssl/wolfcrypt/pkcs11.h index e5dd9f0dff..9885b41ba5 100644 --- a/wolfssl/wolfcrypt/pkcs11.h +++ b/wolfssl/wolfcrypt/pkcs11.h @@ -89,6 +89,7 @@ extern "C" { #define CKK_SHA384_HMAC 0x0000002cUL #define CKK_SHA512_HMAC 0x0000002dUL #define CKK_SHA224_HMAC 0x0000002eUL +#define CKK_ML_DSA 0x0000004aUL #define CKA_CLASS 0x00000000UL #define CKA_TOKEN 0x00000001UL @@ -139,6 +140,8 @@ extern "C" { #define CKA_HW_FEATURE_TYPE 0x00000300UL #define CKA_RESET_ON_INIT 0x00000301UL #define CKA_HAS_RESET 0x00000302UL +#define CKA_PARAMETER_SET 0x0000061DUL + #define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL #define CKM_RSA_PKCS 0x00000001UL @@ -158,6 +161,10 @@ extern "C" { #define CKM_SHA384_HMAC 0x00000261UL #define CKM_SHA512 0x00000270UL #define CKM_SHA512_HMAC 0x00000271UL +#define CKM_SHA512_256 0x0000004CUL +#define CKM_SHA3_256 0x000002B0UL +#define CKM_SHA3_384 0x000002C0UL +#define CKM_SHA3_512 0x000002D0UL #define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL #define CKM_EC_KEY_PAIR_GEN 0x00001040UL #define CKM_ECDSA 0x00001041UL @@ -167,6 +174,9 @@ extern "C" { #define CKM_AES_CBC 0x00001082UL #define CKM_AES_CTR 0x00001086UL #define CKM_AES_GCM 0x00001087UL +#define CKM_ML_DSA_KEY_PAIR_GEN 0x0000001CUL +#define CKM_ML_DSA 0x0000001DUL +#define CKM_HASH_ML_DSA 0x0000001FUL /* full data RSA PK callbacks */ #define CKM_SHA1_RSA_PKCS_PSS 0x0000000EUL @@ -395,6 +405,33 @@ typedef struct CK_ASYNC_DATA { } CK_ASYNC_DATA; typedef CK_ASYNC_DATA* CK_ASYNC_DATA_PTR; +/* generic PQ mechanism parameters */ +typedef CK_ULONG CK_HEDGE_TYPE; +#define CKH_HEDGE_PREFERRED 0x00000000UL +#define CKH_HEDGE_REQUIRED 0x00000001UL +#define CKH_DETERMINISTIC_REQUIRED 0x00000002UL + +typedef struct CK_SIGN_ADDITIONAL_CONTEXT { + CK_HEDGE_TYPE hedgeVariant; + CK_BYTE_PTR pContext; + CK_ULONG ulContextLen; +} CK_SIGN_ADDITIONAL_CONTEXT; + +typedef struct CK_HASH_SIGN_ADDITIONAL_CONTEXT { + CK_HEDGE_TYPE hedgeVariant; + CK_BYTE_PTR pContext; + CK_ULONG ulContextLen; + CK_MECHANISM_TYPE hash; +} CK_HASH_SIGN_ADDITIONAL_CONTEXT; + + +/* ML-DSA values for CKA_PARAMETER_SETS */ +typedef CK_ULONG CK_ML_DSA_PARAMETER_SET_TYPE; +#define CKP_ML_DSA_44 0x00000001UL +#define CKP_ML_DSA_65 0x00000002UL +#define CKP_ML_DSA_87 0x00000003UL + + /* Function list types. */ typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; typedef struct CK_FUNCTION_LIST_3_0 CK_FUNCTION_LIST_3_0; diff --git a/wolfssl/wolfcrypt/wc_pkcs11.h b/wolfssl/wolfcrypt/wc_pkcs11.h index 4a54e71b61..b65244ff43 100644 --- a/wolfssl/wolfcrypt/wc_pkcs11.h +++ b/wolfssl/wolfcrypt/wc_pkcs11.h @@ -78,6 +78,7 @@ enum Pkcs11KeyType { PKCS11_KEY_TYPE_HMAC, PKCS11_KEY_TYPE_RSA, PKCS11_KEY_TYPE_EC, + PKCS11_KEY_TYPE_MLDSA, }; WOLFSSL_API int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library,