From 90c6fe8ab293d8055ce4b818a32e52e301c76305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 26 Feb 2026 15:58:00 +0100 Subject: [PATCH] Add ML-DSA support --- .github/workflows/build-workflow.yml | 2 +- .github/workflows/clang-tidy.yml | 8 +- .github/workflows/cmake.yml | 3 +- .github/workflows/sanitizer-tests.yml | 6 +- .github/workflows/scan-build.yml | 4 +- .github/workflows/unit-test.yml | 4 + CMakeLists.txt | 9 + cmake/options.h.in | 2 + configure.ac | 21 + src/crypto.c | 152 ++++- src/internal.c | 839 +++++++++++++++++++++++++- src/slot.c | 28 + tests/pkcs11v3test.c | 761 +++++++++++++++++++++++ wolfpkcs11/internal.h | 22 + wolfpkcs11/pkcs11.h | 38 ++ wolfpkcs11/store.h | 2 + 16 files changed, 1889 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-workflow.yml b/.github/workflows/build-workflow.yml index f0aaf88b..428929dc 100644 --- a/.github/workflows/build-workflow.yml +++ b/.github/workflows/build-workflow.yml @@ -35,7 +35,7 @@ jobs: working-directory: ./wolfssl run: | ./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 \ - C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" + --enable-mldsa C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" - name: wolfssl make install working-directory: ./wolfssl run: make diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 6829dd7b..7544890e 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -29,19 +29,21 @@ on: jobs: clang-tidy: runs-on: ubuntu-latest - + strategy: fail-fast: false matrix: config: - name: "Standard Build" configure_flags: "" - - name: "NSS Build" + - name: "NSS Build" configure_flags: "--enable-nss" - name: "TPM Build" configure_flags: "--enable-tpm" - name: "NSS+TPM Build" configure_flags: "--enable-nss --enable-tpm" + - name: "PKCS#11 V3.2 PQC Build" + configure_flags: "--enable-pkcs11v32 --enable-mldsa" steps: # Checkout wolfPKCS11 @@ -70,7 +72,7 @@ jobs: cd wolfssl ./autogen.sh ./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 \ - C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" + --enable-mldsa C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" make -j$(nproc) sudo make install sudo ldconfig diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4f69720f..6a4a6af6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -61,7 +61,8 @@ jobs: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWOLFPKCS11_INSTALL:BOOL=yes -DWOLFPKCS11_DEBUG:BOOL=yes \ -DWOLFPKCS11_AESKEYWRAP:BOOL=yes -DWOLFPKCS11_AESCTR:BOOL=yes -DWOLFPKCS11_AESCCM:BOOL=yes \ -DWOLFPKCS11_AESECB:BOOL=yes -DWOLFPKCS11_AESCTS:BOOL=yes -DWOLFPKCS11_AESCMAC:BOOL=yes \ - -DWOLFPKCS11_PBKDF2:BOOL=yes -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/${CMAKE_INSTALL_LIBDIR}" \ + -DWOLFPKCS11_PBKDF2:BOOL=yes -DWOLFPKCS11_MLDSA:BOOL=yes \ + -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/${CMAKE_INSTALL_LIBDIR}" \ .. cmake --build . ctest -j $(nproc) diff --git a/.github/workflows/sanitizer-tests.yml b/.github/workflows/sanitizer-tests.yml index 9e079450..a4e81919 100644 --- a/.github/workflows/sanitizer-tests.yml +++ b/.github/workflows/sanitizer-tests.yml @@ -19,12 +19,14 @@ jobs: config: - name: "Standard Build" configure_flags: "" - - name: "NSS Build" + - name: "NSS Build" configure_flags: "--enable-nss" - name: "TPM Build" configure_flags: "--enable-tpm" - name: "NSS+TPM Build" configure_flags: "--enable-nss --enable-tpm" + - name: "PKCS#11 V3.2 PQC Build" + configure_flags: "--enable-pkcs11v32 --enable-mldsa" steps: #pull wolfPKCS11 @@ -73,7 +75,7 @@ jobs: ;; esac ./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 --enable-debug \ - C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" + --enable-mldsa C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" - name: wolfssl make working-directory: ./wolfssl run: | diff --git a/.github/workflows/scan-build.yml b/.github/workflows/scan-build.yml index a76149b3..7b69960e 100644 --- a/.github/workflows/scan-build.yml +++ b/.github/workflows/scan-build.yml @@ -44,6 +44,8 @@ jobs: configure_flags: "--enable-tpm" - name: "NSS+TPM Build" configure_flags: "--enable-nss --enable-tpm" + - name: "PKCS#11 V3.2 PQC Build" + configure_flags: "--enable-pkcs11v32 --enable-mldsa" steps: # Checkout wolfPKCS11 @@ -72,7 +74,7 @@ jobs: cd wolfssl ./autogen.sh ./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 \ - C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" + --enable-mldsa C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" make -j$(nproc) sudo make install sudo ldconfig diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 4e8f0c31..fb787964 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -102,6 +102,10 @@ jobs: uses: ./.github/workflows/build-workflow.yml with: config: --enable-pkcs11v32 --disable-shared + mldsa: + uses: ./.github/workflows/build-workflow.yml + with: + config: --enable-mldsa debug: uses: ./.github/workflows/build-workflow.yml with: diff --git a/CMakeLists.txt b/CMakeLists.txt index fa426b0c..2bea1caf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -409,6 +409,15 @@ if(WOLFPKCS11_SHA3) list(APPEND WOLFPKCS11_DEFINITIONS "-DWOLFSSL_SHA3") endif() +# ML-DSA +add_option("WOLFPKCS11_MLDSA" + "Enable wolfPKCS11 ML-DSA support (default: disabled)" + "no" "yes;no" +) + +if(WOLFPKCS11_MLDSA) + list(APPEND WOLFPKCS11_DEFINITIONS "-DWOLFPKCS11_MLDSA") +endif() # WolfTPM add_option("WOLFPKCS11_TPM" diff --git a/cmake/options.h.in b/cmake/options.h.in index 46fa7cc2..c54f7b7f 100644 --- a/cmake/options.h.in +++ b/cmake/options.h.in @@ -92,6 +92,8 @@ extern "C" { #cmakedefine WOLFSSL_SHA512 #undef WOLFSSL_SHA3 #cmakedefine WOLFSSL_SHA3 +#undef WOLFPKCS11_MLDSA +#cmakedefine WOLFPKCS11_MLDSA #undef WOLFPKCS11_TPM #cmakedefine WOLFPKCS11_TPM #undef WOLFPKCS11_NSS diff --git a/configure.ac b/configure.ac index badf1095..bb68bdae 100644 --- a/configure.ac +++ b/configure.ac @@ -516,6 +516,26 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFPKCS11_PKCS11_V3_2" fi +AC_ARG_ENABLE([mldsa], + [AS_HELP_STRING([--enable-mldsa],[Enable ML-DSA (default: disabled)])], + [ ENABLED_MLDSA=$enableval ], + [ ENABLED_MLDSA=no ] + ) + +if test "$ENABLED_SHA3" = "no" +then + ENABLED_MLDSA=no +fi + +if test "$ENABLED_MLDSA" = "yes" +then + if test "$ENABLED_PKCS11V3_2" = "no"; then + ENABLED_PKCS11V3_2=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFPKCS11_PKCS11_V3_2" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFPKCS11_MLDSA" +fi + AM_CONDITIONAL([BUILD_STATIC],[test "x$enable_shared" = "xno"]) @@ -703,6 +723,7 @@ echo " * RSA-PSS: $ENABLED_RSAPSS" echo " * DH: $ENABLED_DH" echo " * ECC: $ENABLED_ECC" echo " * HKDF: $ENABLED_HKDF" +echo " * ML-DSA: $ENABLED_MLDSA" echo " * NSS modifications: $ENABLED_NSS" echo " * Default token path: $WOLFPKCS11_DEFAULT_TOKEN_PATH" echo " * PKCS#11 Version 3.0: $ENABLED_PKCS11V3_0" diff --git a/src/crypto.c b/src/crypto.c index 6dc25d3b..d4d08d39 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -87,6 +87,16 @@ static CK_ATTRIBUTE_TYPE ecKeyParams[] = { #define EC_KEY_PARAMS_CNT (sizeof(ecKeyParams)/sizeof(*ecKeyParams)) #endif +#ifdef WOLFPKCS11_MLDSA +/* ML-DSA key data attributes. */ +static CK_ATTRIBUTE_TYPE mldsaKeyParams[] = { + CKA_PARAMETER_SET, + CKA_VALUE +}; +/* Count of ML-DSA key data attributes. */ +#define MLDSA_KEY_PARAMS_CNT (sizeof(mldsaKeyParams)/sizeof(*mldsaKeyParams)) +#endif + #ifndef NO_DH /* DH key data attributes. */ static CK_ATTRIBUTE_TYPE dhKeyParams[] = { @@ -224,6 +234,7 @@ static AttributeType attrType[] = { { CKA_HASH_OF_ISSUER_PUBLIC_KEY, ATTR_TYPE_DATA }, { CKA_NAME_HASH_ALGORITHM, ATTR_TYPE_ULONG }, { CKA_CHECK_VALUE, ATTR_TYPE_DATA }, + { CKA_PARAMETER_SET, ATTR_TYPE_DATA }, #ifdef WOLFPKCS11_NSS { CKA_CERT_SHA1_HASH, ATTR_TYPE_DATA }, { CKA_CERT_MD5_HASH, ATTR_TYPE_DATA }, @@ -455,6 +466,14 @@ static CK_RV SetAttributeDefaults(WP11_Object* obj, CK_OBJECT_CLASS keyType, wrap = CK_FALSE; sign = CK_TRUE; break; + case CKK_ML_DSA: + derive = CK_FALSE; + verify = CK_TRUE; + encrypt = CK_FALSE; + recover = CK_FALSE; + wrap = CK_FALSE; + sign = CK_TRUE; + break; } /* Defaults if not set */ @@ -602,6 +621,12 @@ static CK_RV SetAttributeValue(WP11_Session* session, WP11_Object* obj, cnt = EC_KEY_PARAMS_CNT; break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + attrs = mldsaKeyParams; + cnt = MLDSA_KEY_PARAMS_CNT; + break; + #endif #ifndef NO_DH case CKK_DH: attrs = dhKeyParams; @@ -667,6 +692,11 @@ static CK_RV SetAttributeValue(WP11_Session* session, WP11_Object* obj, ret = WP11_Object_SetEcKey(obj, data, len); break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = WP11_Object_SetMldsaKey(obj, data, len); + break; + #endif #ifndef NO_DH case CKK_DH: ret = WP11_Object_SetDhKey(obj, data, len); @@ -1028,7 +1058,7 @@ static CK_RV CreateObject(WP11_Session* session, CK_ATTRIBUTE_PTR pTemplate, if (objType != CKK_RSA && objType != CKK_EC && objType != CKK_DH && objType != CKK_AES && objType != CKK_HKDF && - objType != CKK_GENERIC_SECRET) { + objType != CKK_GENERIC_SECRET && objType != CKK_ML_DSA) { return CKR_ATTRIBUTE_VALUE_INVALID; } } @@ -4163,6 +4193,39 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, ((pMechanism->mechanism - CKM_ECDSA) << WP11_INIT_DIGEST_SHIFT)); break; #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA: + if (type != CKK_ML_DSA) + return CKR_KEY_TYPE_INCONSISTENT; + if ((pMechanism->pParameter != NULL) && + (pMechanism->ulParameterLen != sizeof(CK_SIGN_ADDITIONAL_CONTEXT))) + return CKR_MECHANISM_PARAM_INVALID; + + ret = WP11_Session_SetMldsaParams(session, + pMechanism->pParameter, + pMechanism->ulParameterLen); + if (ret != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init |= WP11_INIT_MLDSA_SIGN; + break; + case CKM_HASH_ML_DSA: + if (type != CKK_ML_DSA) + return CKR_KEY_TYPE_INCONSISTENT; + if ((pMechanism->pParameter != NULL) && + (pMechanism->ulParameterLen != + sizeof(CK_HASH_SIGN_ADDITIONAL_CONTEXT))) + return CKR_MECHANISM_PARAM_INVALID; + + ret = WP11_Session_SetMldsaParams(session, + pMechanism->pParameter, + pMechanism->ulParameterLen); + if (ret != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init |= WP11_INIT_MLDSA_SIGN; + break; +#endif #ifndef NO_HMAC #ifndef NO_MD5 case CKM_MD5_HMAC: @@ -4525,6 +4588,25 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, break; } #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA: + case CKM_HASH_ML_DSA: + if (!WP11_Session_IsOpInitialized(session, WP11_INIT_MLDSA_SIGN)) + return CKR_OPERATION_NOT_INITIALIZED; + + sigLen = WP11_Mldsa_SigLen(obj); + if (pSignature == NULL) { + *pulSignatureLen = sigLen; + return CKR_OK; + } + if (sigLen > (word32)*pulSignatureLen) + return CKR_BUFFER_TOO_SMALL; + + ret = WP11_Mldsa_Sign(pData, (int)ulDataLen, pSignature, + &sigLen, obj, session); + *pulSignatureLen = sigLen; + break; +#endif #ifndef NO_HMAC #ifndef NO_MD5 case CKM_MD5_HMAC: @@ -5178,6 +5260,39 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, ((pMechanism->mechanism - CKM_ECDSA) << WP11_INIT_DIGEST_SHIFT)); break; #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA: + if (type != CKK_ML_DSA) + return CKR_KEY_TYPE_INCONSISTENT; + if ((pMechanism->pParameter != NULL) && + (pMechanism->ulParameterLen != sizeof(CK_SIGN_ADDITIONAL_CONTEXT))) + return CKR_MECHANISM_PARAM_INVALID; + + ret = WP11_Session_SetMldsaParams(session, + pMechanism->pParameter, + pMechanism->ulParameterLen); + if (ret != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init |= WP11_INIT_MLDSA_VERIFY; + break; + case CKM_HASH_ML_DSA: + if (type != CKK_ML_DSA) + return CKR_KEY_TYPE_INCONSISTENT; + if ((pMechanism->pParameter != NULL) && + (pMechanism->ulParameterLen != + sizeof(CK_HASH_SIGN_ADDITIONAL_CONTEXT))) + return CKR_MECHANISM_PARAM_INVALID; + + ret = WP11_Session_SetMldsaParams(session, + pMechanism->pParameter, + pMechanism->ulParameterLen); + if (ret != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init |= WP11_INIT_MLDSA_VERIFY; + break; +#endif #ifndef NO_HMAC #ifndef NO_MD5 case CKM_MD5_HMAC: @@ -5495,6 +5610,16 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, break; } #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA: + case CKM_HASH_ML_DSA: + if (!WP11_Session_IsOpInitialized(session, WP11_INIT_MLDSA_VERIFY)) + return CKR_OPERATION_NOT_INITIALIZED; + + ret = WP11_Mldsa_Verify(pSignature, (int)ulSignatureLen, pData, + (int)ulDataLen, &stat, obj, session); + break; +#endif #ifndef NO_HMAC #ifndef NO_MD5 case CKM_MD5_HMAC: @@ -6728,7 +6853,7 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, break; #endif #ifdef HAVE_ECC - case CKM_EC_KEY_PAIR_GEN: + case CKM_EC_KEY_PAIR_GEN: if (pMechanism->pParameter != NULL || pMechanism->ulParameterLen != 0) { return CKR_MECHANISM_PARAM_INVALID; @@ -6751,6 +6876,29 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, } break; #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA_KEY_PAIR_GEN: + if (pMechanism->pParameter != NULL || + pMechanism->ulParameterLen != 0) { + return CKR_MECHANISM_PARAM_INVALID; + } + + *phPublicKey = *phPrivateKey = CK_INVALID_HANDLE; + rv = NewObject(session, CKK_ML_DSA, CKO_PUBLIC_KEY, + pPublicKeyTemplate, ulPublicKeyAttributeCount, &pub); + if (rv == CKR_OK) { + rv = NewObject(session, CKK_ML_DSA, CKO_PRIVATE_KEY, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + &priv); + } + if (rv == CKR_OK) { + ret = WP11_Mldsa_GenerateKeyPair(pub, priv, + WP11_Session_GetSlot(session)); + if (ret != 0) + rv = CKR_FUNCTION_FAILED; + } + break; +#endif #ifndef NO_DH case CKM_DH_PKCS_KEY_PAIR_GEN: if (pMechanism->pParameter != NULL || diff --git a/src/internal.c b/src/internal.c index 1d2c6093..9af4af2d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -254,6 +254,9 @@ struct WP11_Object { #ifdef HAVE_ECC ecc_key* ecKey; /* EC key object */ #endif + #ifdef WOLFPKCS11_MLDSA + MlDsaKey* mldsaKey; /* ML-DSA key object */ + #endif #ifndef NO_DH WP11_DhKey* dhKey; /* DH parameters object */ #endif @@ -343,6 +346,14 @@ typedef struct WP11_PssParams { #endif #endif +#ifdef WOLFPKCS11_MLDSA +typedef struct WP11_MldsaParams { + enum wc_HashType preHashType; + byte* ctx; + byte ctxSz; +} WP11_MldsaParams; +#endif + #ifndef NO_AES #ifdef HAVE_AES_CBC typedef struct WP11_CbcParams { @@ -450,6 +461,9 @@ struct WP11_Session { WP11_PssParams pss; /* RSA-PSS parameters */ #endif #endif +#ifdef WOLFPKCS11_MLDSA + WP11_MldsaParams mldsa; /* ML-DSA parameters */ +#endif #ifndef NO_AES #ifdef HAVE_AES_CBC WP11_CbcParams cbc; /* AES-CBC parameters */ @@ -890,7 +904,15 @@ static void wp11_Session_Final(WP11_Session* session) session->params.oaep.label = NULL; } #endif -#ifndef NO_RSA +#ifdef WOLFPKCS11_MLDSA + if ((session->mechanism == CKM_ML_DSA || + session->mechanism == CKM_HASH_ML_DSA) && + session->params.mldsa.ctx != NULL) { + XFREE(session->params.mldsa.ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + session->params.mldsa.ctx = NULL; + } +#endif +#ifndef NO_AES #ifdef HAVE_AES_CBC if ((session->mechanism == CKM_AES_CBC || session->mechanism == CKM_AES_CBC_PAD) && session->init) { @@ -1372,6 +1394,14 @@ static int wolfPKCS11_Store_Name(int type, CK_ULONG id1, CK_ULONG id2, char* nam ret = XSNPRINTF(name, nameLen, "%s/wp11_data_%016lx_%016lx", str, id1, id2); break; + case WOLFPKCS11_STORE_MLDSAKEY_PRIV: + ret = XSNPRINTF(name, nameLen, "%s/wp11_mldsakey_priv_%016lx_%016lx", + str, id1, id2); + break; + case WOLFPKCS11_STORE_MLDSAKEY_PUB: + ret = XSNPRINTF(name, nameLen, "%s/wp11_mldsakey_pub_%016lx_%016lx", + str, id1, id2); + break; default: ret = -1; @@ -2442,6 +2472,20 @@ int wp11_Object_AllocateTypeData(WP11_Object* object) } break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + if (object->data.mldsaKey == NULL) { + object->data.mldsaKey = (MlDsaKey*)XMALLOC( + sizeof(MlDsaKey), NULL, DYNAMIC_TYPE_DILITHIUM); + if (object->data.mldsaKey == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(object->data.mldsaKey, 0, sizeof(MlDsaKey)); + } + } + break; + #endif #ifndef NO_DH case CKK_DH: if (object->data.dhKey == NULL) { @@ -4096,6 +4140,248 @@ static int wp11_Object_Store_EccKey(WP11_Object* object, int tokenId, int objId) } #endif /* HAVE_ECC */ +#ifdef WOLFPKCS11_MLDSA +static int MldsaKeyTryDecode(MlDsaKey* key, byte level, byte* data, + word32 len, CK_OBJECT_CLASS class) +{ + int ret = 0; + word32 idx = 0; + + /* Init key */ + ret = wc_MlDsaKey_Init(key, NULL, INVALID_DEVID); + + if (ret == 0) { + /* Set level */ + ret = wc_MlDsaKey_SetParams(key, level); + } + if (ret == 0) { + if (class == CKO_PRIVATE_KEY) { + /* Decode ML-DSA private key. */ + ret = wc_Dilithium_PrivateKeyDecode(data, &idx, key, len); + } + else { + /* Decode ML-DSA public key. */ + ret = wc_Dilithium_PublicKeyDecode(data, &idx, key, len); + } + } + + return ret; +} + +/** + * Decode the ML-DSA key. + * + * Encoded private keys are encrypted. + * + * @param [in, out] object ML-DSA key object. + * @return 0 on success. + * @return -ve on failure. + */ +static int wp11_Object_Decode_MldsaKey(WP11_Object* object) +{ + int ret = 0; + + if (object->objClass == CKO_PRIVATE_KEY) { + unsigned char* der; + int len = object->keyDataLen - AES_BLOCK_SIZE; + + der = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + } + if (ret == 0) { + ret = wp11_DecryptData(der, object->keyData, len, + object->slot->token.key, + sizeof(object->slot->token.key), object->iv, + sizeof(object->iv), object->devId); + } + if (ret == 0) { + /* Decode ML-DSA private key. */ + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_44, + der, len, object->objClass); + if (ret != 0) { + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_65, + der, len, object->objClass); + } + if (ret != 0) { + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_87, + der, len, object->objClass); + } + XMEMSET(der, 0, len); + } + if (der != NULL) + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + /* Decode ML-DSA public key. */ + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_44, + object->keyData, object->keyDataLen, + object->objClass); + if (ret != 0) { + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_65, + object->keyData, object->keyDataLen, + object->objClass); + } + if (ret != 0) { + ret = MldsaKeyTryDecode(object->data.mldsaKey, WC_ML_DSA_87, + object->keyData, object->keyDataLen, + object->objClass); + } + } + object->encoded = (ret != 0); + + return ret; +} + +/** + * Encode the ML-DSA key. + * + * Private keys are encoded and then encrypted. + * + * @param [in, out] object ML-DSA key object. + * @return 0 on success. + * @return -ve on failure. + */ +static int wp11_Object_Encode_MldsaKey(WP11_Object* object) +{ + int ret; + + if (object->objClass == CKO_PRIVATE_KEY) { + /* Get length of encoded private key. */ + ret = wc_MlDsaKey_PrivateKeyToDer(object->data.mldsaKey, NULL, 0); + if (ret >= 0) { + object->keyDataLen = ret + AES_BLOCK_SIZE; + ret = 0; + } + } + else { + /* Get length of encoded public key. */ + ret = wc_MlDsaKey_PublicKeyToDer(object->data.mldsaKey, NULL, 0, 1); + if (ret >= 0) { + object->keyDataLen = ret; + ret = 0; + } + } + + if (ret == 0) { + XFREE(object->keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + /* Allocate buffer to hold encoded key. */ + object->keyData = (unsigned char*)XMALLOC(object->keyDataLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (object->keyData == NULL) + ret = MEMORY_E; + } + + if (ret == 0 && object->objClass == CKO_PRIVATE_KEY) { + /* Encode private key. */ + ret = wc_MlDsaKey_PrivateKeyToDer(object->data.mldsaKey, + object->keyData, + object->keyDataLen); + if (ret >= 0) { + ret = wp11_EncryptData(object->keyData, object->keyData, ret, + object->slot->token.key, + sizeof(object->slot->token.key), object->iv, + sizeof(object->iv), object->devId); + } + } + else if (ret == 0 && object->objClass == CKO_PUBLIC_KEY) { + /* Encode public key. */ + ret = wc_MlDsaKey_PublicKeyToDer(object->data.mldsaKey, + object->keyData, + object->keyDataLen, 1); + if (ret >= 0) { + ret = 0; + } + } + + if (ret != 0) { + XFREE(object->keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + object->keyData = NULL; + object->keyDataLen = 0; + } + + return ret; +} + +/** + * Load a ML-DSA key from storage. + * + * @param [in, out] object ML-DSA key object. + * @param [in] tokenId Id of token this key belongs to. + * @param [in] objId Id of object for token. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return BUFFER_E when loading fails. + * @return NOT_AVAILABLE_E when unable to locate data. + */ +static int wp11_Object_Load_MldsaKey(WP11_Object* object, int tokenId, + int objId) +{ + int ret; + void* storage = NULL; + int storeType; + + /* Determine store type - private keys may be encrypted. */ + if (object->objClass == CKO_PRIVATE_KEY) + storeType = WOLFPKCS11_STORE_MLDSAKEY_PRIV; + else + storeType = WOLFPKCS11_STORE_MLDSAKEY_PUB; + + /* Open access to ML-DSA key. */ + ret = wp11_storage_open_readonly(storeType, tokenId, objId, &storage); + if (ret == 0) { + /* Read DER encoded ML-DSA key. */ + ret = wp11_storage_read_alloc_array(storage, &object->keyData, + &object->keyDataLen); + wp11_storage_close(storage); + } + + return ret; +} + +/** + * Store a ML-DSA key to storage. + * + * @param [in] object ML-DSA key object. + * @param [in] tokenId Id of token this key belongs to. + * @param [in] objId Id of object for token. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return BUFFER_E when storing fails. + * @return NOT_AVAILABLE_E when unable to write data. + */ +static int wp11_Object_Store_MldsaKey(WP11_Object* object, int tokenId, + int objId) +{ + int ret; + void* storage = NULL; + int storeType; + + if (object->keyData == NULL) { + ret = wp11_Object_Encode_MldsaKey(object); + } + + /* Determine store type - private keys may be encrypted. */ + if (object->objClass == CKO_PRIVATE_KEY) + storeType = WOLFPKCS11_STORE_MLDSAKEY_PRIV; + else + storeType = WOLFPKCS11_STORE_MLDSAKEY_PUB; + + /* Open access to ML-DSA key. */ + ret = wp11_storage_open(storeType, tokenId, objId, object->keyDataLen, + &storage); + if (ret == 0) { + /* Write encoded ML-DSA key to storage. */ + ret = wp11_storage_write_array(storage, object->keyData, + object->keyDataLen); + + wp11_storage_close(storage); + } + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ + #ifndef NO_DH /** * Decode the DH key. @@ -4710,6 +4996,11 @@ static int wp11_Object_Load(WP11_Object* object, int tokenId, int objId) ret = wp11_Object_Load_EccKey(object, tokenId, objId); break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = wp11_Object_Load_MldsaKey(object, tokenId, objId); + break; + #endif #ifndef NO_DH case CKK_DH: ret = wp11_Object_Load_DhKey(object, tokenId, objId); @@ -4881,6 +5172,11 @@ static int wp11_Object_Store(WP11_Object* object, int tokenId, int objId) ret = wp11_Object_Store_EccKey(object, tokenId, objId); break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = wp11_Object_Store_MldsaKey(object, tokenId, objId); + break; + #endif #ifndef NO_DH case CKK_DH: ret = wp11_Object_Store_DhKey(object, tokenId, objId); @@ -4941,6 +5237,11 @@ static int wp11_Object_Decode(WP11_Object* object) ret = wp11_Object_Decode_EccKey(object); break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = wp11_Object_Decode_MldsaKey(object); + break; + #endif #ifndef NO_DH case CKK_DH: ret = wp11_Object_Decode_DhKey(object); @@ -5006,6 +5307,15 @@ static int wp11_Object_Encode(WP11_Object* object, int protect) } break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = wp11_Object_Encode_MldsaKey(object); + if (protect && ret == 0 && object->objClass == CKO_PRIVATE_KEY) { + wc_MlDsaKey_Free(object->data.mldsaKey); + object->encoded = 1; + } + break; + #endif #ifndef NO_DH case CKK_DH: ret = wp11_Object_Encode_DhKey(object); @@ -5088,6 +5398,14 @@ static int wp11_Object_Unstore(WP11_Object* object, int tokenId, int objId) storeObjType = WOLFPKCS11_STORE_ECCKEY_PUB; break; #endif + #ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + if (object->objClass == CKO_PRIVATE_KEY) + storeObjType = WOLFPKCS11_STORE_MLDSAKEY_PRIV; + else + storeObjType = WOLFPKCS11_STORE_MLDSAKEY_PUB; + break; + #endif #ifndef NO_DH case CKK_DH: if (object->objClass == CKO_PRIVATE_KEY) @@ -7034,7 +7352,7 @@ void WP11_Session_SetMechanism(WP11_Session* session, } #if !defined(NO_RSA) || !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS) || \ - defined(WOLFPKCS11_HKDF) + defined(WOLFPKCS11_HKDF) || defined(WOLFPKCS11_MLDSA) /** * Convert the digest mechanism to a hash type for wolfCrypt. * @@ -7069,6 +7387,11 @@ static int wp11_hash_type(CK_MECHANISM_TYPE hashMech, case CKM_SHA512_HMAC: *hashType = WC_HASH_TYPE_SHA512; break; + #ifndef WOLFSSL_NOSHA512_256 + case CKM_SHA512_256: + *hashType = WC_HASH_TYPE_SHA512_256; + break; + #endif case CKM_SHA3_224: *hashType = WC_HASH_TYPE_SHA3_224; break; @@ -7201,6 +7524,86 @@ int WP11_Session_SetPssParams(WP11_Session* session, CK_MECHANISM_TYPE hashAlg, #endif /* WC_RSA_PSS */ #endif /* !NO_RSA */ +#ifdef WOLFPKCS11_MLDSA +/** + * Set the parameters to use for a ML-DSA operation. + * + * @param session [in] Session object. + * @param params [in] Pointer to the parameters (may be NULL). + * @param paramsLen [in] Length of parameters (may be 0). + * @return BAD_FUNC_ARG when the parameters contain problems. + * 0 on success. + */ +int WP11_Session_SetMldsaParams(WP11_Session* session, CK_VOID_PTR params, + CK_ULONG paramsLen) +{ + int ret = 0; + WP11_MldsaParams* mldsa = &session->params.mldsa; + + XMEMSET(mldsa, 0, sizeof(*mldsa)); + + if (params != NULL) { + if (paramsLen == sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) { + CK_SIGN_ADDITIONAL_CONTEXT* ctx = + (CK_SIGN_ADDITIONAL_CONTEXT*)params; + + /* Copy context if present */ + if (ctx->pContext != NULL && ctx->ulContextLen > 0) { + mldsa->ctx = (byte*)XMALLOC(ctx->ulContextLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (mldsa->ctx == NULL) + ret = MEMORY_E; + if (ret == 0) { + XMEMCPY(mldsa->ctx, ctx->pContext, ctx->ulContextLen); + mldsa->ctxSz = ctx->ulContextLen; + } + } + else { + mldsa->ctx = NULL; + mldsa->ctxSz = 0; + } + + mldsa->preHashType = WC_HASH_TYPE_NONE; + } + else if (paramsLen == sizeof(CK_HASH_SIGN_ADDITIONAL_CONTEXT)) { + CK_HASH_SIGN_ADDITIONAL_CONTEXT* ctx = + (CK_HASH_SIGN_ADDITIONAL_CONTEXT*)params; + + /* Copy context if present */ + if (ctx->pContext != NULL && ctx->ulContextLen > 0) { + mldsa->ctx = (byte*)XMALLOC(ctx->ulContextLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (mldsa->ctx == NULL) + ret = MEMORY_E; + if (ret == 0) { + XMEMCPY(mldsa->ctx, ctx->pContext, ctx->ulContextLen); + mldsa->ctxSz = ctx->ulContextLen; + } + } + else { + mldsa->ctx = NULL; + mldsa->ctxSz = 0; + } + + /* Get hash type */ + if (ret == 0) { + ret = wp11_hash_type(ctx->hash, &mldsa->preHashType); + } + } + else { + ret = BAD_FUNC_ARG; + } + } + else { + mldsa->preHashType = WC_HASH_TYPE_NONE; + mldsa->ctx = NULL; + mldsa->ctxSz = 0; + } + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ + #ifndef NO_AES #ifdef HAVE_AES_CBC /** @@ -7830,6 +8233,13 @@ void WP11_Object_Free(WP11_Object* object) object->data.ecKey = NULL; } #endif + #ifdef WOLFPKCS11_MLDSA + if (object->type == CKK_ML_DSA && object->data.mldsaKey != NULL) { + wc_MlDsaKey_Free(object->data.mldsaKey); + XFREE(object->data.mldsaKey, NULL, DYNAMIC_TYPE_DILITHIUM); + object->data.mldsaKey = NULL; + } + #endif #ifndef NO_DH if (object->type == CKK_DH && object->data.dhKey != NULL) { wc_FreeDhKey(&object->data.dhKey->params); @@ -8168,6 +8578,98 @@ int WP11_Object_SetEcKey(WP11_Object* object, unsigned char** data, } #endif /* HAVE_ECC */ +#ifdef WOLFPKCS11_MLDSA +/** + * Set the ML-DSA parameters based on provided data. + * + * @param key [in] ML-DSA key object. + * @param params [in] Pointer to parameters structure. + * @param len [in] Length of parameters. + * @return BUFFER_E when len is too short. + * ASN_PARSE_E when parameter is bad. + * Other -ve on failure. + * 0 on success. + */ +static int mldsaSetParameters(MlDsaKey* key, + CK_ML_DSA_PARAMETER_SET_TYPE* params, + int len) +{ + int ret = 0; + + if (params == NULL || key == NULL) + return BAD_FUNC_ARG; + + if (len != sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)) + return BUFFER_E; + + /* Set ML-DSA level based on the parameter */ + switch (*params) { + case CKP_ML_DSA_44: + ret = wc_MlDsaKey_SetParams(key, WC_ML_DSA_44); + break; + case CKP_ML_DSA_65: + ret = wc_MlDsaKey_SetParams(key, WC_ML_DSA_65); + break; + case CKP_ML_DSA_87: + ret = wc_MlDsaKey_SetParams(key, WC_ML_DSA_87); + break; + default: + ret = ASN_PARSE_E; + break; + } + + return ret; +} + +/** +* Set the ML-DSA key data into the object. +* Store the data in the wolfCrypt data structure. +* +* @param object [in] Object object. +* @param data [in] Array of byte arrays. +* @param len [in] Array of lengths of byte arrays. +* @return -ve on failure. +* 0 on success. +*/ +int WP11_Object_SetMldsaKey(WP11_Object* object, unsigned char** data, + CK_ULONG* len) +{ + int ret; + MlDsaKey* key; + + if (object->onToken) + WP11_Lock_LockRW(object->lock); + + key = object->data.mldsaKey; + ret = wc_MlDsaKey_Init(key, NULL, object->devId); + + /* Set parameters */ + if (ret == 0) { + ret = mldsaSetParameters(key, + (CK_ML_DSA_PARAMETER_SET_TYPE*)data[0], + (int)len[0]); + } + + /* Set key data */ + if (ret == 0 && data[1] != NULL) { + if (object->objClass == CKO_PUBLIC_KEY) { + ret = wc_MlDsaKey_ImportPubRaw(key, data[1], len[1]); + } + else { + ret = wc_MlDsaKey_ImportPrivRaw(key, data[1], len[1]); + } + } + + if (ret != 0) + wc_MlDsaKey_Free(key); + + if (object->onToken) + WP11_Lock_UnlockRW(object->lock); + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ + #ifndef NO_DH /** * Set the DH key data into the object. @@ -8995,6 +9497,155 @@ static int EcObject_GetAttr(WP11_Object* object, CK_ATTRIBUTE_TYPE type, } #endif +#ifdef WOLFPKCS11_MLDSA +static int GetMldsaParams(MlDsaKey* key, byte* data, CK_ULONG* len) +{ + int ret = 0; + CK_ML_DSA_PARAMETER_SET_TYPE params; + + if (len == NULL) + return BUFFER_E; + + switch (key->level) { + case WC_ML_DSA_44: + params = CKP_ML_DSA_44; + break; + case WC_ML_DSA_65: + params = CKP_ML_DSA_65; + break; + case WC_ML_DSA_87: + params = CKP_ML_DSA_87; + break; + default: + return ASN_PARSE_E; + } + + if (data == NULL) + *len = sizeof(CK_ML_DSA_PARAMETER_SET_TYPE); + else if (*len < sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)) + ret = BUFFER_E; + else + XMEMCPY(data, ¶ms, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); + + return ret; +} + +static int GetMldsaPublicKey(MlDsaKey* key, byte* data, CK_ULONG* len) +{ + int ret = 0; + word32 dataLen = 0; + byte level = 0; + + ret = wc_MlDsaKey_GetParams(key, &level); + if (ret != 0) + return ret; + + if (level == WC_ML_DSA_44) + dataLen = ML_DSA_LEVEL2_PUB_KEY_SIZE; + else if (level == WC_ML_DSA_65) + dataLen = ML_DSA_LEVEL3_PUB_KEY_SIZE; + else if (level == WC_ML_DSA_87) + dataLen = ML_DSA_LEVEL5_PUB_KEY_SIZE; + else + return ASN_PARSE_E; + + if (data == NULL) + *len = dataLen; + else if (*len < dataLen) + ret = BUFFER_E; + else { + ret = wc_MlDsaKey_ExportPubRaw(key, data, &dataLen); + if (ret == 0) + *len = dataLen; + } + + return ret; +} + +static int GetMldsaPrivateKey(MlDsaKey* key, byte* data, CK_ULONG* len) +{ + int ret = 0; + word32 dataLen = 0; + byte level = 0; + + ret = wc_MlDsaKey_GetParams(key, &level); + if (ret != 0) + return ret; + + if (level == WC_ML_DSA_44) + dataLen = ML_DSA_LEVEL2_KEY_SIZE; + else if (level == WC_ML_DSA_65) + dataLen = ML_DSA_LEVEL3_KEY_SIZE; + else if (level == WC_ML_DSA_87) + dataLen = ML_DSA_LEVEL5_KEY_SIZE; + else + return ASN_PARSE_E; + + if (data == NULL) + *len = dataLen; + else if (*len < dataLen) + ret = BUFFER_E; + else { + ret = wc_MlDsaKey_ExportPrivRaw(key, data, &dataLen); + if (ret == 0) + *len = dataLen; + } + + return ret; +} + +/** + * Get a ML-DSA object's data as an attribute. + * + * @param object [in] Object object. + * @param type [in] Attribute type. + * @param data [in] Attribute data buffer. + * @param len [in,out] On in, length of attribute data buffer in bytes. + * On out, length of attribute data in bytes. + * @return BUFFER_E when buffer is too small for data. + * NOT_AVAILABLE_E when attribute type is not supported. + * 0 on success. + */ +static int MldsaObject_GetAttr(WP11_Object* object, CK_ATTRIBUTE_TYPE type, + byte* data, CK_ULONG* len) +{ + int ret = 0; + int noPriv = (((object->opFlag & WP11_FLAG_SENSITIVE) != 0) || + ((object->opFlag & WP11_FLAG_EXTRACTABLE) == 0)); + int noPub = 0; + + if (!object->data.mldsaKey->prvKeySet) + noPriv = 1; + if (!object->data.mldsaKey->pubKeySet) + noPub = 1; + + switch (type) { + case CKA_PARAMETER_SET: + ret = GetMldsaParams(object->data.mldsaKey, data, len); + break; + case CKA_VALUE: + if (object->objClass == CKO_PRIVATE_KEY) { + if (noPriv) + *len = CK_UNAVAILABLE_INFORMATION; + else + ret = GetMldsaPrivateKey(object->data.mldsaKey, data, len); + } + else if (object->objClass == CKO_PUBLIC_KEY) { + if (noPub) + *len = CK_UNAVAILABLE_INFORMATION; + else + ret = GetMldsaPublicKey(object->data.mldsaKey, data, len); + } + break; + default: + ret = NOT_AVAILABLE_E; + break; + } + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ + #ifndef NO_DH /** * Get a DH object's data as an attribute. @@ -9378,6 +10029,11 @@ int WP11_Object_GetAttr(WP11_Object* object, CK_ATTRIBUTE_TYPE type, byte* data, ret = EcObject_GetAttr(object, type, data, len); break; #endif +#ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: + ret = MldsaObject_GetAttr(object, type, data, len); + break; +#endif #ifndef NO_DH case CKK_DH: ret = DhObject_GetAttr(object, type, data, len); @@ -9696,6 +10352,9 @@ int WP11_Object_SetAttr(WP11_Object* object, CK_ATTRIBUTE_TYPE type, byte* data, #ifdef HAVE_ECC case CKK_EC: #endif +#ifdef WOLFPKCS11_MLDSA + case CKK_ML_DSA: +#endif #ifndef NO_DH case CKK_DH: #endif @@ -9781,6 +10440,12 @@ int WP11_Object_SetAttr(WP11_Object* object, CK_ATTRIBUTE_TYPE type, byte* data, ret = BAD_FUNC_ARG; } break; + case CKA_PARAMETER_SET: +#ifdef WOLFPKCS11_MLDSA + if (object->type != CKK_ML_DSA) +#endif + ret = BAD_FUNC_ARG; + break; case CKA_WOLFSSL_DEVID: object->devId = (int)(*(CK_ULONG*)data); @@ -11270,6 +11935,176 @@ int WP11_EC_Derive(unsigned char* point, word32 pointLen, unsigned char* key, } #endif /* HAVE_ECC */ +#ifdef WOLFPKCS11_MLDSA +int WP11_Mldsa_GenerateKeyPair(WP11_Object* pub, WP11_Object* priv, + WP11_Slot* slot) +{ + int ret = 0; + byte* pubKey = NULL; + word32 pubKeyLen = 0; + WC_RNG rng; + + /* Both MlDsaKey object inside the pub and priv WP11_Objects are + * already initialized and set to a proper level within + * WP11_Object_SetMldsaKey() based on the given parameter set. */ + + /* Generate into the private key. */ + ret = Rng_New(&slot->token.rng, &slot->token.rngLock, &rng); + if (ret == 0) { + ret = wc_MlDsaKey_MakeKey(priv->data.mldsaKey, &rng); + Rng_Free(&rng); + } + if (ret == 0) { + /* Allocate memory for the public key */ + pubKey = XMALLOC(ML_DSA_LEVEL5_PUB_KEY_SIZE, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pubKey == NULL) { + ret = MEMORY_E; + } + pubKeyLen = ML_DSA_LEVEL5_PUB_KEY_SIZE; + } + if (ret == 0) { + /* Export the public key */ + ret = wc_MlDsaKey_ExportPubRaw(priv->data.mldsaKey, pubKey, &pubKeyLen); + } + if (ret == 0) { + /* Copy the public part into public key. */ + ret = wc_MlDsaKey_ImportPubRaw(pub->data.mldsaKey, pubKey, pubKeyLen); + } + if (ret == 0) { + priv->local = 1; + pub->local = 1; + priv->keyGenMech = CKM_ML_DSA_KEY_PAIR_GEN; + pub->keyGenMech = CKM_ML_DSA_KEY_PAIR_GEN; + } + + if (pubKey != NULL) { + XFREE(pubKey, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + } + + return ret; +} + +/** +* Return the length of a signature in bytes. +* +* @param key [in] ML-DSA key object. +* @return Length of ML-DSA signature in bytes. +*/ +int WP11_Mldsa_SigLen(WP11_Object* key) +{ + int len = 0; + + if (wc_MlDsaKey_GetSigLen(key->data.mldsaKey, &len) != 0) + len = 0; + + return len; +} + +/** +* ML-DSA sign data with private key. +* +* @param data [in] Data to sign (message or hash). +* @param dataLen [in] Length of data in bytes. +* @param sig [in] Buffer to hold signature data. +* @param sigLen [in] Length of buffer in bytes. +* @param sigLen [in,out] On in, length of buffer. +* On out, length data in buffer. +* @param priv [in] Private key object. +* @param session [in] Session object holding parameters. +* @return BUFFER_E when sigLen is too small. +* Other -ve when signing fails. +* 0 on success. +*/ +int WP11_Mldsa_Sign(unsigned char* data, word32 dataLen, unsigned char* sig, + word32* sigLen, WP11_Object* priv, WP11_Session* session) +{ + int ret = 0; + WP11_Slot* slot = WP11_Session_GetSlot(session); + WP11_MldsaParams* params = &session->params.mldsa; + WC_RNG rng; + + if (priv->onToken) + WP11_Lock_LockRO(priv->lock); + + ret = Rng_New(&slot->token.rng, &slot->token.rngLock, &rng); + if (ret == 0) { + if (params->preHashType == WC_HASH_TYPE_NONE) { + ret = wc_MlDsaKey_SignCtx(priv->data.mldsaKey, params->ctx, + params->ctxSz, sig, sigLen, data, + dataLen, &rng); + } + else { + ret = wc_dilithium_sign_ctx_hash(params->ctx, params->ctxSz, + params->preHashType, data, dataLen, + sig, sigLen, priv->data.mldsaKey, + &rng); + } + Rng_Free(&rng); + } + + XFREE(params->ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + params->ctx = NULL; + params->ctxSz = 0; + + if (priv->onToken) + WP11_Lock_UnlockRO(priv->lock); + + return ret; +} + +/** +* ML-DSA verify signature for data with public key. +* +* @param sig [in] Signature data. +* @param sigLen [in] Length of buffer in bytes. +* @param data [in] Data to verify. +* @param dataLen [in] Length of data in bytes. +* @param pub [in] Public key object. +* @param stat [out] Status of verification. 1 on success, otherwise 0. +* @param pub [in] Public key object. +* @param session [in] Session object holding parameters. +* @return -ve when verifying fails. +* 0 on success. +*/ +int WP11_Mldsa_Verify(unsigned char* sig, word32 sigLen, unsigned char* data, + word32 dataLen, int* stat, WP11_Object* pub, + WP11_Session* session) +{ + int ret = 0; + WP11_MldsaParams* params = &session->params.mldsa; + + *stat = 0; + if (pub->onToken) + WP11_Lock_LockRO(pub->lock); + + if (sigLen != (word32)WP11_Mldsa_SigLen(pub)) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (params->preHashType == WC_HASH_TYPE_NONE) { + ret = wc_dilithium_verify_ctx_msg(sig, sigLen, params->ctx, + params->ctxSz, data, dataLen, + stat, pub->data.mldsaKey); + } + else { + ret = wc_dilithium_verify_ctx_hash(sig, sigLen, params->ctx, + params->ctxSz, params->preHashType, data, dataLen, stat, + pub->data.mldsaKey); + } + } + + XFREE(params->ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + params->ctx = NULL; + params->ctxSz = 0; + + if (pub->onToken) + WP11_Lock_UnlockRO(pub->lock); + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ + #if defined(WOLFPKCS11_HKDF) || !defined(NO_AES) /** * Generate a secret key. diff --git a/src/slot.c b/src/slot.c index e013d6ce..5cf07023 100644 --- a/src/slot.c +++ b/src/slot.c @@ -364,6 +364,11 @@ static CK_MECHANISM_TYPE mechanismList[] = { #endif CKM_ECDH1_DERIVE, #endif +#ifdef WOLFPKCS11_MLDSA + CKM_ML_DSA_KEY_PAIR_GEN, + CKM_ML_DSA, + CKM_HASH_ML_DSA, +#endif #ifdef WOLFPKCS11_HKDF CKM_HKDF_DERIVE, CKM_HKDF_DATA, @@ -619,6 +624,20 @@ static CK_MECHANISM_INFO ecdhMechInfo = { 256, 521, CKF_DERIVE }; #endif +#ifdef WOLFPKCS11_MLDSA +/* Info on ML-DSA key generation mechanism. */ +static CK_MECHANISM_INFO mldsaKgMechInfo = { + ML_DSA_LEVEL2_PUB_KEY_SIZE, + ML_DSA_LEVEL5_PUB_KEY_SIZE, + CKF_GENERATE_KEY_PAIR +}; +/* Info on ML-DSA mechanism (also for pre-hash variant). */ +static CK_MECHANISM_INFO mldsaMechInfo = { + ML_DSA_LEVEL2_PUB_KEY_SIZE, + ML_DSA_LEVEL5_PUB_KEY_SIZE, + CKF_SIGN | CKF_VERIFY +}; +#endif #ifdef WOLFPKCS11_HKDF static CK_MECHANISM_INFO hkdfMechInfo = { 1, 16320, CKF_DERIVE @@ -958,6 +977,15 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, XMEMCPY(pInfo, &ecdhMechInfo, sizeof(CK_MECHANISM_INFO)); break; #endif +#ifdef WOLFPKCS11_MLDSA + case CKM_ML_DSA_KEY_PAIR_GEN: + XMEMCPY(pInfo, &mldsaKgMechInfo, sizeof(CK_MECHANISM_INFO)); + break; + case CKM_HASH_ML_DSA: + case CKM_ML_DSA: + XMEMCPY(pInfo, &mldsaMechInfo, sizeof(CK_MECHANISM_INFO)); + break; +#endif #ifdef WOLFPKCS11_HKDF case CKM_HKDF_DERIVE: XMEMCPY(pInfo, &hkdfMechInfo, sizeof(CK_MECHANISM_INFO)); diff --git a/tests/pkcs11v3test.c b/tests/pkcs11v3test.c index febb9ef4..58a145cf 100644 --- a/tests/pkcs11v3test.c +++ b/tests/pkcs11v3test.c @@ -83,6 +83,757 @@ static int soPinLen = 14; static byte* userPin = (byte*)"wolfpkcs11-test"; static int userPinLen; +#ifdef WOLFPKCS11_PKCS11_V3_2 +#ifdef WOLFPKCS11_MLDSA + +static CK_BBOOL ckTrue = CK_TRUE; +static CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY; +static CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY; +static CK_KEY_TYPE mldsaKeyType = CKK_ML_DSA; + +static CK_RV gen_mldsa_keys(CK_SESSION_HANDLE session, + CK_ML_DSA_PARAMETER_SET_TYPE paramSet, + CK_OBJECT_HANDLE* pubKey, CK_OBJECT_HANDLE* privKey, + unsigned char* privId, int privIdLen, + unsigned char* pubId, int pubIdLen, int onToken) +{ + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + CK_MECHANISM mech; + CK_BBOOL token = (CK_BBOOL)onToken; + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_PARAMETER_SET, ¶mSet, sizeof(paramSet) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &token, sizeof(token) }, + { CKA_ID, pubId, pubIdLen }, + }; + CK_ULONG pubTmplCnt = sizeof(pubKeyTmpl) / sizeof(*pubKeyTmpl); + CK_ATTRIBUTE privKeyTmpl[] = { + { CKA_PARAMETER_SET, ¶mSet, sizeof(paramSet) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &token, sizeof(token) }, + { CKA_ID, privId, privIdLen }, + }; + CK_ULONG privTmplCnt = sizeof(privKeyTmpl) / sizeof(*privKeyTmpl); + + if (pubId == NULL) + pubTmplCnt--; + if (privId == NULL) + privTmplCnt--; + + mech.mechanism = CKM_ML_DSA_KEY_PAIR_GEN; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + ret = funcList->C_GenerateKeyPair(session, &mech, pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, &pub, &priv); + CHECK_CKR(ret, "ML-DSA Key Generation"); + if (ret == CKR_OK && pubKey != NULL) + *pubKey = pub; + if (ret == CKR_OK && privKey != NULL) + *privKey = priv; + + if (ret == CKR_OK) { + byte bad = 0; + + mech.pParameter = &bad; + ret = funcList->C_GenerateKeyPair(session, &mech, pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, &pub, &priv); + CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID, + "ML-DSA Key Generation bad parameter"); + mech.pParameter = NULL; + } + if (ret == CKR_OK) { + mech.ulParameterLen = 1; + ret = funcList->C_GenerateKeyPair(session, &mech, pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, &pub, &priv); + CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID, + "ML-DSA Key Generation bad parameter length"); + } + + return ret; +} + +static CK_RV find_mldsa_key(CK_SESSION_HANDLE session, CK_OBJECT_CLASS objClass, + CK_OBJECT_HANDLE* key, unsigned char* id, int idLen) +{ + CK_RV ret = CKR_OK; + CK_ULONG count = 0; + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &objClass, sizeof(objClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_ID, id, idLen }, + }; + + ret = funcList->C_FindObjectsInit(session, tmpl, sizeof(tmpl)/sizeof(*tmpl)); + CHECK_CKR(ret, "ML-DSA Find Objects Init"); + if (ret == CKR_OK) { + ret = funcList->C_FindObjects(session, key, 1, &count); + CHECK_CKR(ret, "ML-DSA Find Objects"); + } + if (ret == CKR_OK) { + ret = funcList->C_FindObjectsFinal(session); + CHECK_CKR(ret, "ML-DSA Find Objects Final"); + } + if (ret == CKR_OK) { + CHECK_COND(count == 1, ret, "ML-DSA Find Objects count"); + } + + return ret; +} + +static CK_RV find_mldsa_priv_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE* key, + unsigned char* id, int idLen) +{ + return find_mldsa_key(session, privKeyClass, key, id, idLen); +} + +static CK_RV find_mldsa_pub_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE* key, + unsigned char* id, int idLen) +{ + return find_mldsa_key(session, pubKeyClass, key, id, idLen); +} + +static CK_RV import_mldsa_priv_key(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE* obj) +{ + CK_RV ret; + CK_ML_DSA_PARAMETER_SET_TYPE paramSet = CKP_ML_DSA_44; + static unsigned char mldsa_44_priv[] = { + 0x6b, 0x34, 0xfb, 0xdf, 0x6c, 0x26, 0xdb, 0xdb, 0xdc, 0x9a, 0x4b, 0xc3, + 0xe3, 0x13, 0x1d, 0xc8, 0x76, 0x9e, 0xbc, 0x91, 0x19, 0xce, 0x4e, 0xc6, + 0x70, 0x1b, 0xf8, 0xab, 0x3f, 0x28, 0x7d, 0x7c, 0x8c, 0xfc, 0xc6, 0xc5, + 0x45, 0xbc, 0x3a, 0x70, 0xfe, 0xab, 0x30, 0x92, 0x71, 0xe2, 0x07, 0x56, + 0xa8, 0x55, 0xe6, 0x74, 0x45, 0xa7, 0xa0, 0x1a, 0x7d, 0x53, 0x6c, 0x8f, + 0x98, 0xac, 0x02, 0x38, 0xdf, 0xfa, 0x27, 0x91, 0x63, 0x20, 0xd7, 0x23, + 0x2d, 0x35, 0x81, 0x75, 0x1e, 0x78, 0x46, 0xf1, 0xab, 0x27, 0x62, 0xee, + 0x18, 0x41, 0x24, 0xd2, 0x7c, 0x8d, 0x4c, 0xe8, 0xa7, 0x88, 0xf5, 0x9d, + 0x1e, 0xa8, 0x57, 0x47, 0x60, 0xa8, 0x16, 0x2d, 0x35, 0xaa, 0x51, 0x30, + 0x63, 0x6b, 0xa9, 0xfb, 0xb3, 0x24, 0x5d, 0xda, 0x14, 0x3c, 0x9f, 0x5c, + 0xdd, 0x7a, 0xf0, 0x0e, 0xc4, 0xad, 0x17, 0xbe, 0x42, 0x94, 0x29, 0x9c, + 0x42, 0x60, 0x44, 0x82, 0x61, 0xdc, 0x06, 0x2d, 0x50, 0x28, 0x09, 0x1a, + 0x12, 0x41, 0x0a, 0x87, 0x64, 0x01, 0x24, 0x28, 0x8c, 0x18, 0x70, 0xe0, + 0x10, 0x12, 0x53, 0x20, 0x26, 0x10, 0xc9, 0x64, 0x83, 0xa8, 0x70, 0x24, + 0x29, 0x06, 0x12, 0x38, 0x05, 0xc9, 0x14, 0x62, 0x10, 0x17, 0x4e, 0x24, + 0x24, 0x6e, 0xc4, 0x42, 0x0e, 0x01, 0x17, 0x70, 0xc8, 0x28, 0x60, 0x48, + 0x90, 0x65, 0xc8, 0x98, 0x45, 0x9b, 0x18, 0x81, 0x44, 0x92, 0x00, 0x0a, + 0xa8, 0x00, 0xd4, 0x84, 0x25, 0x12, 0x17, 0x8a, 0x94, 0x32, 0x32, 0x01, + 0x27, 0x06, 0x02, 0x13, 0x4c, 0x12, 0x98, 0x85, 0x22, 0x42, 0x0c, 0x1a, + 0x81, 0x51, 0x12, 0x14, 0x49, 0x00, 0x23, 0x00, 0xe4, 0x30, 0x48, 0x49, + 0x34, 0x48, 0x18, 0x26, 0x49, 0x98, 0x40, 0x51, 0x43, 0xa4, 0x61, 0x83, + 0x06, 0x80, 0xc2, 0x88, 0x44, 0x02, 0x95, 0x31, 0xe0, 0x10, 0x8d, 0x51, + 0x18, 0x50, 0xdc, 0xa0, 0x44, 0x23, 0x00, 0x31, 0x82, 0xc6, 0x91, 0x52, + 0xb6, 0x60, 0x11, 0x29, 0x51, 0xd2, 0xc0, 0x09, 0x20, 0xb3, 0x4c, 0xd4, + 0xc0, 0x61, 0x90, 0xc2, 0x4d, 0x4c, 0x12, 0x70, 0xe0, 0x38, 0x71, 0x14, + 0x33, 0x46, 0xc1, 0xa6, 0x0d, 0x19, 0x13, 0x60, 0xa2, 0x26, 0x01, 0x98, + 0x90, 0x0c, 0x12, 0x16, 0x12, 0x00, 0xc5, 0x65, 0x82, 0x98, 0x91, 0xcc, + 0x42, 0x0e, 0x09, 0xa5, 0x28, 0xdb, 0x00, 0x61, 0x60, 0xb4, 0x31, 0x49, + 0x92, 0x85, 0x8c, 0x82, 0x71, 0xdb, 0xa2, 0x05, 0x02, 0x27, 0x64, 0x18, + 0x94, 0x8c, 0x9a, 0x18, 0x0e, 0xa0, 0x96, 0x48, 0xe4, 0xb2, 0x20, 0x82, + 0x42, 0x86, 0x62, 0x44, 0x84, 0xc8, 0x40, 0x4d, 0x90, 0xb2, 0x4c, 0x82, + 0x08, 0x70, 0xcc, 0xa0, 0x85, 0x54, 0x14, 0x32, 0xda, 0x28, 0x45, 0x9c, + 0x30, 0x2d, 0xc3, 0x26, 0x6e, 0x03, 0x12, 0x01, 0x4a, 0x28, 0x11, 0x44, + 0x14, 0x48, 0x18, 0x06, 0x22, 0x63, 0x96, 0x04, 0x04, 0xa2, 0x31, 0x18, + 0x28, 0x2d, 0x88, 0x40, 0x01, 0x89, 0x30, 0x2d, 0x60, 0xa8, 0x65, 0x10, + 0x96, 0x2d, 0xcc, 0x44, 0x80, 0xcb, 0x48, 0x25, 0xa2, 0xc0, 0x0d, 0x23, + 0x02, 0x2c, 0x01, 0x12, 0x12, 0x20, 0xb2, 0x49, 0x08, 0x30, 0x82, 0x20, + 0x46, 0x08, 0xd1, 0x20, 0x4d, 0x18, 0x07, 0x31, 0x09, 0x97, 0x10, 0xd8, + 0x34, 0x8e, 0x0c, 0x41, 0x30, 0x80, 0x42, 0x2d, 0x9c, 0x14, 0x65, 0x9a, + 0x10, 0x2c, 0x43, 0x30, 0x29, 0x04, 0x86, 0x09, 0xca, 0xc8, 0x84, 0x22, + 0x06, 0x6e, 0x10, 0x13, 0x40, 0x19, 0x03, 0x21, 0x81, 0x48, 0x61, 0xcc, + 0xb6, 0x81, 0x04, 0x19, 0x4d, 0x61, 0x38, 0x31, 0xd1, 0x00, 0x0d, 0xe2, + 0x34, 0x60, 0x11, 0xb0, 0x0c, 0x12, 0xb1, 0x44, 0x1a, 0x27, 0x12, 0x8a, + 0x48, 0x82, 0x58, 0x34, 0x72, 0x0a, 0x05, 0x6d, 0x59, 0x48, 0x31, 0x23, + 0x03, 0x12, 0x1b, 0xb0, 0x10, 0x1a, 0x21, 0x92, 0x92, 0x86, 0x44, 0x20, + 0x24, 0x12, 0x59, 0x98, 0x40, 0x1c, 0x88, 0x08, 0x50, 0xc6, 0x41, 0x13, + 0xa2, 0x24, 0x19, 0x49, 0x10, 0x63, 0x06, 0x49, 0x12, 0x33, 0x6c, 0x94, + 0x88, 0x20, 0x11, 0x08, 0x68, 0x0b, 0xc8, 0x50, 0x49, 0xc2, 0x69, 0x01, + 0x16, 0x62, 0x8c, 0x20, 0x84, 0x03, 0x87, 0x91, 0x82, 0x24, 0x31, 0x43, + 0x86, 0x70, 0x22, 0x43, 0x29, 0x62, 0x44, 0x64, 0x08, 0xa3, 0x45, 0xc9, + 0x32, 0x88, 0x4c, 0x22, 0x04, 0xc9, 0xc0, 0x30, 0x9c, 0x26, 0x81, 0x1b, + 0x41, 0x22, 0xa4, 0x24, 0x4a, 0x8b, 0x08, 0x0a, 0x1a, 0xc6, 0x84, 0x82, + 0x48, 0x32, 0x1a, 0x05, 0x4d, 0x44, 0x16, 0x08, 0xe3, 0x38, 0x0a, 0x12, + 0xc7, 0x31, 0x5c, 0x16, 0x0c, 0x14, 0x06, 0x0a, 0x01, 0xb2, 0x91, 0x80, + 0x84, 0x4d, 0x1a, 0xa8, 0x01, 0x93, 0xc0, 0x2d, 0x11, 0x04, 0x0a, 0x18, + 0x14, 0x31, 0x02, 0xc6, 0x6c, 0x62, 0xc6, 0x61, 0x61, 0xb0, 0x64, 0x21, + 0xb1, 0x45, 0x52, 0xc6, 0x2d, 0x1c, 0x06, 0x48, 0x0c, 0x42, 0x71, 0x5a, + 0x42, 0x41, 0xcc, 0xc6, 0x31, 0x22, 0x24, 0x05, 0x50, 0x44, 0x64, 0x9b, + 0xc0, 0x89, 0x01, 0x48, 0x91, 0x43, 0x38, 0x46, 0x24, 0x37, 0x26, 0xd8, + 0x26, 0x28, 0xd8, 0x04, 0x71, 0x0c, 0x06, 0x10, 0xc2, 0x98, 0x61, 0x62, + 0xa4, 0x4d, 0x03, 0xb9, 0x88, 0x20, 0xa5, 0x80, 0x23, 0x37, 0x8d, 0x1c, + 0x24, 0x50, 0xc3, 0x40, 0x4a, 0x5a, 0x96, 0x49, 0x90, 0xc0, 0x48, 0xd1, + 0xa2, 0x85, 0xd0, 0x08, 0x2a, 0xd8, 0x94, 0x49, 0x82, 0x44, 0x85, 0x02, + 0x15, 0x90, 0x03, 0xa4, 0x81, 0x4c, 0x96, 0x40, 0x82, 0x10, 0x8c, 0x11, + 0x29, 0x44, 0xa1, 0x94, 0x80, 0x13, 0xa9, 0x08, 0x64, 0x06, 0x8d, 0x8b, + 0xa8, 0x29, 0x19, 0x23, 0x40, 0x9b, 0x16, 0x26, 0x0a, 0x03, 0x92, 0x04, + 0x18, 0x8d, 0xd8, 0x30, 0x52, 0x98, 0x24, 0x72, 0xdc, 0x30, 0x04, 0x18, + 0x19, 0x91, 0x18, 0x11, 0x31, 0x13, 0xb6, 0x29, 0xc9, 0xb4, 0x69, 0x04, + 0x13, 0x2a, 0x13, 0x02, 0x4e, 0xdc, 0x26, 0x6d, 0x5b, 0xb0, 0x2c, 0x1b, + 0x44, 0x72, 0x92, 0x90, 0x44, 0x19, 0x10, 0x50, 0x44, 0x08, 0x66, 0x60, + 0x84, 0x85, 0x12, 0xc4, 0x09, 0x63, 0x24, 0x50, 0x14, 0x07, 0x72, 0x04, + 0x91, 0x25, 0xc4, 0x94, 0x61, 0x5b, 0x92, 0x69, 0x12, 0x94, 0x48, 0x12, + 0x16, 0x91, 0xc4, 0x24, 0x4d, 0x14, 0xa1, 0x6c, 0x91, 0x14, 0x6c, 0x23, + 0xc4, 0x4c, 0x94, 0xa4, 0x8d, 0xc1, 0x12, 0x04, 0x88, 0x46, 0x10, 0xca, + 0x90, 0x50, 0x4a, 0xb0, 0x49, 0x4c, 0x26, 0x01, 0x4c, 0xfe, 0xba, 0xe8, + 0x06, 0x78, 0x3c, 0x7f, 0x05, 0x16, 0x52, 0xb2, 0x50, 0x0d, 0xf0, 0xb3, + 0x1d, 0xec, 0x06, 0x5e, 0x36, 0x0d, 0x32, 0x52, 0x5c, 0x81, 0xab, 0x5f, + 0xd0, 0x33, 0x8f, 0x48, 0x9a, 0xe1, 0x8e, 0xcc, 0xcd, 0xa0, 0x9c, 0x0a, + 0x8e, 0x17, 0x39, 0x30, 0x24, 0x02, 0xcc, 0x01, 0xbb, 0x2a, 0x1c, 0xbd, + 0xb1, 0x79, 0xba, 0xfb, 0xe8, 0x1b, 0x6a, 0xd2, 0xe5, 0xbf, 0x21, 0x63, + 0x62, 0x11, 0x63, 0xbb, 0x66, 0x99, 0x47, 0xd5, 0x73, 0x88, 0x00, 0x9d, + 0x71, 0xdb, 0x40, 0xfe, 0x2d, 0x70, 0x37, 0xb6, 0xd2, 0x81, 0x29, 0x5f, + 0x5f, 0x6f, 0x51, 0x68, 0x28, 0x44, 0xda, 0xcc, 0x6f, 0xa4, 0xa1, 0xab, + 0xb1, 0xa8, 0xbb, 0x1a, 0x9f, 0x20, 0x75, 0x5a, 0x84, 0x20, 0x82, 0x45, + 0xa1, 0xd6, 0xf9, 0xaa, 0xbe, 0x04, 0xcd, 0x13, 0x13, 0x38, 0xa7, 0x95, + 0x5a, 0x20, 0x3e, 0xd2, 0x9a, 0x96, 0x51, 0x85, 0x41, 0x05, 0xb0, 0x94, + 0x6f, 0xa9, 0x54, 0xb9, 0x0b, 0xac, 0xd1, 0x5f, 0xc8, 0x33, 0xcb, 0xc6, + 0x04, 0x81, 0xa1, 0x22, 0x62, 0x05, 0xeb, 0x02, 0x5f, 0x40, 0x0d, 0x3a, + 0xaa, 0xfa, 0x08, 0x5e, 0x7b, 0xff, 0xfb, 0x3d, 0xf7, 0x14, 0xa4, 0xd7, + 0x18, 0x03, 0x63, 0x4f, 0xfc, 0x99, 0x4d, 0xa1, 0xed, 0x32, 0x6f, 0xd4, + 0x0e, 0x27, 0x53, 0x31, 0x7e, 0x86, 0x35, 0x7b, 0x13, 0xa8, 0x26, 0xa2, + 0x52, 0x9d, 0xca, 0x96, 0xb4, 0x7d, 0x22, 0xcf, 0x37, 0x4d, 0xd6, 0x2a, + 0x47, 0x48, 0xaf, 0x35, 0x7b, 0x43, 0x2f, 0xac, 0x19, 0xe4, 0x31, 0xd4, + 0x93, 0xdb, 0x78, 0x0b, 0x60, 0xb1, 0x83, 0x4a, 0xb6, 0x0b, 0x79, 0x71, + 0xef, 0x88, 0xec, 0x2b, 0x76, 0xcc, 0x49, 0xb9, 0x40, 0x18, 0x32, 0xe7, + 0x7d, 0xfd, 0x64, 0x52, 0x39, 0x5d, 0xc0, 0x05, 0xa3, 0xff, 0xe4, 0x06, + 0x1e, 0xe3, 0x00, 0x3d, 0x4b, 0x0c, 0xa5, 0x06, 0x59, 0xf3, 0xc9, 0x46, + 0x18, 0x2b, 0xb2, 0x2b, 0x74, 0xce, 0x2b, 0xa7, 0xb7, 0xb9, 0x1b, 0x25, + 0xf0, 0xc0, 0xed, 0x2d, 0x20, 0xd8, 0xb0, 0x92, 0x9b, 0x54, 0x6f, 0x3f, + 0xb8, 0xb5, 0x5e, 0x40, 0x20, 0x24, 0xe1, 0x73, 0xb4, 0x0b, 0x44, 0x84, + 0x17, 0xf4, 0x3c, 0x37, 0x00, 0xf9, 0xa0, 0x1b, 0x36, 0x57, 0x71, 0x23, + 0x4e, 0x66, 0xbb, 0xd5, 0x9c, 0xdc, 0xa6, 0x01, 0xe5, 0x37, 0x46, 0xf9, + 0xdc, 0xe4, 0x37, 0x56, 0x27, 0x41, 0x06, 0x71, 0x90, 0x2c, 0xd2, 0xca, + 0xde, 0xc9, 0x4f, 0x4f, 0xa2, 0xf1, 0x3b, 0xca, 0xf1, 0x00, 0x32, 0x93, + 0x40, 0x8c, 0x7c, 0x6f, 0x24, 0xeb, 0xd0, 0x3d, 0xa7, 0x61, 0xa3, 0xe7, + 0x38, 0x38, 0xc9, 0x1f, 0x3f, 0xf3, 0x70, 0xfd, 0xe8, 0xb2, 0xac, 0xfe, + 0xc2, 0xc6, 0xc9, 0x39, 0xb5, 0xb9, 0x99, 0x1d, 0x47, 0x33, 0xaa, 0xd4, + 0x74, 0xea, 0x39, 0x34, 0xd7, 0xb0, 0xb7, 0xc6, 0x62, 0xdd, 0x32, 0xa0, + 0xae, 0xd4, 0xf3, 0x6e, 0x3f, 0x04, 0x5a, 0x96, 0x17, 0x18, 0x4b, 0xac, + 0x85, 0xa7, 0xac, 0xe2, 0x3a, 0xa8, 0x5e, 0x24, 0xbd, 0x2c, 0xae, 0xe7, + 0x83, 0xe6, 0xec, 0x3e, 0x8e, 0x02, 0xb7, 0x7b, 0xca, 0x97, 0x37, 0xca, + 0xfc, 0x81, 0x61, 0xaa, 0x3b, 0x1e, 0xaf, 0xf0, 0x4e, 0x8d, 0xa5, 0xa2, + 0x3e, 0x9c, 0x8c, 0x99, 0x4e, 0x70, 0x59, 0x6c, 0x2e, 0x79, 0xb0, 0xa3, + 0x28, 0xaa, 0x08, 0x8a, 0xb7, 0x3f, 0x91, 0xba, 0xab, 0xe1, 0xfd, 0x71, + 0x8b, 0x2f, 0x96, 0x89, 0x2a, 0x21, 0xfa, 0x2f, 0xa0, 0x6a, 0x8c, 0xd5, + 0x0f, 0x1f, 0x56, 0x4d, 0x57, 0x08, 0x3e, 0x09, 0xb0, 0x38, 0x9c, 0x77, + 0xc5, 0x83, 0xfc, 0x33, 0x47, 0xfb, 0x23, 0x1f, 0xdb, 0xa6, 0xbe, 0x54, + 0x00, 0x00, 0x9c, 0xa9, 0xff, 0xfd, 0xf6, 0xc7, 0x17, 0x34, 0x0b, 0x89, + 0x0e, 0x9c, 0x6b, 0x31, 0x70, 0x8a, 0x1e, 0x7f, 0xcb, 0xd0, 0x52, 0x1d, + 0x1f, 0x58, 0x0a, 0x82, 0xbc, 0xe2, 0x63, 0x66, 0xb1, 0xde, 0x2d, 0x68, + 0x2a, 0x33, 0xbb, 0x05, 0xd2, 0xb6, 0xae, 0x02, 0x78, 0x7a, 0x38, 0x6f, + 0xdc, 0x27, 0x18, 0x6f, 0x19, 0xf8, 0xbf, 0xff, 0xa9, 0xda, 0x62, 0xee, + 0xed, 0xe3, 0xb5, 0x7a, 0x5d, 0x52, 0x8a, 0x3c, 0x5c, 0x12, 0x29, 0xf3, + 0xc4, 0x5d, 0xb1, 0x50, 0xc3, 0x85, 0xa8, 0xfa, 0x98, 0x37, 0x17, 0x6d, + 0x7a, 0x4c, 0x49, 0x02, 0xd1, 0x87, 0x26, 0x21, 0x31, 0x1b, 0xea, 0xb5, + 0xb4, 0x6c, 0x3f, 0x1b, 0x9a, 0x6e, 0xe9, 0x6a, 0x34, 0x17, 0x2a, 0x3c, + 0xeb, 0x06, 0x53, 0x54, 0xb0, 0x27, 0xf8, 0x79, 0x18, 0x17, 0x26, 0xa1, + 0xba, 0x9c, 0xd5, 0xa4, 0x81, 0x65, 0x94, 0xda, 0x0c, 0xc5, 0x84, 0xb3, + 0x61, 0x52, 0x18, 0x32, 0x71, 0x67, 0x65, 0xaa, 0xfc, 0x48, 0xd6, 0x74, + 0x55, 0xf2, 0xab, 0xbd, 0x08, 0x18, 0xb4, 0x86, 0xc3, 0xaa, 0x85, 0xc6, + 0x69, 0x19, 0xe7, 0x47, 0x67, 0x6a, 0xde, 0xf0, 0x50, 0x51, 0x86, 0x18, + 0x48, 0xf3, 0x35, 0x31, 0x0f, 0x32, 0xdf, 0xe2, 0x50, 0x48, 0xd7, 0x73, + 0x4d, 0x75, 0x82, 0xd2, 0x87, 0x29, 0xe4, 0x63, 0xcf, 0x4f, 0xa2, 0x81, + 0x56, 0x35, 0x5b, 0x1a, 0x25, 0x00, 0x7c, 0x9d, 0x36, 0x89, 0xcc, 0x4e, + 0xd6, 0x16, 0xc3, 0xd4, 0xe5, 0x58, 0x60, 0x2b, 0xe2, 0xc7, 0x0b, 0xf1, + 0xf4, 0x00, 0xe5, 0xab, 0x8b, 0x6d, 0x0e, 0x1d, 0xf0, 0xeb, 0x56, 0x20, + 0x56, 0xf2, 0x11, 0x79, 0x42, 0x6c, 0xb3, 0xb3, 0x28, 0xc1, 0xad, 0xb8, + 0x19, 0xb3, 0xa1, 0xfa, 0xda, 0xcc, 0xe3, 0xf4, 0x54, 0xc6, 0x13, 0x69, + 0x7a, 0x72, 0x26, 0xaa, 0xf5, 0x65, 0x63, 0xb2, 0x8e, 0xff, 0x8d, 0x4a, + 0x56, 0x77, 0x84, 0x2e, 0x6e, 0x3d, 0xfe, 0x0f, 0x79, 0x1d, 0x1a, 0x77, + 0xfe, 0xd4, 0x30, 0x4e, 0x81, 0x0b, 0x95, 0x14, 0x86, 0xa3, 0xab, 0x82, + 0xd1, 0x36, 0x53, 0x1a, 0x83, 0x37, 0xb8, 0x0f, 0x17, 0x1b, 0x82, 0x3f, + 0x50, 0x07, 0x30, 0xe4, 0xef, 0x2d, 0xf1, 0x11, 0x2a, 0x0e, 0xc9, 0x2e, + 0x5d, 0x8c, 0x49, 0xae, 0x1d, 0xc1, 0x92, 0x65, 0xa8, 0x7d, 0xed, 0x37, + 0x12, 0x0c, 0x73, 0xaf, 0xfb, 0xd5, 0xc1, 0x93, 0x1e, 0x07, 0x17, 0x92, + 0xb7, 0x7d, 0x06, 0x10, 0x4e, 0x32, 0x32, 0x68, 0x40, 0x53, 0x7e, 0xed, + 0x8d, 0x3b, 0x2a, 0x2b, 0x83, 0x1f, 0x20, 0x24, 0x9c, 0x2a, 0x4b, 0x36, + 0x53, 0x56, 0x9d, 0xef, 0x9c, 0x0c, 0x85, 0xfa, 0xae, 0x06, 0x59, 0xb4, + 0xf4, 0x7b, 0xc4, 0x25, 0xb1, 0xf5, 0x09, 0x68, 0x8f, 0x72, 0xf4, 0xc8, + 0xd1, 0x43, 0x51, 0x1b, 0x82, 0x41, 0x7f, 0x67, 0xdb, 0x69, 0x0b, 0x9f, + 0xaf, 0xa8, 0x20, 0xb9, 0xe4, 0xb8, 0x35, 0x76, 0x05, 0xa1, 0xe0, 0x1c, + 0x84, 0xc8, 0x6d, 0x31, 0x74, 0x1b, 0x48, 0x20, 0x0d, 0xcb, 0x5a, 0x54, + 0xc7, 0x29, 0x8e, 0x4d, 0xf1, 0xeb, 0xac, 0x18, 0x31, 0x15, 0x45, 0xd1, + 0x9e, 0xc7, 0xaf, 0x94, 0x18, 0xa2, 0x45, 0x7b, 0x77, 0x28, 0x12, 0x23, + 0x58, 0x11, 0xa7, 0xf6, 0x16, 0x82, 0x78, 0x22, 0xe5, 0x4c, 0x3d, 0x69, + 0x45, 0x01, 0x29, 0x7a, 0xa4, 0xac, 0xc5, 0x01, 0x95, 0x75, 0xbe, 0xee, + 0xc4, 0x33, 0xe8, 0x33, 0x64, 0x81, 0xa3, 0xe5, 0x96, 0x0b, 0x14, 0x5c, + 0x79, 0x7b, 0x13, 0x89, 0x41, 0x27, 0x03, 0xbf, 0xcf, 0x1f, 0x2e, 0x2b, + 0x5b, 0xa1, 0xaf, 0xa9, 0x1f, 0xb8, 0x3b, 0x7a, 0xb5, 0xc9, 0xe8, 0x88, + 0x0a, 0x0e, 0xad, 0x23, 0x4d, 0xc8, 0x18, 0x8d, 0xeb, 0x34, 0x76, 0xb8, + 0xeb, 0x83, 0x67, 0x67, 0xba, 0xf5, 0x1d, 0xd1, 0xc7, 0x7b, 0xe0, 0xaf, + 0x8c, 0x69, 0x86, 0xaf, 0x17, 0xb8, 0xab, 0xd4, 0xcc, 0x2e, 0x48, 0x4c, + 0x4e, 0x21, 0xc1, 0x9c, 0x7c, 0x2c, 0xbb, 0x7a, 0x46, 0x1d, 0xd2, 0x99, + 0x8b, 0xb2, 0x8e, 0x54, 0x7a, 0x86, 0x3f, 0x67, 0xff, 0x8a, 0x63, 0xb6, + 0xbe, 0x32, 0x8c, 0x06, 0x42, 0xc4, 0x2f, 0x4f, 0x15, 0xc8, 0x87, 0x8e, + 0x99, 0x78, 0xcc, 0x44, 0x86, 0x99, 0x12, 0x5c, 0xb9, 0xee, 0xba, 0x0c, + 0xe1, 0xee, 0x0e, 0x69, 0x51, 0x06, 0x3a, 0x50, 0xa1, 0x62, 0x03, 0x53, + 0x54, 0xe4, 0x1a, 0x2d, 0x20, 0x10, 0xd1, 0xa3, 0x88, 0xb6, 0xb2, 0x3f, + 0x1e, 0xaa, 0xd2, 0xb1, 0xdc, 0xd2, 0x13, 0x09, 0xce, 0xa7, 0x10, 0x35, + 0x02, 0x40, 0xd5, 0x2e, 0x67, 0x8e, 0xd2, 0x7a, 0xd6, 0x59, 0x5c, 0x6f, + 0xf2, 0xb3, 0xad, 0x75, 0x8b, 0x81, 0x7e, 0xd0, 0xd2, 0xb8, 0x9b, 0x16, + 0x6c, 0x68, 0x06, 0x29, 0x6a, 0xc2, 0xdf, 0x7c, 0x4e, 0x57, 0xa5, 0x24, + 0x8d, 0x45, 0x0c, 0x9f, 0x3d, 0x56, 0xf5, 0xef, 0x66, 0x60, 0x83, 0xbe, + 0x6e, 0xaa, 0xa6, 0xe6, 0x9f, 0xd5, 0xba, 0xb4, 0x10, 0x9f, 0xbc, 0x54, + 0x89, 0x05, 0x89, 0x9a, 0x6f, 0xa0, 0x2f, 0xfc, 0x3e, 0x43, 0x9f, 0x40, + 0x57, 0x0e, 0x81, 0xa4, 0x0b, 0xd7, 0x31, 0xcc, 0x87, 0x8a, 0xa1, 0xa2, + 0xf8, 0x9d, 0xdf, 0x73, 0xf3, 0x9b, 0xc7, 0x63, 0x4f, 0x0f, 0x4e, 0x55, + 0x68, 0x5e, 0x79, 0xd6, 0x11, 0xbf, 0xf1, 0xda, 0x5f, 0x23, 0xe6, 0xd9, + 0x24, 0xa1, 0xb9, 0x40, 0x25, 0x41, 0x3d, 0xfc, 0xb9, 0xcc, 0x3f, 0x98, + 0xb5, 0xe8, 0x9e, 0x99, 0xae, 0xa8, 0x7c, 0x97, 0x98, 0xeb, 0x66, 0xd3, + 0x95, 0x0c, 0x3a, 0x69, 0xe4, 0x15, 0x5e, 0x79, 0x0f, 0xdb, 0x79, 0x84, + 0x3b, 0xc2, 0x35, 0x0a, 0x35, 0xb8, 0x87, 0xaa, 0x83, 0x1d, 0x48, 0xd0, + 0x0b, 0x48, 0x0a, 0x65, 0x27, 0x7a, 0x53, 0x77, 0x72, 0x79, 0xb6, 0x03, + 0xe7, 0x7a, 0xcd, 0xf6, 0x43, 0x03, 0x05, 0xcb, 0x29, 0xd1, 0x1a, 0x34, + 0x38, 0xd3, 0xe2, 0x4f, 0xf7, 0x6d, 0xb1, 0x5c, 0x78, 0xb3, 0x7c, 0xb0, + 0xdd, 0xc3, 0xed, 0x22, 0xfc, 0xbd, 0x03, 0x3a, 0x56, 0xcc, 0x83, 0x80, + 0x9f, 0xb2, 0x29, 0x8d, 0x5a, 0x48, 0xbe, 0xe1, 0xa6, 0x7b, 0xcb, 0x15, + 0xec, 0x9a, 0x5a, 0x0f, 0x87, 0x1d, 0x61, 0x04, 0xf6, 0x31, 0xed, 0xc5, + 0x94, 0xa1, 0xab, 0xd1, 0xbe, 0xdb, 0x48, 0x3b, 0x76, 0xd3, 0x8b, 0x28, + 0xe5, 0x90, 0xcf, 0x8a, 0x2b, 0xdb, 0x9a, 0x88, 0xb2, 0x04, 0x01, 0xa1, + 0xc1, 0x8b, 0x0b, 0x14, 0x2f, 0x54, 0x8e, 0xa8, 0x0a, 0xd9, 0x6e, 0x4f, + 0x6e, 0x85, 0xac, 0x3a, 0xc9, 0xd4, 0x59, 0xe6, 0x33, 0x2b, 0xcc, 0x6e, + 0xea, 0xbb, 0xa2, 0x52, 0xe4, 0xdc, 0xf4, 0x3d, 0x32, 0xdb, 0xe5, 0xe5, + 0xe5, 0xd7, 0x60, 0x1e, 0xd5, 0xca, 0xd9, 0x14, 0x6a, 0xc3, 0xf9, 0xce, + 0x18, 0xfb, 0x51, 0xb8, 0xd8, 0x7c, 0xef, 0xdb, 0x18, 0x5f, 0x7e, 0xb1, + 0x3a, 0xe6, 0xc3, 0x1a, 0x5d, 0x8a, 0x8a, 0x78, 0x7c, 0x39, 0xd3, 0xed, + 0x55, 0xc7, 0x15, 0xa6, 0xa3, 0xbe, 0xa0, 0x8d, 0x27, 0x44, 0x0e, 0x2e, + 0x4d, 0xb9, 0xd3, 0x45, 0xf5, 0xed, 0x12, 0x3b, 0x02, 0xa8, 0x05, 0x23, + 0x5a, 0x84, 0xdd, 0xd5, 0x44, 0x4a, 0xda, 0x72, 0x18, 0x12, 0xa6, 0x61, + 0xab, 0x6a, 0x97, 0xf6, 0x67, 0x62, 0x6b, 0xc3, 0x53, 0x50, 0x53, 0x5f, + 0x6d, 0x21, 0x28, 0xd6, 0x55, 0x07, 0x6e, 0x1c, 0x1f, 0x7d, 0xe0, 0xce, + 0xb7, 0xb8, 0x2a, 0xeb, 0x23, 0x89, 0xcb, 0x6e, 0x26, 0xd7, 0xa8, 0x1c, + 0x1c, 0x83, 0xeb, 0xef, 0xfd, 0x34, 0xa5, 0xdb, 0x22, 0xef, 0x17, 0xf0, + 0xbc, 0x71, 0x25, 0x32, 0x6b, 0x11, 0xd9, 0xf7, 0xfb, 0xca, 0xb1, 0x46, + 0xd1, 0xfb, 0xa0, 0xd8, 0xef, 0xb7, 0xc2, 0x60, 0xe7, 0x4e, 0x3f, 0x72, + 0x93, 0xf6, 0xed, 0xcd, 0x2d, 0x27, 0x3a, 0xdd, 0x6f, 0x58, 0xd2, 0xb0, + 0x68, 0x52, 0x1a, 0xbe, 0x44, 0x79, 0x56, 0x40, 0x10, 0xbd, 0x03, 0x51, + 0x3a, 0x0b, 0x55, 0x44, 0x30, 0xa0, 0x9c, 0xe9, 0xfe, 0xbe, 0x5a, 0x32, + 0x02, 0xcc, 0x3b, 0x69, 0x41, 0x5c, 0x93, 0x87, 0xc6, 0x54, 0x61, 0xdd, + 0xe5, 0xa3, 0x54, 0x75, 0x20, 0xd9, 0x4a, 0x81, 0x0d, 0x21, 0xed, 0x25, + 0x15, 0x5c, 0x59, 0x60, 0x28, 0xe5, 0x76, 0xfe, 0xaa, 0x30, 0xbc, 0x65, + 0xa5, 0x40, 0x4a, 0xd3, 0xd2, 0x7b, 0x6f, 0x8f, 0x8a, 0x50, 0x33, 0x05, + 0x72, 0xc4, 0x29, 0x83, 0x9f, 0x0e, 0xf8, 0x0c, 0xe5, 0x6a, 0xb4, 0x72, + 0x58, 0x79, 0xd2, 0x87 + }; + + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_PARAMETER_SET, ¶mSet, sizeof(paramSet) }, + { CKA_VALUE, mldsa_44_priv, sizeof(mldsa_44_priv) }, + }; + int cnt = sizeof(tmpl)/sizeof(*tmpl); + + ret = funcList->C_CreateObject(session, tmpl, cnt, obj); + CHECK_CKR(ret, "ML-DSA Private Key Create Object"); + + return ret; +} + +static CK_RV import_mldsa_pub_key(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE* obj) +{ + CK_RV ret; + CK_ML_DSA_PARAMETER_SET_TYPE paramSet = CKP_ML_DSA_44; + static unsigned char mldsa_44_pub[] = { + 0x6b, 0x34, 0xfb, 0xdf, 0x6c, 0x26, 0xdb, 0xdb, 0xdc, 0x9a, 0x4b, 0xc3, + 0xe3, 0x13, 0x1d, 0xc8, 0x76, 0x9e, 0xbc, 0x91, 0x19, 0xce, 0x4e, 0xc6, + 0x70, 0x1b, 0xf8, 0xab, 0x3f, 0x28, 0x7d, 0x7c, 0x5d, 0x81, 0x2e, 0xe8, + 0xf0, 0xb8, 0xc8, 0x20, 0xe3, 0xaa, 0x02, 0x9c, 0x9b, 0xe0, 0xc1, 0x40, + 0xbb, 0xff, 0x4d, 0xe4, 0x88, 0x65, 0xb4, 0xe3, 0xa1, 0xc7, 0x6a, 0xb7, + 0x5f, 0xc7, 0x20, 0x21, 0x52, 0x44, 0xdc, 0xf8, 0xf9, 0x7c, 0xdb, 0x5d, + 0xb0, 0xb2, 0xad, 0x96, 0x5a, 0x97, 0x55, 0xea, 0x54, 0xfe, 0x4b, 0x82, + 0xeb, 0x4b, 0x7d, 0xe8, 0x1a, 0xf2, 0x41, 0x37, 0x40, 0x6e, 0x6f, 0x4a, + 0x2f, 0xdd, 0xcd, 0xb6, 0x64, 0x92, 0xe0, 0xcb, 0x72, 0x7c, 0x1d, 0x4f, + 0xe8, 0xa4, 0x90, 0xb5, 0x4e, 0xad, 0x29, 0xd5, 0x44, 0x53, 0x3d, 0x4f, + 0x3c, 0x3a, 0x19, 0xa5, 0x68, 0x8c, 0x8c, 0xfa, 0x9a, 0xf0, 0x12, 0x85, + 0xc8, 0x52, 0xfd, 0xa8, 0x5c, 0x50, 0x80, 0x48, 0x49, 0x6f, 0x8a, 0x67, + 0xe8, 0x33, 0x5d, 0x66, 0x64, 0x9f, 0xbc, 0xe9, 0xaf, 0xb8, 0x5d, 0xe5, + 0xc0, 0x31, 0x98, 0xd7, 0x98, 0x7d, 0x27, 0x63, 0x11, 0xf7, 0x32, 0xd6, + 0x98, 0x7b, 0x61, 0xbb, 0x6e, 0x62, 0xea, 0x43, 0x7d, 0x82, 0x78, 0x09, + 0x3e, 0xf5, 0x9b, 0x88, 0xfe, 0x2d, 0x04, 0x8d, 0x7f, 0xf9, 0x0a, 0x99, + 0x83, 0x51, 0xad, 0x81, 0xb3, 0x27, 0xbb, 0xbe, 0x2e, 0xeb, 0xac, 0xb6, + 0x1e, 0xc1, 0xf8, 0x0d, 0xc4, 0x73, 0x50, 0x8d, 0xea, 0x36, 0x0f, 0x9d, + 0xd5, 0xc0, 0xce, 0xba, 0x2e, 0x95, 0x9e, 0x14, 0x64, 0xaa, 0x6d, 0x16, + 0x99, 0xa5, 0xec, 0xc0, 0x9e, 0xce, 0x3f, 0xf9, 0x85, 0x85, 0xbc, 0xdc, + 0xc2, 0x4c, 0x11, 0x43, 0x4c, 0xc8, 0x18, 0xb1, 0x54, 0x01, 0x9e, 0x84, + 0x12, 0x61, 0xea, 0xa6, 0xf3, 0x64, 0x48, 0x2c, 0x86, 0x8a, 0x68, 0x5e, + 0x2e, 0x03, 0x95, 0x81, 0x4f, 0x16, 0x8a, 0x68, 0xa7, 0x5d, 0x69, 0x02, + 0xe9, 0x59, 0x4c, 0x13, 0xa1, 0x8c, 0x83, 0x5a, 0x3b, 0xe4, 0xc0, 0xb7, + 0x76, 0x5c, 0x2a, 0x9d, 0x00, 0xf2, 0x5c, 0x57, 0xd6, 0x0f, 0x03, 0x94, + 0x66, 0xd2, 0xdc, 0x2f, 0x37, 0x3e, 0xe8, 0x78, 0xe5, 0xca, 0x76, 0x5d, + 0xd9, 0xb9, 0xc9, 0x0d, 0xd7, 0x0d, 0xbd, 0xfd, 0x81, 0x75, 0xff, 0x5c, + 0xa4, 0x7d, 0xa6, 0xec, 0x9d, 0x9d, 0x6a, 0x71, 0x44, 0x1d, 0xed, 0x51, + 0xbb, 0xe6, 0xe5, 0x77, 0x89, 0x6a, 0x00, 0xff, 0x80, 0x42, 0x8c, 0x11, + 0x3b, 0x6f, 0x19, 0xb9, 0xd6, 0x97, 0x44, 0x7c, 0x45, 0xc8, 0x7f, 0x71, + 0x6b, 0xc3, 0x64, 0xe2, 0x53, 0xa2, 0xa6, 0x15, 0x11, 0x57, 0x02, 0xf6, + 0xa4, 0x35, 0x3c, 0xe9, 0xdd, 0x73, 0xac, 0x48, 0xa4, 0x85, 0x84, 0x5a, + 0x91, 0xaf, 0xa2, 0x19, 0x1f, 0xd6, 0xe9, 0xdb, 0xb2, 0xed, 0xcc, 0x68, + 0x85, 0x27, 0x34, 0x22, 0x80, 0x04, 0xa8, 0x7b, 0x5f, 0xe0, 0xc1, 0x65, + 0x40, 0xac, 0x1c, 0xaa, 0x86, 0x21, 0x19, 0x7c, 0x62, 0x49, 0xb4, 0x7c, + 0xfd, 0xa9, 0x30, 0x96, 0x06, 0xfb, 0x3d, 0x61, 0xcd, 0x4f, 0xaa, 0xf4, + 0x1e, 0xe9, 0x83, 0x69, 0x21, 0x8f, 0x06, 0xf9, 0xfe, 0x4f, 0xd2, 0x55, + 0x0e, 0x22, 0x1a, 0x8d, 0x4c, 0xfd, 0x94, 0xd3, 0x94, 0x47, 0x99, 0x57, + 0x5a, 0xd6, 0x6b, 0xe7, 0xb3, 0x84, 0x80, 0x59, 0x39, 0x5a, 0x85, 0x18, + 0x7c, 0x12, 0x18, 0xb0, 0x8d, 0x16, 0x72, 0x73, 0x2b, 0x42, 0xb0, 0x14, + 0x92, 0xcc, 0x05, 0x49, 0xe3, 0xc3, 0xa5, 0xd7, 0x76, 0xa8, 0x5e, 0xea, + 0xfc, 0x97, 0x0c, 0x1f, 0xf1, 0xca, 0x31, 0xaf, 0xec, 0x2b, 0x7a, 0x25, + 0x9e, 0x55, 0xc9, 0xf6, 0x99, 0x5a, 0xdb, 0xc3, 0xab, 0x6e, 0x56, 0xe6, + 0x3d, 0xee, 0xb2, 0x72, 0x4c, 0x55, 0xe0, 0xc0, 0x16, 0xdd, 0xb4, 0x33, + 0x20, 0xfe, 0x0e, 0x45, 0x34, 0x99, 0x84, 0xf5, 0x25, 0x4b, 0xf3, 0xab, + 0xeb, 0x49, 0xb7, 0xd7, 0xbe, 0x27, 0x40, 0xc8, 0x1b, 0x14, 0xbc, 0x8e, + 0x8a, 0x4a, 0xa8, 0x9f, 0xa6, 0xaf, 0x5b, 0x09, 0x6a, 0x89, 0x55, 0xc3, + 0x0c, 0x8a, 0x45, 0xd6, 0xa4, 0xb5, 0x44, 0x3d, 0xc8, 0xbb, 0x89, 0xe6, + 0x71, 0x19, 0x8c, 0xcd, 0xbb, 0xc5, 0x29, 0x8f, 0x0f, 0xba, 0xd6, 0x02, + 0xae, 0x65, 0x97, 0x76, 0x15, 0x4a, 0x86, 0x14, 0x81, 0x36, 0x6f, 0x20, + 0xf4, 0x8b, 0xc3, 0x87, 0x50, 0x11, 0x24, 0xbf, 0xaf, 0x75, 0xeb, 0x24, + 0x74, 0x49, 0xfa, 0x5b, 0x11, 0xcc, 0x2e, 0x27, 0x16, 0x49, 0xa9, 0xb9, + 0x9e, 0xe6, 0x06, 0xaa, 0x0a, 0x89, 0x41, 0xeb, 0x00, 0xfa, 0x90, 0xab, + 0x30, 0x8c, 0x89, 0x1c, 0x07, 0x9e, 0x60, 0xc6, 0xb2, 0x16, 0x5a, 0x93, + 0x8f, 0x2b, 0x84, 0x33, 0x84, 0x1d, 0xe6, 0xb9, 0x7c, 0x64, 0x18, 0xa1, + 0x46, 0x49, 0x1b, 0x37, 0xfb, 0xd8, 0x7c, 0x66, 0xba, 0xee, 0x89, 0x2a, + 0x03, 0x97, 0x84, 0x15, 0xf2, 0xc9, 0xa5, 0x7e, 0xc9, 0x27, 0xfb, 0xfa, + 0x70, 0x4c, 0x4a, 0x5b, 0x1a, 0x36, 0x91, 0x24, 0x0e, 0x74, 0x67, 0xa3, + 0x3a, 0x10, 0x4e, 0x7a, 0x59, 0x9d, 0x25, 0x92, 0x20, 0x82, 0x14, 0xc6, + 0xd6, 0x22, 0xd8, 0xcb, 0x71, 0x01, 0x0a, 0x66, 0x26, 0xef, 0xdf, 0x72, + 0xc9, 0x7d, 0xcf, 0x5b, 0xc3, 0x88, 0x2f, 0x2c, 0xe7, 0xa0, 0x5b, 0x75, + 0x90, 0xb3, 0x81, 0x5a, 0xdd, 0x13, 0x0b, 0x74, 0x13, 0xc8, 0xd9, 0xa9, + 0x6f, 0x1c, 0xa5, 0x50, 0xa6, 0x99, 0x86, 0xe8, 0xd3, 0xe4, 0x08, 0x30, + 0xc8, 0xc6, 0xe4, 0xa9, 0xe5, 0xa8, 0xb5, 0x17, 0xa1, 0x04, 0x27, 0x9e, + 0x06, 0x4f, 0xe5, 0x06, 0x9c, 0x95, 0xec, 0x92, 0x58, 0xf1, 0x07, 0xc9, + 0x2f, 0xa0, 0x66, 0x90, 0xbb, 0x69, 0x87, 0xd0, 0xe5, 0x09, 0x0c, 0xab, + 0x24, 0x38, 0x78, 0xed, 0x2c, 0x87, 0x81, 0xa2, 0xfc, 0x0f, 0x74, 0x5e, + 0xe1, 0x73, 0x7f, 0xec, 0x75, 0x33, 0xde, 0x70, 0x5e, 0x44, 0x71, 0x66, + 0x4d, 0xad, 0xcd, 0x5a, 0x4c, 0xda, 0xa9, 0xf7, 0xf9, 0x1e, 0x2c, 0xb7, + 0xa5, 0xeb, 0x5e, 0xde, 0xc6, 0x45, 0xcf, 0x1c, 0xb0, 0xb3, 0xd5, 0x2e, + 0x91, 0xe0, 0xaa, 0x7f, 0xbf, 0x87, 0x5b, 0x25, 0x8b, 0x9f, 0xb3, 0x12, + 0xe9, 0x89, 0xff, 0x94, 0x45, 0x4c, 0x8e, 0xba, 0xc3, 0x63, 0x16, 0xa7, + 0xaf, 0x13, 0xd0, 0x7b, 0x45, 0x5b, 0x84, 0xf6, 0xa5, 0xe0, 0x77, 0x4d, + 0x36, 0xaf, 0xc2, 0xba, 0xc6, 0xd4, 0x5e, 0x16, 0x50, 0xe5, 0x03, 0xab, + 0x95, 0x32, 0x5e, 0x7d, 0xa0, 0xb9, 0x1f, 0xc7, 0x20, 0x53, 0xe9, 0x74, + 0x77, 0x55, 0x6b, 0xaa, 0x5e, 0xe6, 0x68, 0x5b, 0xef, 0x5b, 0x93, 0x25, + 0x6b, 0xf8, 0x66, 0xae, 0x5b, 0x56, 0x3e, 0x55, 0xca, 0x00, 0x38, 0x1c, + 0xe5, 0x28, 0x93, 0x6c, 0x44, 0x93, 0xf5, 0xfd, 0xce, 0x6c, 0x9b, 0x1f, + 0x45, 0x89, 0x93, 0x8c, 0xe9, 0xf8, 0x3c, 0xe6, 0x3a, 0xef, 0xfa, 0x36, + 0x87, 0x4f, 0x86, 0x60, 0xfe, 0xfe, 0xfa, 0xf0, 0xc5, 0xc2, 0xde, 0x1e, + 0x24, 0xb7, 0x9b, 0x73, 0x8a, 0x32, 0xf4, 0x38, 0x26, 0xba, 0x20, 0x1f, + 0xa5, 0x96, 0x16, 0x92, 0xad, 0x46, 0x1f, 0x20, 0x2c, 0xf9, 0x4c, 0xc3, + 0x95, 0xb5, 0x9c, 0x5d, 0xdb, 0x43, 0x62, 0x64, 0xf8, 0xc6, 0x3f, 0x25, + 0xf6, 0x56, 0xd1, 0x1c, 0x31, 0xdd, 0x9c, 0xfc, 0xe9, 0x8b, 0xf9, 0xad, + 0xd9, 0x5b, 0x68, 0xb3, 0xbb, 0xd8, 0xb0, 0xf6, 0x84, 0xc3, 0x05, 0x45, + 0x72, 0x30, 0xf8, 0xa8, 0x58, 0x06, 0x60, 0x1d, 0x86, 0xcb, 0xb1, 0xc9, + 0x54, 0xe7, 0xe7, 0x79, 0x3f, 0x2a, 0x50, 0x0e, 0x81, 0x46, 0xe7, 0xa2, + 0xf1, 0x3f, 0xc5, 0x79, 0xb5, 0x8c, 0x1a, 0xc6, 0x91, 0xc3, 0x36, 0xfb, + 0xd4, 0x00, 0x1a, 0xfa, 0xa1, 0x84, 0x2c, 0x19, 0x46, 0x5f, 0x3c, 0x28, + 0xe7, 0x37, 0xb1, 0x35, 0xa8, 0xcb, 0x53, 0x2a, 0x20, 0x92, 0xa6, 0x1f, + 0x35, 0xec, 0x11, 0x52, 0x6b, 0x3f, 0x84, 0x24, 0x64, 0xfb, 0x85, 0x03, + 0xe0, 0x46, 0xf6, 0xb4, 0x94, 0xd7, 0xdb, 0xcf, 0x14, 0x90, 0xb9, 0x9f, + 0x38, 0x21, 0xb7, 0x56, 0xde, 0xb0, 0xde, 0x54, 0x9b, 0x2f, 0x3e, 0x94, + 0xfe, 0xa6, 0xe7, 0x97, 0x38, 0xea, 0xe5, 0x37, 0x9c, 0xc0, 0x2a, 0x5e, + 0xb2, 0xfa, 0xcd, 0x0b, 0x1d, 0x9f, 0x1d, 0xc0, 0xfd, 0xf7, 0x56, 0x52, + 0x17, 0x2c, 0x80, 0x9b, 0x63, 0x74, 0x61, 0xe8, 0x3d, 0xc9, 0x04, 0xae, + 0xbe, 0x65, 0x48, 0xf1, 0xa5, 0x5e, 0x94, 0x6d, 0xcc, 0x32, 0x90, 0x9c, + 0xca, 0x6f, 0xa0, 0x4d, 0xe7, 0x5b, 0xc4, 0x43, 0xf8, 0xc9, 0x47, 0xa9, + 0x70, 0x19, 0x7d, 0xf5, 0xd4, 0x99, 0x2a, 0x75, 0x51, 0x2e, 0x8e, 0x6a, + 0x75, 0xf2, 0x1f, 0xac, 0x12, 0x18, 0x72, 0xa2, 0x41, 0xc6, 0xf9, 0x16, + 0x14, 0x4a, 0xe1, 0xe1, 0xef, 0xe6, 0x2b, 0xe8, 0xe1, 0x6d, 0x29, 0x24, + 0xcf, 0x9d, 0x0e, 0x7b, 0xca, 0x52, 0xe5, 0x56, 0xec, 0xce, 0xb4, 0x3d, + 0xc2, 0xf8, 0x33, 0x59, 0x3c, 0x0d, 0xbf, 0x7a, 0x87, 0x42, 0x33, 0xa7, + 0x8d, 0x9b, 0xfb, 0x81, 0x3c, 0xe8, 0x7e, 0x07, 0xc4, 0xba, 0x53, 0x64, + 0x02, 0xa6, 0x5d, 0x1d, 0xf9, 0x61, 0x43, 0x11, 0xec, 0x4e, 0x86, 0xfe, + 0x99, 0xa2, 0xf2, 0x00, 0xda, 0xb5, 0x20, 0xf9, 0x48, 0x07, 0x0d, 0x5c, + 0x02, 0x38, 0x4d, 0xc0, 0xf4, 0xf3, 0x14, 0xb6, 0x47, 0x2c, 0x4e, 0xdc, + 0x24, 0xbd, 0x16, 0x82, 0x78, 0x81, 0x7d, 0x35, 0x7f, 0xa2, 0x57, 0xb3, + 0xe2, 0x16, 0x7a, 0x86, 0x86, 0x93, 0x36, 0xad, 0xc8, 0xc8, 0x5e, 0xb4, + 0xdf, 0x64, 0x97, 0xeb + }; + + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &mldsaKeyType, sizeof(mldsaKeyType) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_PARAMETER_SET, ¶mSet, sizeof(paramSet) }, + { CKA_VALUE, mldsa_44_pub, sizeof(mldsa_44_pub) }, + }; + int cnt = sizeof(tmpl)/sizeof(*tmpl); + + ret = funcList->C_CreateObject(session, tmpl, cnt, obj); + CHECK_CKR(ret, "ML-DSA Public Key Create Object"); + + return ret; +} + +static CK_RV mldsa_sign_verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE privKey, + CK_OBJECT_HANDLE pubKey, CK_MECHANISM* mech, + byte* data, CK_ULONG dataSz) +{ + CK_RV ret = CKR_OK; + byte sig[8192]; + byte sigBad[8192]; + CK_ULONG sigSz = sizeof(sig); + CK_ULONG sigBadSz; + + ret = funcList->C_SignInit(session, mech, privKey); + CHECK_CKR(ret, "ML-DSA Sign Init"); + if (ret == CKR_OK) { + sigSz = 0; + ret = funcList->C_Sign(session, data, dataSz, NULL, &sigSz); + CHECK_CKR(ret, "ML-DSA Sign out size no out"); + } + if (ret == CKR_OK) { + CHECK_COND(sigSz == DILITHIUM_ML_DSA_44_SIG_SIZE, + ret, "ML-DSA Sign out size"); + } + if (ret == CKR_OK) { + CK_ULONG smallSz = 1; + ret = funcList->C_Sign(session, data, dataSz, sig, &smallSz); + CHECK_CKR_FAIL(ret, CKR_BUFFER_TOO_SMALL, + "ML-DSA Sign out size too small"); + } + if (ret == CKR_OK) { + ret = funcList->C_Sign(session, data, dataSz, sig, &sigSz); + CHECK_CKR(ret, "ML-DSA Sign"); + } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, mech, pubKey); + CHECK_CKR(ret, "ML-DSA Verify Init"); + } + if (ret == CKR_OK) { + ret = funcList->C_Verify(session, data, dataSz, sig, sigSz); + CHECK_CKR(ret, "ML-DSA Verify"); + } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, mech, pubKey); + CHECK_CKR(ret, "ML-DSA Verify Init"); + } + if (ret == CKR_OK) { + ret = funcList->C_Verify(session, data, dataSz - 1, sig, sigSz); + CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "ML-DSA Verify bad data"); + } + if (ret == CKR_OK) { + XMEMCPY(sigBad, sig, sigSz); + sigBad[0] ^= 0x01; + sigBadSz = sigSz; + ret = funcList->C_VerifyInit(session, mech, pubKey); + CHECK_CKR(ret, "ML-DSA Verify Init"); + } + if (ret == CKR_OK) { + ret = funcList->C_Verify(session, data, dataSz, sigBad, sigBadSz); + CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "ML-DSA Verify bad sig"); + } + + return ret; +} + +static CK_RV mldsa_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE privKey, + CK_OBJECT_HANDLE pubKey) +{ + CK_RV ret = CKR_OK; + byte data[64]; + CK_MECHANISM mech; + CK_SIGN_ADDITIONAL_CONTEXT signCtx; + byte ctx[] = "mldsa-ctx"; +#ifndef NO_SHA256 + byte preHash[WC_SHA256_DIGEST_SIZE]; + CK_HASH_SIGN_ADDITIONAL_CONTEXT hashCtx; + + XMEMSET(preHash, 0x3C, sizeof(preHash)); + XMEMSET(&hashCtx, 0, sizeof(hashCtx)); +#endif + + XMEMSET(data, 0x5A, sizeof(data)); + XMEMSET(&signCtx, 0, sizeof(signCtx)); + signCtx.hedgeVariant = CKH_HEDGE_REQUIRED; + signCtx.pContext = ctx; + signCtx.ulContextLen = sizeof(ctx) - 1; + + mech.mechanism = CKM_ML_DSA; + mech.pParameter = &signCtx; + mech.ulParameterLen = sizeof(signCtx); + ret = mldsa_sign_verify(session, privKey, pubKey, &mech, data, + sizeof(data)); + if (ret == CKR_OK) { + signCtx.pContext = NULL; + signCtx.ulContextLen = 0; + ret = mldsa_sign_verify(session, privKey, pubKey, &mech, data, + sizeof(data)); + } + +#ifndef NO_SHA256 + if (ret == CKR_OK) { + hashCtx.hedgeVariant = CKH_HEDGE_REQUIRED; + hashCtx.pContext = ctx; + hashCtx.ulContextLen = sizeof(ctx) - 1; + hashCtx.hash = CKM_SHA256; + + mech.mechanism = CKM_HASH_ML_DSA; + mech.pParameter = &hashCtx; + mech.ulParameterLen = sizeof(hashCtx); + ret = mldsa_sign_verify(session, privKey, pubKey, &mech, preHash, + sizeof(preHash)); + } + if (ret == CKR_OK) { + hashCtx.pContext = NULL; + hashCtx.ulContextLen = 0; + ret = mldsa_sign_verify(session, privKey, pubKey, &mech, preHash, + sizeof(preHash)); + } +#endif + + return ret; +} + +static CK_RV test_mldsa_gen_keys(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + + ret = gen_mldsa_keys(session, CKP_ML_DSA_44, &pub, &priv, NULL, 0, NULL, 0, + 0); + if (ret == CKR_OK) + ret = mldsa_test(session, priv, pub); + + if (priv != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, priv); + if (pub != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, pub); + + return ret; +} + +static CK_RV test_mldsa_fixed_keys(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + + ret = import_mldsa_priv_key(session, &priv); + if (ret == CKR_OK) + ret = import_mldsa_pub_key(session, &pub); + if (ret == CKR_OK) + ret = mldsa_test(session, priv, pub); + + if (priv != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, priv); + if (pub != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, pub); + + return ret; +} + +static CK_RV test_mldsa_gen_keys_id(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + unsigned char* privId = (unsigned char*)"mldsa-priv-id"; + int privIdLen = (int)XSTRLEN((const char*)privId); + + ret = gen_mldsa_keys(session, CKP_ML_DSA_44, &pub, NULL, privId, privIdLen, + NULL, 0, 0); + if (ret == CKR_OK) + ret = find_mldsa_priv_key(session, &priv, privId, privIdLen); + if (ret == CKR_OK) + ret = mldsa_test(session, priv, pub); + + if (priv != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, priv); + if (pub != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, pub); + + return ret; +} + +static CK_RV test_mldsa_gen_keys_token(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + unsigned char* privId = (unsigned char*)"mldsa-priv-token"; + unsigned char* pubId = (unsigned char*)"mldsa-pub-token"; + int privIdLen = (int)XSTRLEN((const char*)privId); + int pubIdLen = (int)XSTRLEN((const char*)pubId); + + return gen_mldsa_keys(session, CKP_ML_DSA_44, NULL, NULL, privId, privIdLen, + pubId, pubIdLen, 1); +} + +static CK_RV test_mldsa_token_keys(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + unsigned char* privId = (unsigned char*)"mldsa-priv-token"; + unsigned char* pubId = (unsigned char*)"mldsa-pub-token"; + int privIdLen = (int)XSTRLEN((const char*)privId); + int pubIdLen = (int)XSTRLEN((const char*)pubId); + + ret = find_mldsa_priv_key(session, &priv, privId, privIdLen); + if (ret == CKR_OK) + ret = find_mldsa_pub_key(session, &pub, pubId, pubIdLen); + if (ret == CKR_OK) + ret = mldsa_test(session, priv, pub); + + if (priv != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, priv); + if (pub != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, pub); + + return ret; +} + +static CK_RV test_mldsa_sig_fail(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret = CKR_OK; + CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; + CK_MECHANISM mech; + CK_HASH_SIGN_ADDITIONAL_CONTEXT hashCtx; + byte ctx[] = "mldsa-fail"; + byte dummy = 0; + + ret = gen_mldsa_keys(session, CKP_ML_DSA_44, &pub, &priv, NULL, 0, NULL, 0, + 0); + if (ret != CKR_OK) + return ret; + + mech.mechanism = CKM_ML_DSA; + mech.pParameter = &dummy; + mech.ulParameterLen = sizeof(dummy); + ret = funcList->C_SignInit(session, &mech, priv); + CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID, + "ML-DSA Sign Init bad parameter length"); + + if (ret == CKR_OK) { + XMEMSET(&hashCtx, 0, sizeof(hashCtx)); + hashCtx.hedgeVariant = CKH_HEDGE_PREFERRED; + hashCtx.pContext = ctx; + hashCtx.ulContextLen = sizeof(ctx) - 1; + hashCtx.hash = 0; + mech.mechanism = CKM_HASH_ML_DSA; + mech.pParameter = &hashCtx; + mech.ulParameterLen = sizeof(hashCtx); + ret = funcList->C_SignInit(session, &mech, priv); + CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID, + "HASH-ML-DSA Sign Init bad hash"); + } + + if (priv != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, priv); + if (pub != CK_INVALID_HANDLE) + funcList->C_DestroyObject(session, pub); + + return ret; +} +#endif /* WOLFPKCS11_MLDSA */ +#endif /* WOLFPKCS11_PKCS11_V3_2 */ + static CK_RV test_get_interface_list(void* args) { CK_RV ret = CKR_OK; @@ -667,6 +1418,16 @@ static TEST_FUNC testFunc[] = { PKCS11TEST_FUNC_NO_INIT_DECL(test_get_interface), PKCS11TEST_FUNC_TOKEN_DECL(test_get_info), PKCS11TEST_FUNC_SESS_DECL(test_function_not_supported), +#ifdef WOLFPKCS11_PKCS11_V3_2 +#ifdef WOLFPKCS11_MLDSA + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_gen_keys), + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_fixed_keys), + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_gen_keys_id), + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_gen_keys_token), + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_token_keys), + PKCS11TEST_FUNC_SESS_DECL(test_mldsa_sig_fail), +#endif +#endif }; static int testFuncCnt = sizeof(testFunc) / sizeof(*testFunc); diff --git a/wolfpkcs11/internal.h b/wolfpkcs11/internal.h index ebc224e2..cb9ecfd3 100644 --- a/wolfpkcs11/internal.h +++ b/wolfpkcs11/internal.h @@ -32,6 +32,10 @@ #include #include +#ifdef WOLFPKCS11_MLDSA +#include +#endif + #include #include @@ -95,6 +99,9 @@ C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT" #endif #endif +#if defined(WOLFPKCS11_MLDSA) && !defined(HAVE_DILITHIUM) +#error Compiling with ML-DSA requires ML-DSA support in wolfSSL. +#endif /* We need the next two for NSS, just for storage, even if we have no algos */ #ifndef WC_MD5_DIGEST_SIZE @@ -240,6 +247,8 @@ C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT" #define WP11_INIT_AES_KEYWRAP_DEC 0x0061 #define WP11_INIT_TLS_MAC_SIGN 0x0070 #define WP11_INIT_TLS_MAC_VERIFY 0x0071 +#define WP11_INIT_MLDSA_SIGN 0x0080 +#define WP11_INIT_MLDSA_VERIFY 0x0081 /* Some operations can have an additional hashing step before the sign/verify */ #define WP11_INIT_DIGEST_SHIFT 12 #define WP11_INIT_DIGEST_MASK (0xF << WP11_INIT_DIGEST_SHIFT) @@ -378,6 +387,8 @@ WP11_LOCAL int WP11_Session_SetCcmParams(WP11_Session* session, int dataSz, int macSz); WP11_LOCAL int WP11_Session_SetCtsParams(WP11_Session* session, unsigned char* iv, int enc, WP11_Object* object); +WP11_LOCAL int WP11_Session_SetMldsaParams(WP11_Session* session, CK_VOID_PTR params, + CK_ULONG paramsLen); WP11_LOCAL int WP11_Session_AddObject(WP11_Session* session, int onToken, WP11_Object* object); WP11_LOCAL int WP11_Session_RemoveObject(WP11_Session* session, WP11_Object* object); @@ -406,6 +417,8 @@ WP11_LOCAL int WP11_Object_SetRsaKey(WP11_Object* object, unsigned char** data, CK_ULONG* len); WP11_LOCAL int WP11_Object_SetEcKey(WP11_Object* object, unsigned char** data, CK_ULONG* len); +WP11_LOCAL int WP11_Object_SetMldsaKey(WP11_Object* object, unsigned char** data, + CK_ULONG* len); WP11_LOCAL int WP11_Object_SetDhKey(WP11_Object* object, unsigned char** data, CK_ULONG* len); WP11_LOCAL int WP11_Object_SetSecretKey(WP11_Object* object, unsigned char** data, @@ -493,6 +506,15 @@ WP11_LOCAL int WP11_Ec_Verify(unsigned char* sig, word32 sigLen, unsigned char* WP11_LOCAL int WP11_EC_Derive(unsigned char* point, word32 pointLen, unsigned char* key, word32* keyLen, WP11_Object* priv); +WP11_LOCAL int WP11_Mldsa_GenerateKeyPair(WP11_Object* pub, WP11_Object* priv, + WP11_Slot* slot); +WP11_LOCAL int WP11_Mldsa_SigLen(WP11_Object* key); +WP11_LOCAL int WP11_Mldsa_Sign(unsigned char* data, word32 dataLen, unsigned char* sig, + word32* sigLen, WP11_Object* priv, WP11_Session* session); +WP11_LOCAL int WP11_Mldsa_Verify(unsigned char* sig, word32 sigLen, unsigned char* data, + word32 dataLen, int* stat, WP11_Object* pub, + WP11_Session* session); + WP11_LOCAL int WP11_Dh_GenerateKeyPair(WP11_Object* pub, WP11_Object* priv, WP11_Slot* slot); WP11_LOCAL int WP11_Dh_Derive(unsigned char* pub, word32 pubLen, unsigned char* key, diff --git a/wolfpkcs11/pkcs11.h b/wolfpkcs11/pkcs11.h index 686cadd7..fef774b8 100644 --- a/wolfpkcs11/pkcs11.h +++ b/wolfpkcs11/pkcs11.h @@ -173,6 +173,7 @@ extern "C" { #define CKK_AES 0x0000001FUL #define CKK_DES3 0x00000015UL /* not supported */ #define CKK_HKDF 0x00000042UL +#define CKK_ML_DSA 0x0000004AUL #ifdef WOLFPKCS11_NSS /* Not defined by NSS, but we need one */ @@ -251,6 +252,9 @@ extern "C" { #define CKA_DERIVE_TEMPLATE 0x40000213UL #define CKA_ALLOWED_MECHANISMS 0x40000600UL +/* new post-quantum (general) */ +#define CKA_PARAMETER_SET 0x0000061DUL + #ifdef WOLFPKCS11_NSS #define CKA_NSS_EMAIL (CKA_NSS + 2) #define CKA_TRUST (CKA_NSS + 0x2000) @@ -294,6 +298,7 @@ extern "C" { #define CKM_SHA512_RSA_PKCS_PSS 0x00000045UL #define CKM_SHA224_RSA_PKCS 0x00000046UL #define CKM_SHA224_RSA_PKCS_PSS 0x00000047UL +#define CKM_SHA512_256 0x0000004CUL #define CKM_MD5 0x00000210UL #define CKM_MD5_HMAC 0x00000211UL #define CKM_SHA1 0x00000220UL @@ -314,6 +319,9 @@ extern "C" { #define CKM_SHA3_384_HMAC 0x000002C1UL #define CKM_SHA3_512 0x000002D0UL #define CKM_SHA3_512_HMAC 0x000002D1UL +#define CKM_SHA3_256 0x000002B0UL +#define CKM_SHA3_384 0x000002C0UL +#define CKM_SHA3_512 0x000002D0UL #define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL #define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371UL #define CKM_TLS_PRF 0x00000378UL @@ -347,6 +355,9 @@ extern "C" { #define CKM_HKDF_DERIVE 0x0000402AUL #define CKM_HKDF_DATA 0x0000402BUL #define CKM_HKDF_KEY_GEN 0x0000402CUL +#define CKM_ML_DSA_KEY_PAIR_GEN 0x0000001CUL +#define CKM_ML_DSA 0x0000001DUL +#define CKM_HASH_ML_DSA 0x0000001FUL #ifdef WOLFPKCS11_NSS #define CKM_NSS_TLS_PRF_GENERAL_SHA256 (CKM_NSS + 21) @@ -827,6 +838,33 @@ typedef struct 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/wolfpkcs11/store.h b/wolfpkcs11/store.h index 7ec48faa..2ba49a5f 100644 --- a/wolfpkcs11/store.h +++ b/wolfpkcs11/store.h @@ -36,6 +36,8 @@ #define WOLFPKCS11_STORE_CERT 0x09 #define WOLFPKCS11_STORE_TRUST 0x0A #define WOLFPKCS11_STORE_DATA 0x0B +#define WOLFPKCS11_STORE_MLDSAKEY_PRIV 0x0C +#define WOLFPKCS11_STORE_MLDSAKEY_PUB 0x0D /* * Opens access to location to read/write token data.