diff --git a/m4/acx_crypto_backend.m4 b/m4/acx_crypto_backend.m4 index fe59ca97f..4a77f0364 100644 --- a/m4/acx_crypto_backend.m4 +++ b/m4/acx_crypto_backend.m4 @@ -28,6 +28,16 @@ AC_DEFUN([ACX_CRYPTO_BACKEND],[ [enable_eddsa="detect"] ) + # Add SLHDSA check (only for OpenSSL) + + AC_ARG_ENABLE(slhdsa, + AS_HELP_STRING([--enable-slhdsa], + [Enable support for SLHDSA (default disabled, OpenSSL only)] + ), + [enable_slhdsa="${enableval}"], + [enable_slhdsa="no"] + ) + # Second check for the FIPS 140-2 mode AC_ARG_ENABLE(fips, @@ -100,6 +110,14 @@ AC_DEFUN([ACX_CRYPTO_BACKEND],[ detect*-no*) enable_eddsa="no";; esac + case "${enable_slhdsa}" in + yes|detect) ACX_OPENSSL_SLHDSA;; + esac + case "${enable_slhdsa}-${have_lib_openssl_slhdsa_support}" in + yes-no) AC_MSG_ERROR([OpenSSL library has no SLHDSA support]);; + detect-*) enable_slhdsa="${have_lib_openssl_slhdsa_support}";; + esac + case "${enable_gost}-${enable_fips}" in yes-yes) AC_MSG_ERROR([GOST is not FIPS approved]);; yes-no|detect-no) ACX_OPENSSL_GOST;; @@ -178,6 +196,11 @@ AC_DEFUN([ACX_CRYPTO_BACKEND],[ AC_MSG_ERROR([Botan does not support FIPS 140-2 mode]) fi + if test "x${enable_slhdsa}" = "xyes"; then + AC_MSG_WARN([SLHDSA is not supported with Botan. Disabling.]) + enable_slhdsa="no" + fi + ACX_BOTAN_RFC5649 ACX_BOTAN_RAWPSS @@ -231,6 +254,18 @@ AC_DEFUN([ACX_CRYPTO_BACKEND],[ fi AM_CONDITIONAL([WITH_EDDSA], [test "x${enable_eddsa}" = "xyes"]) + AC_MSG_CHECKING(for SLHDSA support) + if test "x${enable_slhdsa}" = "xyes"; then + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED( + [WITH_SLHDSA], + [], + [Compile with SLHDSA support] + ) + else + AC_MSG_RESULT(no) + fi + AM_CONDITIONAL([WITH_SLHDSA], [test "x${enable_slhdsa}" = "xyes"]) AC_SUBST(CRYPTO_INCLUDES) AC_SUBST(CRYPTO_LIBS) diff --git a/m4/acx_openssl_slhdsa.m4 b/m4/acx_openssl_slhdsa.m4 new file mode 100644 index 000000000..70d8481cb --- /dev/null +++ b/m4/acx_openssl_slhdsa.m4 @@ -0,0 +1,42 @@ +AC_DEFUN([ACX_OPENSSL_SLHDSA],[ + AC_MSG_CHECKING(for OpenSSL SLHDSA support) + + tmp_CPPFLAGS=$CPPFLAGS + tmp_LIBS=$LIBS + + CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES" + LIBS="$CRYPTO_LIBS $LIBS" + + AC_LANG_PUSH([C]) + AC_CACHE_VAL([acx_cv_lib_openssl_slhdsa_support],[ + acx_cv_lib_openssl_slhdsa_support=no + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ + #include + #include + int main() + { + EVP_PKEY_CTX *ctx; + ctx = EVP_PKEY_CTX_new_from_name(NULL, "SLH-DSA-SHA2-128f", NULL); + if (ctx == NULL) + return 1; + return 0; + } + ]]) + ],[ + AC_MSG_RESULT([Found SLHDSA]) + acx_cv_lib_openssl_slhdsa_support=yes + ],[ + AC_MSG_RESULT([Cannot find SLHDSA]) + acx_cv_lib_openssl_slhdsa_support=no + ],[ + AC_MSG_WARN([Cannot test, SLHDSA]) + acx_cv_lib_openssl_slhdsa_support=yes + ]) + ]) + AC_LANG_POP([C]) + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS + have_lib_openssl_slhdsa_support="${acx_cv_lib_openssl_slhdsa_support}" +]) diff --git a/src/bin/dump/tables.h b/src/bin/dump/tables.h index e6db51697..4cbe0d2b1 100644 --- a/src/bin/dump/tables.h +++ b/src/bin/dump/tables.h @@ -100,6 +100,7 @@ void fill_CKA_table(std::map &t) t[CKA_COPYABLE] = "CKA_COPYABLE"; t[CKA_DESTROYABLE] = "CKA_DESTROYABLE"; t[CKA_EC_PARAMS] = "CKA_EC_PARAMS"; + t[CKA_SLHDSA_PARAMS] = "CKA_SLHDSA_PARAMS"; t[CKA_EC_POINT] = "CKA_EC_POINT"; t[CKA_SECONDARY_AUTH] = "CKA_SECONDARY_AUTH"; t[CKA_AUTH_PIN_FLAGS] = "CKA_AUTH_PIN_FLAGS"; @@ -478,6 +479,8 @@ void fill_CKM_table(std::map &t) t[CKM_RSA_PKCS_OAEP_TPM_1_1] = "CKM_RSA_PKCS_OAEP_TPM_1_1"; t[CKM_EC_EDWARDS_KEY_PAIR_GEN] = "CKM_EC_EDWARDS_KEY_PAIR_GEN"; t[CKM_EDDSA] = "CKM_EDDSA"; + t[CKM_SLH_KEY_PAIR_GEN] = "CKM_SLH_KEY_PAIR_GEN"; + t[CKM_SLHDSA] = "CKM_SLHDSA"; } void fill_CKO_table(std::map &t) @@ -544,6 +547,7 @@ void fill_CKK_table(std::map &t) t[CKK_GOSTR3411] = "CKK_GOSTR3411"; t[CKK_GOST28147] = "CKK_GOST28147"; t[CKK_EC_EDWARDS] = "CKK_EC_EDWARDS"; + t[CKK_SLHDSA] = "CKK_SLHDSA"; } void fill_CKC_table(std::map &t) diff --git a/src/bin/util/softhsm2-util-ossl.cpp b/src/bin/util/softhsm2-util-ossl.cpp index 2ead15866..e42f7c020 100644 --- a/src/bin/util/softhsm2-util-ossl.cpp +++ b/src/bin/util/softhsm2-util-ossl.cpp @@ -152,6 +152,22 @@ int crypto_import_key_pair #ifdef WITH_EDDSA EVP_PKEY* eddsa = NULL; #endif +#ifdef WITH_SLHDSA + EVP_PKEY* slhdsa = NULL; +#endif + + + int result = 0; +#ifdef WITH_SLHDSA + const char *name = EVP_PKEY_get0_type_name(pkey); + if (strncmp(name, "SLH-DSA", 7) == 0) { + EVP_PKEY_up_ref(pkey); + slhdsa = pkey; + result = crypto_save_slhdsa(hSession, label, objID, objIDLen, noPublicKey, slhdsa); + EVP_PKEY_free(slhdsa); + return result; + } +#endif switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) { @@ -183,8 +199,6 @@ int crypto_import_key_pair } EVP_PKEY_free(pkey); - int result = 0; - if (rsa) { result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa); @@ -1138,3 +1152,155 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat) } #endif + +#ifdef WITH_SLHDSA + +// Save the key data in PKCS#11 +int crypto_save_slhdsa +( + CK_SESSION_HANDLE hSession, + char* label, + char* objID, + size_t objIDLen, + int noPublicKey, + EVP_PKEY* slhdsa +) +{ + slhdsa_key_material_t* keyMat = crypto_malloc_slhdsa(slhdsa); + if (keyMat == NULL) + { + fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n"); + return 1; + } + + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_SLHDSA; + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE; + if (noPublicKey) + { + ckToken = CK_FALSE; + } + CK_ATTRIBUTE pubTemplate[] = { + { CKA_CLASS, &pubClass, sizeof(pubClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_TOKEN, &ckToken, sizeof(ckToken) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_WRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_SLHDSA_PARAMS, keyMat->derPublicKey, keyMat->sizePublicKey }, + }; + CK_ATTRIBUTE privTemplate[] = { + { CKA_CLASS, &privClass, sizeof(privClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, label, strlen(label) }, + { CKA_ID, objID, objIDLen }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) }, + { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, + { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) }, + { CKA_SLHDSA_PARAMS, keyMat->derPrivateKey, keyMat->sizePrivateKey }, + }; + + CK_OBJECT_HANDLE hKey1, hKey2; + CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 12, &hKey1); + if (rv != CKR_OK) + { + fprintf(stderr, "ERROR: Could not save the private key in the token. " + "Maybe the algorithm is not supported.\n"); + crypto_free_slhdsa(keyMat); + return 1; + } + + rv = p11->C_CreateObject(hSession, pubTemplate, 9, &hKey2); + crypto_free_slhdsa(keyMat); + + if (rv != CKR_OK) + { + p11->C_DestroyObject(hSession, hKey1); + fprintf(stderr, "ERROR: Could not save the public key in the token.\n"); + return 1; + } + + printf("The key pair has been imported.\n"); + + return 0; +} + +// Convert the OpenSSL key to binary + +slhdsa_key_material_t* crypto_malloc_slhdsa(EVP_PKEY* pkey) +{ + if (pkey == NULL) + return NULL; + + slhdsa_key_material_t* keyMat = (slhdsa_key_material_t*)calloc(1, sizeof(slhdsa_key_material_t)); + if (keyMat == NULL) + return NULL; + + unsigned char* buf = NULL; + int len = 0; + + // DER encode public key + len = i2d_PUBKEY(pkey, NULL); + if (len <= 0) { + crypto_free_slhdsa(keyMat); + return NULL; + } + buf = (unsigned char*)OPENSSL_malloc(len); + if (!buf) { + crypto_free_slhdsa(keyMat); + return NULL; + } + unsigned char* p = buf; + if (i2d_PUBKEY(pkey, &p) <= 0) { + OPENSSL_free(buf); + crypto_free_slhdsa(keyMat); + return NULL; + } + keyMat->sizePublicKey = (unsigned long)len; + keyMat->derPublicKey = buf; + + // DER encode private key + len = i2d_PrivateKey(pkey, NULL); + if (len <= 0) { + crypto_free_slhdsa(keyMat); + return NULL; + } + buf = (unsigned char*)OPENSSL_malloc(len); + if (!buf) { + crypto_free_slhdsa(keyMat); + return NULL; + } + p = buf; + if (i2d_PrivateKey(pkey, &p) <= 0) { + OPENSSL_free(buf); + crypto_free_slhdsa(keyMat); + return NULL; + } + keyMat->sizePrivateKey = (unsigned long)len; + keyMat->derPrivateKey = buf; + + return keyMat; +} + +// Free the memory of the key +void crypto_free_slhdsa(slhdsa_key_material_t* keyMat) +{ + if (keyMat == NULL) + return; + + if (keyMat->derPrivateKey) + OPENSSL_free(keyMat->derPrivateKey); + + if (keyMat->derPublicKey) + OPENSSL_free(keyMat->derPublicKey); + + free(keyMat); +} + +#endif diff --git a/src/bin/util/softhsm2-util-ossl.h b/src/bin/util/softhsm2-util-ossl.h index 8fac6123b..59c96575c 100644 --- a/src/bin/util/softhsm2-util-ossl.h +++ b/src/bin/util/softhsm2-util-ossl.h @@ -38,7 +38,7 @@ #ifdef WITH_ECC #include #endif -#ifdef WITH_EDDSA +#if defined(WITH_EDDSA) || defined (WITH_SLHDSA) #include #endif @@ -142,6 +142,22 @@ typedef struct eddsa_key_material_t { } eddsa_key_material_t; #endif +#ifdef WITH_SLHDSA +typedef struct slhdsa_key_material_t { + CK_ULONG sizePrivateKey; + CK_ULONG sizePublicKey; + CK_VOID_PTR derPrivateKey; + CK_VOID_PTR derPublicKey; + + slhdsa_key_material_t() { + sizePrivateKey = 0; + sizePublicKey = 0; + derPrivateKey = NULL_PTR; + derPublicKey = NULL_PTR; + } +} slhdsa_key_material_t; +#endif + EVP_PKEY* crypto_read_file(char* filePath, char* filePIN); // RSA @@ -168,4 +184,11 @@ eddsa_key_material_t* crypto_malloc_eddsa(EVP_PKEY* eddsa); void crypto_free_eddsa(eddsa_key_material_t* keyMat); #endif +#ifdef WITH_SLHDSA +// SLHDSA +int crypto_save_slhdsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, EVP_PKEY* slhdsa); +slhdsa_key_material_t* crypto_malloc_slhdsa(EVP_PKEY* slhdsa); +void crypto_free_slhdsa(slhdsa_key_material_t* keyMat); +#endif + #endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H diff --git a/src/lib/P11Attributes.cpp b/src/lib/P11Attributes.cpp index fc9ab0041..f120bc816 100644 --- a/src/lib/P11Attributes.cpp +++ b/src/lib/P11Attributes.cpp @@ -2227,6 +2227,17 @@ bool P11AttrEcPoint::setDefault() return osobject->setAttribute(type, attr); } +/***************************************** + * CKA_SLHDSA_PARAMS + *****************************************/ + +// Set default value +bool P11AttrSLHDSAParams::setDefault() +{ + OSAttribute attr(ByteString("")); + return osobject->setAttribute(type, attr); +} + /***************************************** * CKA_GOSTR3410_PARAMS *****************************************/ diff --git a/src/lib/P11Attributes.h b/src/lib/P11Attributes.h index 6fd31f8d0..566ebe19c 100644 --- a/src/lib/P11Attributes.h +++ b/src/lib/P11Attributes.h @@ -1144,6 +1144,21 @@ class P11AttrEcPoint : public P11Attribute virtual bool setDefault(); }; +/***************************************** + * CKA_SLHDSA_PARAMS + *****************************************/ + +class P11AttrSLHDSAParams : public P11Attribute +{ +public: + // Constructor + P11AttrSLHDSAParams(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_SLHDSA_PARAMS; checks = ck1|inchecks; } + +protected: + // Set the default value of the attribute + virtual bool setDefault(); +}; + /***************************************** * CKA_GOSTR3410_PARAMS *****************************************/ diff --git a/src/lib/P11Objects.cpp b/src/lib/P11Objects.cpp index bbd021047..5142a938a 100644 --- a/src/lib/P11Objects.cpp +++ b/src/lib/P11Objects.cpp @@ -296,7 +296,6 @@ CK_RV P11Object::saveTemplate(Token *token, bool isPrivate, CK_ATTRIBUTE_PTR pTe { return CKR_GENERAL_ERROR; } - return CKR_OK; } @@ -930,6 +929,51 @@ bool P11EDPublicKeyObj::init(OSObject *inobject) return true; } +// Constructor +P11SLHPublicKeyObj::P11SLHPublicKeyObj() +{ + initialized = false; +} + +// Add attributes +bool P11SLHPublicKeyObj::init(OSObject *inobject) +{ + if (initialized) return true; + if (inobject == NULL) return false; + + if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_SLHDSA) { + OSAttribute setKeyType((unsigned long)CKK_SLHDSA); + inobject->setAttribute(CKA_KEY_TYPE, setKeyType); + } + + // Create parent + if (!P11PublicKeyObj::init(inobject)) return false; + + // Create attributes + P11Attribute* attrSLHDSAParams = new P11AttrSLHDSAParams(osobject,P11Attribute::ck3); + P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7); + + // Initialize the attributes + if + ( + !attrSLHDSAParams->init() || + !attrValue->init() + ) + { + ERROR_MSG("Could not initialize the attribute"); + delete attrSLHDSAParams; + delete attrValue; + return false; + } + + // Add them to the map + attributes[attrSLHDSAParams->getType()] = attrSLHDSAParams; + attributes[attrValue->getType()] = attrValue; + + initialized = true; + return true; +} + // Constructor P11DHPublicKeyObj::P11DHPublicKeyObj() { @@ -1335,6 +1379,51 @@ bool P11EDPrivateKeyObj::init(OSObject *inobject) return true; } +// Constructor +P11SLHPrivateKeyObj::P11SLHPrivateKeyObj() +{ + initialized = false; +} + +// Add attributes +bool P11SLHPrivateKeyObj::init(OSObject *inobject) +{ + if (initialized) return true; + if (inobject == NULL) return false; + + if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_SLHDSA) { + OSAttribute setKeyType((unsigned long)CKK_SLHDSA); + inobject->setAttribute(CKA_KEY_TYPE, setKeyType); + } + + // Create parent + if (!P11PrivateKeyObj::init(inobject)) return false; + + // Create attributes + P11Attribute* attrSLHDSAParams = new P11AttrSLHDSAParams(osobject,P11Attribute::ck4|P11Attribute::ck6); + P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7); + + // Initialize the attributes + if + ( + !attrSLHDSAParams->init() || + !attrValue->init() + ) + { + ERROR_MSG("Could not initialize the attribute"); + delete attrSLHDSAParams; + delete attrValue; + return false; + } + + // Add them to the map + attributes[attrSLHDSAParams->getType()] = attrSLHDSAParams; + attributes[attrValue->getType()] = attrValue; + + initialized = true; + return true; +} + // Constructor P11DHPrivateKeyObj::P11DHPrivateKeyObj() { diff --git a/src/lib/P11Objects.h b/src/lib/P11Objects.h index 9d223ac01..faa84651b 100644 --- a/src/lib/P11Objects.h +++ b/src/lib/P11Objects.h @@ -198,6 +198,19 @@ class P11EDPublicKeyObj : public P11PublicKeyObj bool initialized; }; +class P11SLHPublicKeyObj : public P11PublicKeyObj +{ +public: + // Constructor + P11SLHPublicKeyObj(); + + // Add attributes + virtual bool init(OSObject *inobject); + +protected: + bool initialized; +}; + class P11DHPublicKeyObj : public P11PublicKeyObj { public: @@ -287,6 +300,19 @@ class P11EDPrivateKeyObj : public P11PrivateKeyObj bool initialized; }; +class P11SLHPrivateKeyObj : public P11PrivateKeyObj +{ +public: + // Constructor + P11SLHPrivateKeyObj(); + + // Add attributes + virtual bool init(OSObject *inobject); + +protected: + bool initialized; +}; + class P11DHPrivateKeyObj : public P11PrivateKeyObj { public: diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp index 234fbfa18..b1c35e6c9 100644 --- a/src/lib/SoftHSM.cpp +++ b/src/lib/SoftHSM.cpp @@ -55,6 +55,7 @@ #include "ECPublicKey.h" #include "ECPrivateKey.h" #include "ECParameters.h" +#include "SLHParameters.h" #include "EDPublicKey.h" #include "EDPrivateKey.h" #include "DHParameters.h" @@ -140,6 +141,8 @@ static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERT *p11object = new P11GOSTPublicKeyObj(); else if (keyType == CKK_EC_EDWARDS) *p11object = new P11EDPublicKeyObj(); + else if (keyType == CKK_SLHDSA) + *p11object = new P11SLHPublicKeyObj(); else return CKR_ATTRIBUTE_VALUE_INVALID; break; @@ -157,6 +160,8 @@ static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERT *p11object = new P11GOSTPrivateKeyObj(); else if (keyType == CKK_EC_EDWARDS) *p11object = new P11EDPrivateKeyObj(); + else if (keyType == CKK_SLHDSA) + *p11object = new P11SLHPrivateKeyObj(); else return CKR_ATTRIBUTE_VALUE_INVALID; break; @@ -824,6 +829,10 @@ void SoftHSM::prepareSupportedMechanisms(std::maprecycleAsymmetricAlgorithm(eddsa); #endif + +#ifdef WITH_SLHDSA + AsymmetricAlgorithm* slhdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::SLHDSA); + if (slhdsa != NULL) + { + slhdsaMinSize = slhdsa->getMinKeySize(); + slhdsaMaxSize = slhdsa->getMaxKeySize(); + } + else + { + return CKR_GENERAL_ERROR; + } + CryptoFactory::i()->recycleAsymmetricAlgorithm(slhdsa); +#endif + pInfo->flags = 0; // initialize flags switch (type) { @@ -1314,6 +1342,18 @@ CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_ pInfo->ulMaxKeySize = eddsaMaxSize; pInfo->flags = CKF_SIGN | CKF_VERIFY; break; +#endif +#ifdef WITH_SLHDSA + case CKM_SLH_KEY_PAIR_GEN: + pInfo->ulMinKeySize = slhdsaMinSize; + pInfo->ulMaxKeySize = slhdsaMaxSize; + pInfo->flags = CKF_GENERATE_KEY_PAIR; + break; + case CKM_SLHDSA: + pInfo->ulMinKeySize = slhdsaMinSize; + pInfo->ulMaxKeySize = slhdsaMaxSize; + pInfo->flags = CKF_SIGN | CKF_VERIFY; + break; #endif case CKM_CONCATENATE_DATA_AND_BASE: case CKM_CONCATENATE_BASE_AND_DATA: @@ -4153,6 +4193,9 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan #endif #ifdef WITH_EDDSA bool isEDDSA = false; +#endif +#ifdef WITH_SLHDSA + bool isSLHDSA = false; #endif switch(pMechanism->mechanism) { case CKM_RSA_PKCS: @@ -4419,6 +4462,13 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan bAllowMultiPartOp = false; isEDDSA = true; break; +#endif +#ifdef WITH_SLHDSA + case CKM_SLHDSA: + mechanism = AsymMech::SLHDSA; + bAllowMultiPartOp = false; + isSLHDSA = true; + break; #endif default: return CKR_MECHANISM_INVALID; @@ -4505,6 +4555,27 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan return CKR_GENERAL_ERROR; } } +#endif +#ifdef WITH_SLHDSA + else if (isSLHDSA) + { + asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::SLHDSA); + if (asymCrypto == NULL) return CKR_MECHANISM_INVALID; + + privateKey = asymCrypto->newPrivateKey(); + if (privateKey == NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto); + return CKR_HOST_MEMORY; + } + + if (getSLHPrivateKey((SLHPrivateKey*)privateKey, token, key) != CKR_OK) + { + asymCrypto->recyclePrivateKey(privateKey); + CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto); + return CKR_GENERAL_ERROR; + } + } #endif else { @@ -4687,7 +4758,7 @@ static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, C // Check size if (signature.size() != size) { - ERROR_MSG("The size of the signature differs from the size of the mechanism"); + ERROR_MSG("The size of the signature differs from the size of the mechanism %d, %d", signature.size(), size); session->resetOp(); return CKR_GENERAL_ERROR; } @@ -5156,6 +5227,9 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech #endif #ifdef WITH_EDDSA bool isEDDSA = false; +#endif +#ifdef WITH_SLHDSA + bool isSLHDSA = false; #endif switch(pMechanism->mechanism) { case CKM_RSA_PKCS: @@ -5420,6 +5494,13 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech bAllowMultiPartOp = false; isEDDSA = true; break; +#endif +#ifdef WITH_SLHDSA + case CKM_SLHDSA: + mechanism = AsymMech::SLHDSA; + bAllowMultiPartOp = false; + isSLHDSA = true; + break; #endif default: return CKR_MECHANISM_INVALID; @@ -5506,6 +5587,27 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech return CKR_GENERAL_ERROR; } } +#endif +#ifdef WITH_SLHDSA + else if (isSLHDSA) + { + asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::SLHDSA); + if (asymCrypto == NULL) return CKR_MECHANISM_INVALID; + + publicKey = asymCrypto->newPublicKey(); + if (publicKey == NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto); + return CKR_HOST_MEMORY; + } + + if (getSLHPublicKey((SLHPublicKey*)publicKey, token, key) != CKR_OK) + { + asymCrypto->recyclePublicKey(publicKey); + CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto); + return CKR_GENERAL_ERROR; + } + } #endif else { @@ -6089,7 +6191,7 @@ CK_RV SoftHSM::C_GenerateKeyPair Session* session = (Session*)handleManager->getSession(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation. + // Check the mechanism, only accept RSA, DSA, EC, SLH and DH key pair generation. CK_KEY_TYPE keyType; switch (pMechanism->mechanism) { @@ -6116,6 +6218,11 @@ CK_RV SoftHSM::C_GenerateKeyPair case CKM_EC_EDWARDS_KEY_PAIR_GEN: keyType = CKK_EC_EDWARDS; break; +#endif +#ifdef WITH_SLHDSA + case CKM_SLH_KEY_PAIR_GEN: + keyType = CKK_SLHDSA; + break; #endif default: return CKR_MECHANISM_INVALID; @@ -6144,12 +6251,15 @@ CK_RV SoftHSM::C_GenerateKeyPair return CKR_TEMPLATE_INCONSISTENT; if (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN && keyType != CKK_EC_EDWARDS) return CKR_TEMPLATE_INCONSISTENT; + if (pMechanism->mechanism == CKM_SLH_KEY_PAIR_GEN && keyType != CKK_SLHDSA) + return CKR_TEMPLATE_INCONSISTENT; // Extract information from the private key template that is needed to create the object. CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY; CK_BBOOL isprivateKeyToken = CK_FALSE; CK_BBOOL isprivateKeyPrivate = CK_TRUE; bool isPrivateKeyImplicit = true; + extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit); // Report errors caused by accidental template mix-ups in the application using this cryptoki lib. @@ -6167,6 +6277,8 @@ CK_RV SoftHSM::C_GenerateKeyPair return CKR_TEMPLATE_INCONSISTENT; if (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN && keyType != CKK_EC_EDWARDS) return CKR_TEMPLATE_INCONSISTENT; + if (pMechanism->mechanism == CKM_SLH_KEY_PAIR_GEN && keyType != CKK_SLHDSA) + return CKR_TEMPLATE_INCONSISTENT; // Check user credentials CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate); @@ -6230,6 +6342,16 @@ CK_RV SoftHSM::C_GenerateKeyPair ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate); } + // Generate SLHDSA keys + if (pMechanism->mechanism == CKM_SLH_KEY_PAIR_GEN) + { + return this->generateSLH(hSession, + pPublicKeyTemplate, ulPublicKeyAttributeCount, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + phPublicKey, phPrivateKey, + ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate); + } + // Generate EDDSA keys if (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) { @@ -9933,6 +10055,253 @@ CK_RV SoftHSM::generateED return rv; } + +// Generate an SLHDSA key pair +CK_RV SoftHSM::generateSLH +(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey, + CK_BBOOL isPublicKeyOnToken, + CK_BBOOL isPublicKeyPrivate, + CK_BBOOL isPrivateKeyOnToken, + CK_BBOOL isPrivateKeyPrivate) +{ + *phPublicKey = CK_INVALID_HANDLE; + *phPrivateKey = CK_INVALID_HANDLE; + + // Get the session + Session* session = (Session*)handleManager->getSession(hSession); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + + // Get the token + Token* token = session->getToken(); + if (token == NULL) + return CKR_GENERAL_ERROR; + + // Extract desired key information + ByteString params; + for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++) + { + switch (pPublicKeyTemplate[i].type) + { + case CKA_SLHDSA_PARAMS: + params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen); + break; + default: + break; + } + } + + // The parameters must be specified to be able to generate a key pair. + if (params.size() == 0) { + INFO_MSG("Missing parameter(s) in pPublicKeyTemplate"); + return CKR_TEMPLATE_INCOMPLETE; + } + + // Set the parameters + SLHParameters p; + p.setName(params); + + // Generate key pair + AsymmetricKeyPair* kp = NULL; + AsymmetricAlgorithm* slh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::SLHDSA); + if (slh == NULL) return CKR_GENERAL_ERROR; + if (!slh->generateKeyPair(&kp, &p)) + { + ERROR_MSG("Could not generate key pair"); + CryptoFactory::i()->recycleAsymmetricAlgorithm(slh); + return CKR_GENERAL_ERROR; + } + + SLHPublicKey* pub = (SLHPublicKey*) kp->getPublicKey(); + SLHPrivateKey* priv = (SLHPrivateKey*) kp->getPrivateKey(); + + CK_RV rv = CKR_OK; + + // Create a public key using C_CreateObject + if (rv == CKR_OK) + { + const CK_ULONG maxAttribs = 32; + CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY; + CK_KEY_TYPE publicKeyType = CKK_SLHDSA; + CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = { + { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) }, + { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) }, + { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) }, + { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) }, + }; + CK_ULONG publicKeyAttribsCount = 4; + + // Add the additional + if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount)) + rv = CKR_TEMPLATE_INCONSISTENT; + for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i) + { + switch (pPublicKeyTemplate[i].type) + { + case CKA_CLASS: + case CKA_TOKEN: + case CKA_PRIVATE: + case CKA_KEY_TYPE: + continue; + default: + publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i]; + } + } + + if (rv == CKR_OK) + { + rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE); + } + + // Store the attributes that are being supplied by the key generation to the object + if (rv == CKR_OK) + { + OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey); + if (osobject == NULL_PTR || !osobject->isValid()) { + rv = CKR_FUNCTION_FAILED; + } else if (osobject->startTransaction()) { + bool bOK = true; + + // Common Key Attributes + bOK = bOK && osobject->setAttribute(CKA_LOCAL,true); + CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_SLH_KEY_PAIR_GEN; + bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism); + + // SLHDSA Public Key Attributes + ByteString value; + if (isPublicKeyPrivate) + { + token->encrypt(pub->getDerPublicKey(), value); + } + else + { + value = pub->getDerPublicKey(); + } + bOK = bOK && osobject->setAttribute(CKA_SLHDSA_PARAMS, value); + + if (bOK) + bOK = osobject->commitTransaction(); + else + osobject->abortTransaction(); + + if (!bOK) + rv = CKR_FUNCTION_FAILED; + } else + rv = CKR_FUNCTION_FAILED; + } + } + + // Create a private key using C_CreateObject + if (rv == CKR_OK) + { + const CK_ULONG maxAttribs = 32; + CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE privateKeyType = CKK_SLHDSA; + CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = { + { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) }, + { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) }, + { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) }, + { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) }, + }; + CK_ULONG privateKeyAttribsCount = 4; + if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount)) + rv = CKR_TEMPLATE_INCONSISTENT; + for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i) + { + switch (pPrivateKeyTemplate[i].type) + { + case CKA_CLASS: + case CKA_TOKEN: + case CKA_PRIVATE: + case CKA_KEY_TYPE: + continue; + default: + privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i]; + } + } + + if (rv == CKR_OK) + { + rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE); + } + + // Store the attributes that are being supplied by the key generation to the object + if (rv == CKR_OK) + { + OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey); + if (osobject == NULL_PTR || !osobject->isValid()) { + rv = CKR_FUNCTION_FAILED; + } else if (osobject->startTransaction()) { + bool bOK = true; + + // Common Key Attributes + bOK = bOK && osobject->setAttribute(CKA_LOCAL,true); + CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_SLH_KEY_PAIR_GEN; + bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism); + + // Common Private Key Attributes + bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false); + bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive); + bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false; + bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable); + + // SLHDSA Private Key Attributes + ByteString value; + if (isPrivateKeyPrivate) + { + token->encrypt(priv->getDerPrivateKey(), value); + } + else + { + value = priv->getDerPrivateKey(); + } + bOK = bOK && osobject->setAttribute(CKA_SLHDSA_PARAMS, value); + + if (bOK) + bOK = osobject->commitTransaction(); + else + osobject->abortTransaction(); + + if (!bOK) + rv = CKR_FUNCTION_FAILED; + } else + rv = CKR_FUNCTION_FAILED; + } + } + + // Clean up + slh->recycleKeyPair(kp); + CryptoFactory::i()->recycleAsymmetricAlgorithm(slh); + + // Remove keys that may have been created already when the function fails. + if (rv != CKR_OK) + { + if (*phPrivateKey != CK_INVALID_HANDLE) + { + OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey); + handleManager->destroyObject(*phPrivateKey); + if (ospriv) ospriv->destroyObject(); + *phPrivateKey = CK_INVALID_HANDLE; + } + + if (*phPublicKey != CK_INVALID_HANDLE) + { + OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey); + handleManager->destroyObject(*phPublicKey); + if (ospub) ospub->destroyObject(); + *phPublicKey = CK_INVALID_HANDLE; + } + } + + return rv; +} + // Generate a DH key pair CK_RV SoftHSM::generateDH (CK_SESSION_HANDLE hSession, @@ -12281,7 +12650,6 @@ CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTempla return rv; } - // Change order of attributes const CK_ULONG maxAttribs = 32; CK_ATTRIBUTE attribs[maxAttribs]; @@ -12304,9 +12672,7 @@ CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTempla } } for (CK_ULONG i=0; i < saveAttribsCount; i++) - { attribs[attribsCount++] = saveAttribs[i]; - } P11Object* p11object = NULL; rv = newP11Object(objClass,keyType,certType,&p11object); @@ -12316,13 +12682,9 @@ CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTempla // Create the object in session or on the token OSObject *object = NULL_PTR; if (isOnToken) - { object = (OSObject*) token->createObject(); - } else - { object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE); - } if (object == NULL || !p11object->init(object)) { @@ -12662,6 +13024,62 @@ CK_RV SoftHSM::getEDPublicKey(EDPublicKey* publicKey, Token* token, OSObject* ke return CKR_OK; } +CK_RV SoftHSM::getSLHPrivateKey(SLHPrivateKey* privateKey, Token* token, OSObject* key) +{ + if (privateKey == NULL) return CKR_ARGUMENTS_BAD; + if (token == NULL) return CKR_ARGUMENTS_BAD; + if (key == NULL) return CKR_ARGUMENTS_BAD; + + // Get the CKA_PRIVATE attribute, when the attribute is not present use default false + bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false); + + // SLHDSA Private Key Attributes + ByteString value; + if (isKeyPrivate) + { + bool bOK = true; + bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SLHDSA_PARAMS), value); + if (!bOK) + return CKR_GENERAL_ERROR; + } + else + { + value = key->getByteStringValue(CKA_SLHDSA_PARAMS); + } + + privateKey->setDerPrivateKey(value); + + return CKR_OK; +} + +CK_RV SoftHSM::getSLHPublicKey(SLHPublicKey* publicKey, Token* token, OSObject* key) +{ + if (publicKey == NULL) return CKR_ARGUMENTS_BAD; + if (token == NULL) return CKR_ARGUMENTS_BAD; + if (key == NULL) return CKR_ARGUMENTS_BAD; + + // Get the CKA_PRIVATE attribute, when the attribute is not present use default false + bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false); + + // SLHDSA Public Key Attributes + ByteString value; + if (isKeyPrivate) + { + bool bOK = true; + bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SLHDSA_PARAMS), value); + if (!bOK) + return CKR_GENERAL_ERROR; + } + else + { + value = key->getByteStringValue(CKA_SLHDSA_PARAMS); + } + + publicKey->setDerPublicKey(value); + return CKR_OK; +} + + CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key) { if (privateKey == NULL) return CKR_ARGUMENTS_BAD; diff --git a/src/lib/SoftHSM.h b/src/lib/SoftHSM.h index 644686b2b..c7fdbdb88 100644 --- a/src/lib/SoftHSM.h +++ b/src/lib/SoftHSM.h @@ -48,6 +48,8 @@ #include "ECPrivateKey.h" #include "EDPublicKey.h" #include "EDPrivateKey.h" +#include "SLHPublicKey.h" +#include "SLHPrivateKey.h" #include "DHPublicKey.h" #include "DHPrivateKey.h" #include "GOSTPublicKey.h" @@ -313,6 +315,20 @@ class SoftHSM CK_BBOOL isPrivateKeyOnToken, CK_BBOOL isPrivateKeyPrivate ); + CK_RV generateSLH + ( + CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey, + CK_BBOOL isPublicKeyOnToken, + CK_BBOOL isPublicKeyPrivate, + CK_BBOOL isPrivateKeyOnToken, + CK_BBOOL isPrivateKeyPrivate + ); CK_RV generateDH ( CK_SESSION_HANDLE hSession, @@ -428,6 +444,8 @@ class SoftHSM CK_RV getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key); CK_RV getEDPrivateKey(EDPrivateKey* privateKey, Token* token, OSObject* key); CK_RV getEDPublicKey(EDPublicKey* publicKey, Token* token, OSObject* key); + CK_RV getSLHPrivateKey(SLHPrivateKey* privateKey, Token* token, OSObject* key); + CK_RV getSLHPublicKey(SLHPublicKey* publicKey, Token* token, OSObject* key); CK_RV getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key); CK_RV getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams); CK_RV getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData); diff --git a/src/lib/crypto/AsymmetricAlgorithm.h b/src/lib/crypto/AsymmetricAlgorithm.h index 52519db65..9174dc1b7 100644 --- a/src/lib/crypto/AsymmetricAlgorithm.h +++ b/src/lib/crypto/AsymmetricAlgorithm.h @@ -53,7 +53,8 @@ struct AsymAlgo ECDH, ECDSA, GOST, - EDDSA + EDDSA, + SLHDSA }; }; @@ -92,7 +93,8 @@ struct AsymMech ECDSA_SHA512, GOST, GOST_GOST, - EDDSA + EDDSA, + SLHDSA }; }; diff --git a/src/lib/crypto/CMakeLists.txt b/src/lib/crypto/CMakeLists.txt index 4b7c22e65..a3e17ee0f 100644 --- a/src/lib/crypto/CMakeLists.txt +++ b/src/lib/crypto/CMakeLists.txt @@ -20,10 +20,13 @@ set(SOURCES AESKey.cpp DSAPrivateKey.cpp DSAPublicKey.cpp ECParameters.cpp + SLHParameters.cpp ECPrivateKey.cpp ECPublicKey.cpp EDPrivateKey.cpp EDPublicKey.cpp + SLHPrivateKey.cpp + SLHPublicKey.cpp GOSTPrivateKey.cpp GOSTPublicKey.cpp HashAlgorithm.cpp @@ -58,6 +61,10 @@ if(WITH_OPENSSL) OSSLEDKeyPair.cpp OSSLEDPrivateKey.cpp OSSLEDPublicKey.cpp + OSSLSLHDSA.cpp + OSSLSLHKeyPair.cpp + OSSLSLHPrivateKey.cpp + OSSLSLHPublicKey.cpp OSSLEVPCMacAlgorithm.cpp OSSLEVPHashAlgorithm.cpp OSSLEVPMacAlgorithm.cpp diff --git a/src/lib/crypto/Makefile.am b/src/lib/crypto/Makefile.am index e23848fa2..5620c4a6d 100644 --- a/src/lib/crypto/Makefile.am +++ b/src/lib/crypto/Makefile.am @@ -20,10 +20,13 @@ libsofthsm_crypto_la_SOURCES = AESKey.cpp \ DSAPublicKey.cpp \ DSAPrivateKey.cpp \ ECParameters.cpp \ + SLHParameters.cpp \ ECPublicKey.cpp \ ECPrivateKey.cpp \ EDPublicKey.cpp \ EDPrivateKey.cpp \ + SLHPublicKey.cpp \ + SLHPrivateKey.cpp \ GOSTPublicKey.cpp \ GOSTPrivateKey.cpp \ HashAlgorithm.cpp \ @@ -64,6 +67,11 @@ libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \ OSSLEDKeyPair.cpp \ OSSLEDPrivateKey.cpp \ OSSLEDPublicKey.cpp \ + OSSLSLHDSA.cpp \ + OSSLSLHKeyPair.cpp \ + OSSLSLHPrivateKey.cpp \ + OSSLSLHPublicKey.cpp \ + OSSLSLHUtil.cpp \ OSSLEVPHashAlgorithm.cpp \ OSSLEVPMacAlgorithm.cpp \ OSSLEVPCMacAlgorithm.cpp \ diff --git a/src/lib/crypto/OSSLCryptoFactory.cpp b/src/lib/crypto/OSSLCryptoFactory.cpp index db22998ad..380187932 100644 --- a/src/lib/crypto/OSSLCryptoFactory.cpp +++ b/src/lib/crypto/OSSLCryptoFactory.cpp @@ -58,6 +58,9 @@ #ifdef WITH_EDDSA #include "OSSLEDDSA.h" #endif +#ifdef WITH_SLHDSA +#include "OSSLSLHDSA.h" +#endif #include #include @@ -347,6 +350,10 @@ AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type al #ifdef WITH_EDDSA case AsymAlgo::EDDSA: return new OSSLEDDSA(); +#endif +#ifdef WITH_SLHDSA + case AsymAlgo::SLHDSA: + return new OSSLSLHDSA(); #endif default: break; diff --git a/src/lib/crypto/OSSLSLHDSA.cpp b/src/lib/crypto/OSSLSLHDSA.cpp new file mode 100644 index 000000000..063c2995f --- /dev/null +++ b/src/lib/crypto/OSSLSLHDSA.cpp @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHDSA.cpp + + OpenSSL SLHDSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_SLHDSA +#include "log.h" +#include "OSSLSLHDSA.h" +#include "CryptoFactory.h" +#include "SLHParameters.h" +#include "OSSLSLHKeyPair.h" +#include "OSSLComp.h" +#include "OSSLUtil.h" +#include +#include +#include +#include +#include + +// Signing functions +bool OSSLSLHDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + if (mechanism != AsymMech::SLHDSA) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLSLHPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + OSSLSLHPrivateKey* pk = (OSSLSLHPrivateKey*) privateKey; + EVP_PKEY* pkey = pk->getOSSLKey(); + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL private key"); + + return false; + } + + // Perform the signature operation + size_t len = pk->getOrderLength(); + if (len == 0) + { + ERROR_MSG("Could not get the order length"); + return false; + } + signature.resize(len); + memset(&signature[0], 0, len); + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + if (!EVP_DigestSignInit(ctx, NULL, NULL, NULL, pkey)) + { + ERROR_MSG("SLHDSA sign init failed (0x%08X)", ERR_get_error()); + EVP_MD_CTX_free(ctx); + return false; + } + if (!EVP_DigestSign(ctx, &signature[0], &len, dataToSign.const_byte_str(), dataToSign.size())) + { + ERROR_MSG("SLHDSA sign failed (0x%08X)", ERR_get_error()); + + unsigned long err = ERR_get_error(); + char buf[256]; + ERR_error_string_n(err, buf, sizeof(buf)); + ERROR_MSG("SLHDSA sign failed: %s\n", buf); + ERROR_MSG("Key type: %s\n", EVP_PKEY_get0_type_name(pkey)); + + EVP_MD_CTX_free(ctx); + return false; + } + EVP_MD_CTX_free(ctx); + return true; +} + +bool OSSLSLHDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("SLHDSA does not support multi part signing"); + + return false; +} + +bool OSSLSLHDSA::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("SLHDSA does not support multi part signing"); + + return false; +} + +bool OSSLSLHDSA::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("SLHDSA does not support multi part signing"); + + return false; +} + +// Verification functions +bool OSSLSLHDSA::verify(PublicKey* publicKey, const ByteString& originalData, + const ByteString& signature, const AsymMech::Type mechanism, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + if (mechanism != AsymMech::SLHDSA) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + return false; + } + + // Check if the private key is the right type + if (!publicKey->isOfType(OSSLSLHPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + OSSLSLHPublicKey* pk = (OSSLSLHPublicKey*) publicKey; + EVP_PKEY* pkey = pk->getOSSLKey(); + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL public key"); + + return false; + } + + // Perform the verify operation + size_t len = pk->getOrderLength(); + if (len == 0) + { + ERROR_MSG("Could not get the order length"); + return false; + } + if (signature.size() != len) + { + ERROR_MSG("Invalid buffer length"); + return false; + } + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey)) + { + ERROR_MSG("SLHDSA verify init failed (0x%08X)", ERR_get_error()); + EVP_MD_CTX_free(ctx); + return false; + } + int ret = EVP_DigestVerify(ctx, signature.const_byte_str(), len, originalData.const_byte_str(), originalData.size()); + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("SLHDSA verify failed (0x%08X)", ERR_get_error()); + EVP_MD_CTX_free(ctx); + return false; + } + EVP_MD_CTX_free(ctx); + return true; +} + +bool OSSLSLHDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("SLHDSA does not support multi part verifying"); + + return false; +} + +bool OSSLSLHDSA::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("SLHDSA does not support multi part verifying"); + + return false; +} + +bool OSSLSLHDSA::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("SLHDSA does not support multi part verifying"); + + return false; +} + +// Encryption functions +bool OSSLSLHDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("SLHDSA does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLSLHDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("SLHDSA does not support decryption"); + + return false; +} + +// Key factory +bool OSSLSLHDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(SLHParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for SLHDSA key generation"); + + return false; + } + + SLHParameters* params = (SLHParameters*) parameters; + + const unsigned char* name = params->getName().const_byte_str(); + + // Generate the key-pair + EVP_PKEY* pkey = NULL; + EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(NULL, reinterpret_cast(name), NULL); + if (ctx == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL SLHDSA context"); + return false; + } + int ret = EVP_PKEY_keygen_init(ctx); + if (ret != 1) + { + ERROR_MSG("SLHDSA key generation init failed (0x%08X)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + return false; + } + ret = EVP_PKEY_keygen(ctx, &pkey); + if (ret != 1) + { + ERROR_MSG("SLHDSA key generation failed (0x%08X)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + return false; + } + EVP_PKEY_CTX_free(ctx); + + // Create an asymmetric key-pair object to return + OSSLSLHKeyPair* kp = new OSSLSLHKeyPair(); + + ((OSSLSLHPublicKey*) kp->getPublicKey())->setFromOSSL(pkey); + ((OSSLSLHPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey); + + *ppKeyPair = kp; + + // Release the key + EVP_PKEY_free(pkey); + + return true; +} + +bool OSSLSLHDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) +{ + ERROR_MSG("SLHDSA does not support key derivation"); + return false; +} + +unsigned long OSSLSLHDSA::getMinKeySize() +{ + return 7856; +} + +unsigned long OSSLSLHDSA::getMaxKeySize() +{ + return 49856; +} + +bool OSSLSLHDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData) +{ + // Check input + if ((ppKeyPair == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + ByteString dPub = ByteString::chainDeserialise(serialisedData); + ByteString dPriv = ByteString::chainDeserialise(serialisedData); + + OSSLSLHKeyPair* kp = new OSSLSLHKeyPair(); + + bool rv = true; + + if (!((SLHPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((SLHPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLSLHDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLSLHPublicKey* pub = new OSSLSLHPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLSLHDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLSLHPrivateKey* priv = new OSSLSLHPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLSLHDSA::newPublicKey() +{ + return (PublicKey*) new OSSLSLHPublicKey(); +} + +PrivateKey* OSSLSLHDSA::newPrivateKey() +{ + return (PrivateKey*) new OSSLSLHPrivateKey(); +} + +AsymmetricParameters* OSSLSLHDSA::newParameters() +{ + return (AsymmetricParameters*) new SLHParameters(); +} + +bool OSSLSLHDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + SLHParameters* params = new SLHParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} +#endif diff --git a/src/lib/crypto/OSSLSLHDSA.h b/src/lib/crypto/OSSLSLHDSA.h new file mode 100644 index 000000000..19b56c7ae --- /dev/null +++ b/src/lib/crypto/OSSLSLHDSA.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHDSA.h + + OpenSSL SLHDSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSLHDSA_H +#define _SOFTHSM_V2_OSSLSLHDSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include + +class OSSLSLHDSA : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLSLHDSA() { } + + // Signing functions + virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0); + virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0); + virtual bool signUpdate(const ByteString& dataToSign); + virtual bool signFinal(ByteString& signature); + + // Verification functions + virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0); + virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0); + virtual bool verifyUpdate(const ByteString& originalData); + virtual bool verifyFinal(const ByteString& signature); + + // Encryption functions + virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding); + + // Decryption functions + virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding); + + // Key factory + virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL); + virtual unsigned long getMinKeySize(); + virtual unsigned long getMaxKeySize(); + virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey); + virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData); + virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData); + virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData); + virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData); + virtual PublicKey* newPublicKey(); + virtual PrivateKey* newPrivateKey(); + virtual AsymmetricParameters* newParameters(); + +private: +}; + +#endif // !_SOFTHSM_V2_OSSLSLHDSA_H + diff --git a/src/lib/crypto/OSSLSLHKeyPair.cpp b/src/lib/crypto/OSSLSLHKeyPair.cpp new file mode 100644 index 000000000..bae48efa8 --- /dev/null +++ b/src/lib/crypto/OSSLSLHKeyPair.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHKeyPair.cpp + + OpenSSL SLHDSA key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_SLHDSA +#include "log.h" +#include "OSSLSLHKeyPair.h" + +// Set the public key +void OSSLSLHKeyPair::setPublicKey(OSSLSLHPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLSLHKeyPair::setPrivateKey(OSSLSLHPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLSLHKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLSLHKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLSLHKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLSLHKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/src/lib/crypto/OSSLSLHKeyPair.h b/src/lib/crypto/OSSLSLHKeyPair.h new file mode 100644 index 000000000..e560cfba8 --- /dev/null +++ b/src/lib/crypto/OSSLSLHKeyPair.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHKeyPair.h + + OpenSSL SLHDSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSLHKEYPAIR_H +#define _SOFTHSM_V2_OSSLSLHKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLSLHPublicKey.h" +#include "OSSLSLHPrivateKey.h" + +class OSSLSLHKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLSLHPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLSLHPrivateKey& privateKey); + + // Return the public key + virtual PublicKey* getPublicKey(); + virtual const PublicKey* getConstPublicKey() const; + + // Return the private key + virtual PrivateKey* getPrivateKey(); + virtual const PrivateKey* getConstPrivateKey() const; + +private: + // The public key + OSSLSLHPublicKey pubKey; + + // The private key + OSSLSLHPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLSLHKEYPAIR_H + diff --git a/src/lib/crypto/OSSLSLHPrivateKey.cpp b/src/lib/crypto/OSSLSLHPrivateKey.cpp new file mode 100644 index 000000000..ef102564d --- /dev/null +++ b/src/lib/crypto/OSSLSLHPrivateKey.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHPrivateKey.cpp + + OpenSSL SLHDSA private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_SLHDSA +#include "log.h" +#include "OSSLSLHPrivateKey.h" +#include "OSSLUtil.h" +#include +#include +#include +#include "OSSLSLHUtil.h" + +// Constructors +OSSLSLHPrivateKey::OSSLSLHPrivateKey() +{ + pkey = NULL; + name = NULL; +} + +OSSLSLHPrivateKey::OSSLSLHPrivateKey(const EVP_PKEY* inPKEY) +{ + pkey = NULL; + name = NULL; + + setFromOSSL(inPKEY); +} + +// Destructor +OSSLSLHPrivateKey::~OSSLSLHPrivateKey() +{ + if (pkey) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + name = NULL; +} + +// The type +/*static*/ const char* OSSLSLHPrivateKey::type = "OpenSSL SLHDSA Private Key"; + +unsigned long OSSLSLHPrivateKey::getOrderLength() const +{ + return OSSLSLH::getSignatureSizeFromName(name); +} + +// Set from OpenSSL representation +void OSSLSLHPrivateKey::setFromOSSL(const EVP_PKEY* inPKEY) +{ + if (EVP_PKEY_get0_type_name(inPKEY) == NULL) + { + ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); + return; + } + name = EVP_PKEY_get0_type_name(inPKEY); + + // Serialize to DER (PKCS#8), like function PKCS8Encode + ByteString der; + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(inPKEY); + if (!p8inf) + { ERROR_MSG("EVP_PKEY2PKCS8 info error"); return; } + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len <= 0) + { + ERROR_MSG("i2d_PKCS8_PRIV_KEY_INFO info error, len is smaller or eq than zero"); + return; + } + + der.resize(len); + unsigned char* p = &der[0]; + if (i2d_PKCS8_PRIV_KEY_INFO(p8inf, &p) != len) + { ERROR_MSG("i2d_PKCS8_PRIV_KEY_INFO serialization error"); return; } + + PKCS8_PRIV_KEY_INFO_free(p8inf); + + setDerPrivateKey(der); + return; +} + +// Check if the key is of the given type +bool OSSLSLHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +void OSSLSLHPrivateKey::setDerPrivateKey(const ByteString& inSk) +{ + SLHPrivateKey::setDerPrivateKey(inSk); + + getOSSLKey(); + if (EVP_PKEY_get0_type_name(pkey) == NULL) + { ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); return; } + + name = EVP_PKEY_get0_type_name(pkey); + + if (pkey) + { EVP_PKEY_free(pkey); pkey = NULL; } +} + +// Encode into PKCS#8 DER +ByteString OSSLSLHPrivateKey::PKCS8Encode() +{ + ByteString der; + EVP_PKEY* key = getOSSLKey(); + if (key == NULL) return der; + PKCS8_PRIV_KEY_INFO* p8 = EVP_PKEY2PKCS8(key); + if (p8 == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL); + if (len <= 0) + { + PKCS8_PRIV_KEY_INFO_free(p8); + return der; + } + der.resize(len); + unsigned char* p = &der[0]; + i2d_PKCS8_PRIV_KEY_INFO(p8, &p); + PKCS8_PRIV_KEY_INFO_free(p8); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLSLHPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* p = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + if (p8 == NULL) return false; + EVP_PKEY* key = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (key == NULL) return false; + setFromOSSL(key); + EVP_PKEY_free(key); + return true; +} + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLSLHPrivateKey::getOSSLKey() +{ + if (pkey == NULL) createOSSLKey(); + + return pkey; +} + +// Create the OpenSSL representation of the key +void OSSLSLHPrivateKey::createOSSLKey() +{ + // Deserialize from DER (PKCS#8), like function PKCS8Decode + if (pkey != NULL) return; + + const unsigned char *p = &derPrivateKey[0]; + PKCS8_PRIV_KEY_INFO* p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, derPrivateKey.size()); + if (!p8inf) + ERROR_MSG("d2i_PKCS8_PRIV_KEY_INFO; error on decoding pkey"); + pkey = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + + if (!pkey) + ERROR_MSG("EVP_PKCS82PKEY; Error on deserialize derPrivateKey to pkey"); + + if (EVP_PKEY_get0_type_name(pkey) == NULL) + { ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); return; } + name = EVP_PKEY_get0_type_name(pkey); +} + + +#endif diff --git a/src/lib/crypto/OSSLSLHPrivateKey.h b/src/lib/crypto/OSSLSLHPrivateKey.h new file mode 100644 index 000000000..68be7dd90 --- /dev/null +++ b/src/lib/crypto/OSSLSLHPrivateKey.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHPrivateKey.h + + OpenSSL SLHDSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSLHPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLSLHPRIVATEKEY_H + +#include "config.h" +#include "SLHPrivateKey.h" +#include +#include + +class OSSLSLHPrivateKey : public SLHPrivateKey +{ +public: + // Constructors + OSSLSLHPrivateKey(); + + OSSLSLHPrivateKey(const EVP_PKEY* inPKEY); + + // Destructor + virtual ~OSSLSLHPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the base point order length + virtual unsigned long getOrderLength() const; + + // Setters for the SLHDSA private key components + virtual void setDerPrivateKey(const ByteString& inSk); + + // Encode into PKCS#8 DER + virtual ByteString PKCS8Encode(); + + // Decode from PKCS#8 BER + virtual bool PKCS8Decode(const ByteString& ber); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EVP_PKEY* inPKEY); + + // Retrieve the OpenSSL representation of the key + EVP_PKEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + const char* name; + EVP_PKEY* pkey; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLSLHPRIVATEKEY_H + diff --git a/src/lib/crypto/OSSLSLHPublicKey.cpp b/src/lib/crypto/OSSLSLHPublicKey.cpp new file mode 100644 index 000000000..0ba92d2fa --- /dev/null +++ b/src/lib/crypto/OSSLSLHPublicKey.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHPublicKey.cpp + + OpenSSL SLHDSA public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_SLHDSA +#include "log.h" +#include "DerUtil.h" +#include "OSSLSLHPublicKey.h" +#include "OSSLUtil.h" +#include +#include +#include "OSSLSLHUtil.h" + +// Constructors +OSSLSLHPublicKey::OSSLSLHPublicKey() +{ + pkey = NULL; + name = NULL; +} + +OSSLSLHPublicKey::OSSLSLHPublicKey(const EVP_PKEY* inPKEY) +{ + name = NULL; + pkey = NULL; + + setFromOSSL(inPKEY); +} + +// Destructor +OSSLSLHPublicKey::~OSSLSLHPublicKey() +{ + if (pkey) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + name = NULL; +} + +// The type +/*static*/ const char* OSSLSLHPublicKey::type = "OpenSSL SLHDSA Public Key"; + +unsigned long OSSLSLHPublicKey::getOrderLength() const +{ + return OSSLSLH::getSignatureSizeFromName(name); +} + +// Set from OpenSSL representation +void OSSLSLHPublicKey::setFromOSSL(const EVP_PKEY* inPKEY) +{ + if (EVP_PKEY_get0_type_name(inPKEY) == NULL) + { + ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); + return; + } + name = EVP_PKEY_get0_type_name(inPKEY); + + ByteString der; + int len = i2d_PUBKEY(inPKEY, NULL); + if (len <= 0) + { + ERROR_MSG("i2d_PUBKEY info error, len is smaller or eq than zero"); + return; + } + der.resize(len); + unsigned char* p = &der[0]; + if (i2d_PUBKEY(inPKEY, &p) != len) + { ERROR_MSG("i2d_PUBKEY serialization error"); return; } + + setDerPublicKey(der); +} + +// Check if the key is of the given type +bool OSSLSLHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the SLHDSA public key components +void OSSLSLHPublicKey::setDerPublicKey(const ByteString& inPk) +{ + SLHPublicKey::setDerPublicKey(inPk); + + getOSSLKey(); + if (EVP_PKEY_get0_type_name(pkey) == NULL) + { ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); return; } + + name = EVP_PKEY_get0_type_name(pkey); + + if (pkey) + { EVP_PKEY_free(pkey); pkey = NULL; } +} + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLSLHPublicKey::getOSSLKey() +{ + if (pkey == NULL) createOSSLKey(); + + return pkey; +} + +// Create the OpenSSL representation of the key +void OSSLSLHPublicKey::createOSSLKey() +{ + if (pkey != NULL) return; + + const unsigned char *p = &derPublicKey[0]; + pkey = d2i_PUBKEY(NULL, &p, (long)derPublicKey.size()); + + if (!pkey) + ERROR_MSG("d2i_PUBKEY; Error on deserialize derPublicKey to pkey"); + + if (EVP_PKEY_get0_type_name(pkey) == NULL) + { ERROR_MSG("Could not determine algorithm name from EVP_PKEY"); return; } + name = EVP_PKEY_get0_type_name(pkey); +} +#endif diff --git a/src/lib/crypto/OSSLSLHPublicKey.h b/src/lib/crypto/OSSLSLHPublicKey.h new file mode 100644 index 000000000..e2bc9c465 --- /dev/null +++ b/src/lib/crypto/OSSLSLHPublicKey.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHPublicKey.h + + OpenSSL SLHDSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSLHPUBLICKEY_H +#define _SOFTHSM_V2_OSSLSLHPUBLICKEY_H + +#include "config.h" +#include "SLHPublicKey.h" +#include + +class OSSLSLHPublicKey : public SLHPublicKey +{ +public: + // Constructors + OSSLSLHPublicKey(); + + OSSLSLHPublicKey(const EVP_PKEY* inPKEY); + + // Destructor + virtual ~OSSLSLHPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the base point order length + virtual unsigned long getOrderLength() const; + + // Setters for the SLHDSA public key components + virtual void setDerPublicKey(const ByteString& inPk); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EVP_PKEY* inPKEY); + + // Retrieve the OpenSSL representation of the key + EVP_PKEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + const char* name; + EVP_PKEY* pkey; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLSLHPUBLICKEY_H + diff --git a/src/lib/crypto/OSSLSLHUtil.cpp b/src/lib/crypto/OSSLSLHUtil.cpp new file mode 100644 index 000000000..3b8c85a33 --- /dev/null +++ b/src/lib/crypto/OSSLSLHUtil.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHUtils.cpp + + OpenSSL SLHDSA Utils + *****************************************************************************/ + +#include "OSSLSLHUtil.h" +#include "log.h" +#include + +namespace OSSLSLH { + +unsigned long getSignatureSizeFromName(const char* name) +{ + if (name == NULL){ + ERROR_MSG("Could not determine the signature size, name is NULL"); + return 0; + } + unsigned long name_len = strnlen(name, 100); + unsigned long signature_size = 0; + + if (name_len < 4) { + ERROR_MSG("Could not determine the signature size, name size is smaller than 4"); + return 0; + } + + if (strncmp(&name[name_len - 4], "128s", 4) == 0) { + signature_size = 7856; + } else if (strncmp(&name[name_len - 4], "128f", 4) == 0) { + signature_size = 17088; + } else if (strncmp(&name[name_len - 4], "192s", 4) == 0) { + signature_size = 16224; + } else if (strncmp(&name[name_len - 4], "192f", 4) == 0) { + signature_size = 35664; + } else if (strncmp(&name[name_len - 4], "256s", 4) == 0) { + signature_size = 29792; + } else if (strncmp(&name[name_len - 4], "256f", 4) == 0) { + signature_size = 49856; + } else{ + ERROR_MSG("Could not determine the signature size, returned 0"); + return 0; + } + return signature_size; +} + +} // namespace OSSLSLH diff --git a/src/lib/crypto/OSSLSLHUtil.h b/src/lib/crypto/OSSLSLHUtil.h new file mode 100644 index 000000000..ee0f139a8 --- /dev/null +++ b/src/lib/crypto/OSSLSLHUtil.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + OSSLSLHUtils.h + + OpenSSL SLHDSA Utils + *****************************************************************************/ + +#ifndef OSSLSLH_UTIL_H +#define OSSLSLH_UTIL_H + +namespace OSSLSLH { + unsigned long getSignatureSizeFromName(const char* name); +} + +#endif // OSSLSLH_UTIL_H diff --git a/src/lib/crypto/OSSLUtil.cpp b/src/lib/crypto/OSSLUtil.cpp index 794f80e3e..a0e4b0d80 100644 --- a/src/lib/crypto/OSSLUtil.cpp +++ b/src/lib/crypto/OSSLUtil.cpp @@ -118,7 +118,7 @@ EC_POINT* OSSL::byteString2pt(const ByteString& byteString, const EC_GROUP* grp) } #endif -#ifdef WITH_EDDSA +#if defined(WITH_EDDSA) // Convert an OpenSSL NID to a ByteString ByteString OSSL::oid2ByteString(int nid) { diff --git a/src/lib/crypto/OSSLUtil.h b/src/lib/crypto/OSSLUtil.h index 7b86c50e8..04e32df4f 100644 --- a/src/lib/crypto/OSSLUtil.h +++ b/src/lib/crypto/OSSLUtil.h @@ -39,7 +39,7 @@ #ifdef WITH_ECC #include #endif -#ifdef WITH_EDDSA +#if defined(WITH_EDDSA) #include #endif @@ -65,7 +65,7 @@ namespace OSSL EC_POINT* byteString2pt(const ByteString& byteString, const EC_GROUP* grp); #endif -#ifdef WITH_EDDSA +#if defined(WITH_EDDSA) // Convert an OpenSSL NID to a ByteString ByteString oid2ByteString(int nid); diff --git a/src/lib/crypto/SLHParameters.cpp b/src/lib/crypto/SLHParameters.cpp new file mode 100644 index 000000000..4816e9f80 --- /dev/null +++ b/src/lib/crypto/SLHParameters.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHParameters.cpp + + SLH-DSA parameters (only used for key generation) + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "SLHParameters.h" +#include + +const char* SLHParameters::type = "Generic SLH parameters"; + +void SLHParameters::setName(const ByteString& inName) +{ + name = inName; +} + +const ByteString& SLHParameters::getName() const +{ + return name; +} + +bool SLHParameters::areOfType(const char* inType) +{ + return (strcmp(type, inType) == 0); +} + +// Serialisation +ByteString SLHParameters::serialise() const +{ + return name.serialise(); +} + +bool SLHParameters::deserialise(ByteString& serialised) +{ + ByteString dName = ByteString::chainDeserialise(serialised); + + if (dName.size() == 0) + { + return false; + } + + setName(dName); + + return true; +} + diff --git a/src/lib/crypto/SLHParameters.h b/src/lib/crypto/SLHParameters.h new file mode 100644 index 000000000..e409e353f --- /dev/null +++ b/src/lib/crypto/SLHParameters.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHParameters.h + + SLH-DSA parameters (only used for key generation) + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SLHPARAMETERS_H +#define _SOFTHSM_V2_SLHPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "AsymmetricParameters.h" + +class SLHParameters : public AsymmetricParameters +{ +public: + // The type + static const char* type; + + void setName(const ByteString& inName); + const ByteString& getName() const; + + // Are the parameters of the given type? + virtual bool areOfType(const char* inType); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +private: + ByteString name; +}; + +#endif // !_SOFTHSM_V2_SLHPARAMETERS_H + diff --git a/src/lib/crypto/SLHPrivateKey.cpp b/src/lib/crypto/SLHPrivateKey.cpp new file mode 100644 index 000000000..832061b9d --- /dev/null +++ b/src/lib/crypto/SLHPrivateKey.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHPrivateKey.cpp + + SLHDSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "SLHPrivateKey.h" +#include + +// Set the type +/*static*/ const char* SLHPrivateKey::type = "Abstract SLHDSA private key"; + +// Check if the key is of the given type +bool SLHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long SLHPrivateKey::getBitLength() const +{ + return getDerPrivateKey().size() * 8; +} + +// Get the output length +unsigned long SLHPrivateKey::getOutputLength() const +{ + return getOrderLength(); +} + +void SLHPrivateKey::setDerPrivateKey(const ByteString& inSk) +{ + derPrivateKey = inSk; +} + +const ByteString& SLHPrivateKey::getDerPrivateKey() const +{ + return derPrivateKey; +} + +// Serialisation +ByteString SLHPrivateKey::serialise() const +{ + return derPrivateKey.serialise(); +} + +bool SLHPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dDerPrivateKey = ByteString::chainDeserialise(serialised); + + if (dDerPrivateKey.size() == 0) + { + return false; + } + + setDerPrivateKey(dDerPrivateKey); + return true; +} + diff --git a/src/lib/crypto/SLHPrivateKey.h b/src/lib/crypto/SLHPrivateKey.h new file mode 100644 index 000000000..55984beb7 --- /dev/null +++ b/src/lib/crypto/SLHPrivateKey.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHPrivateKey.h + + SLHDSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SLHPRIVATEKEY_H +#define _SOFTHSM_V2_SLHPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class SLHPrivateKey : public PrivateKey +{ +public: + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the bit length + virtual unsigned long getBitLength() const; + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Get the order length + virtual unsigned long getOrderLength() const = 0; + + // Setters for the SLHDSA private key components + virtual void setDerPrivateKey(const ByteString& inSk); + + // Getters for the SLHDSA private key components + virtual const ByteString& getDerPrivateKey() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // TODO: Replace derPrivateKey with attrs + getters and setters. + // generally these attrs are from type ByteString + // SK = (SK.seed, SK.prf, PK) + ByteString derPrivateKey; +}; + +#endif // !_SOFTHSM_V2_SLHPRIVATEKEY_H + diff --git a/src/lib/crypto/SLHPublicKey.cpp b/src/lib/crypto/SLHPublicKey.cpp new file mode 100644 index 000000000..b88b083ee --- /dev/null +++ b/src/lib/crypto/SLHPublicKey.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHPublicKey.cpp + + SLHDSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "SLHPublicKey.h" +#include + +// Set the type +/*static*/ const char* SLHPublicKey::type = "Abstract SLHDSA public key"; + +// Check if the key is of the given type +bool SLHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long SLHPublicKey::getBitLength() const +{ + return getDerPublicKey().size() * 8; +} + +// Get the output length +unsigned long SLHPublicKey::getOutputLength() const +{ + return getOrderLength(); +} + +// Setters for the SLH public key components +void SLHPublicKey::setDerPublicKey(const ByteString& inPk) +{ + derPublicKey = inPk; +} + +// Getters for the SLH public key components +const ByteString& SLHPublicKey::getDerPublicKey() const +{ + return derPublicKey; +} + +// Serialisation +ByteString SLHPublicKey::serialise() const +{ + return derPublicKey.serialise(); +} + +bool SLHPublicKey::deserialise(ByteString& serialised) +{ + ByteString dDerPublicKey = ByteString::chainDeserialise(serialised); + + if (dDerPublicKey.size() == 0) + { + return false; + } + + setDerPublicKey(dDerPublicKey); + + return true; +} + diff --git a/src/lib/crypto/SLHPublicKey.h b/src/lib/crypto/SLHPublicKey.h new file mode 100644 index 000000000..1487a6d7b --- /dev/null +++ b/src/lib/crypto/SLHPublicKey.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHPublicKey.h + + SLHDSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SLHPUBLICKEY_H +#define _SOFTHSM_V2_SLHPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class SLHPublicKey : public PublicKey +{ +public: + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the bit length + virtual unsigned long getBitLength() const; + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Get the order length + virtual unsigned long getOrderLength() const = 0; + + // Setters for the SLHDSA public key components + virtual void setDerPublicKey(const ByteString& inPk); + + // Getters for the SLHDSA public key components + virtual const ByteString& getDerPublicKey() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Public components + // TODO: Replace derPrivateKey with attrs + getters and setters. + // generally these attrs are from type ByteString + // PK = (PK.seed, PK.root) + ByteString derPublicKey; +}; + +#endif // !_SOFTHSM_V2_SLHPUBLICKEY_H + diff --git a/src/lib/crypto/test/Makefile.am b/src/lib/crypto/test/Makefile.am index 4065ef9ce..7def9c5ae 100644 --- a/src/lib/crypto/test/Makefile.am +++ b/src/lib/crypto/test/Makefile.am @@ -20,6 +20,7 @@ cryptotest_SOURCES = cryptotest.cpp \ DSATests.cpp \ ECDHTests.cpp \ ECDSATests.cpp \ + SLHDSATests.cpp \ EDDSATests.cpp \ GOSTTests.cpp \ HashTests.cpp \ diff --git a/src/lib/crypto/test/SLHDSATests.cpp b/src/lib/crypto/test/SLHDSATests.cpp new file mode 100644 index 000000000..b43995e48 --- /dev/null +++ b/src/lib/crypto/test/SLHDSATests.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHDSATests.cpp + + Contains test cases to test the SLHDSA class + *****************************************************************************/ + +#include "SLHDSATests.h" +#include "AsymmetricAlgorithm.h" +#include "AsymmetricKeyPair.h" +#include "CryptoFactory.h" +#include "RNG.h" +#ifdef WITH_SLHDSA +#include "SLHParameters.h" +#include "SLHPrivateKey.h" +#include "SLHPublicKey.h" +#include +#include +#include +#include + +CPPUNIT_TEST_SUITE_REGISTRATION(SLHDSATests); + +void SLHDSATests::setUp() { + slhdsa = NULL; + + slhdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::SLHDSA); + + // Check the SLHDSA object + CPPUNIT_ASSERT(slhdsa != NULL); +} + +void SLHDSATests::tearDown() { + if (slhdsa != NULL) { + CryptoFactory::i()->recycleAsymmetricAlgorithm(slhdsa); + } + + fflush(stdout); +} + +void SLHDSATests::testKeyGeneration() { + // slhdsa_names to test + std::vector slhdsa_names; + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-128s", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-128s", 19)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-128f", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-128f", 19)); + + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-192s", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-192s", 19)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-192f", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-192f", 19)); + + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-256s", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-256s", 19)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHA2-256f", 18)); + slhdsa_names.push_back( + ByteString((const unsigned char *)"SLH-DSA-SHAKE-256f", 19)); + + for (auto c = slhdsa_names.begin(); c != slhdsa_names.end(); c++) { + AsymmetricKeyPair *kp; + SLHParameters *p = new SLHParameters(); + p->setName(*c); + + // Generate key-pair + CPPUNIT_ASSERT(slhdsa->generateKeyPair(&kp, p)); + + SLHPublicKey *pub = (SLHPublicKey *)kp->getPublicKey(); + SLHPrivateKey *priv = (SLHPrivateKey *)kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getDerPublicKey() != ByteString("")); + CPPUNIT_ASSERT(priv->getDerPrivateKey() != ByteString("")); + + slhdsa->recycleParameters(p); + slhdsa->recycleKeyPair(kp); + } +} + +void SLHDSATests::testSerialisation() +{ + SLHParameters* p = new SLHParameters; + p->setName(ByteString((const unsigned char *) "SLH-DSA-SHA2-192f", 18)); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dName; + + CPPUNIT_ASSERT(slhdsa->reconstructParameters(&dName, serialisedParams)); + + CPPUNIT_ASSERT(dName->areOfType(SLHParameters::type)); + + SLHParameters* ddName = (SLHParameters*) dName; + + CPPUNIT_ASSERT(p->getName() == ddName->getName()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(slhdsa->generateKeyPair(&kp, dName)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(slhdsa->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + SLHPrivateKey* privKey = (SLHPrivateKey*) kp->getPrivateKey(); + SLHPublicKey* pubKey = (SLHPublicKey*) kp->getPublicKey(); + + SLHPrivateKey* dPrivKey = (SLHPrivateKey*) dKP->getPrivateKey(); + SLHPublicKey* dPubKey = (SLHPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getDerPrivateKey() == dPrivKey->getDerPrivateKey()); + + CPPUNIT_ASSERT(pubKey->getDerPublicKey() == dPubKey->getDerPublicKey()); + + slhdsa->recycleParameters(p); + slhdsa->recycleParameters(dName); + slhdsa->recycleKeyPair(kp); + slhdsa->recycleKeyPair(dKP); +} + +void SLHDSATests::testPKCS8() +{ + SLHParameters* p = new SLHParameters; + p->setName(ByteString((const unsigned char *) "SLH-DSA-SHA2-192f", 18)); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(slhdsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + SLHPrivateKey* priv = (SLHPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + SLHPrivateKey* dPriv = (SLHPrivateKey*) slhdsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getDerPrivateKey() == dPriv->getDerPrivateKey()); + + slhdsa->recycleParameters(p); + slhdsa->recycleKeyPair(kp); + slhdsa->recyclePrivateKey(dPriv); +} + +void SLHDSATests::testSigningVerifying() +{ + // slhdsa_names to test + std::vector slhdsa_names; + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-128s", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-128s", 19)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-128f", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-128f", 19)); + + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-192s", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-192s", 19)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-192f", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-192f", 19)); + + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-256s", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-256s", 19)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHA2-256f", 18)); + slhdsa_names.push_back(ByteString((const unsigned char *)"SLH-DSA-SHAKE-256f", 19)); + + for (auto c = slhdsa_names.begin(); c != slhdsa_names.end(); c++) { + AsymmetricKeyPair *kp; + SLHParameters *p = new SLHParameters(); + p->setName(*c); + + // Generate key-pair + CPPUNIT_ASSERT(slhdsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(p != NULL); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + CPPUNIT_ASSERT(rng != NULL); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Sign the data + ByteString sig; + CPPUNIT_ASSERT(slhdsa->sign(kp->getPrivateKey(), dataToSign, sig, AsymMech::SLHDSA)); + + // And verify it + CPPUNIT_ASSERT(slhdsa->verify(kp->getPublicKey(), dataToSign, sig, AsymMech::SLHDSA)); + + slhdsa->recycleKeyPair(kp); + slhdsa->recycleParameters(p); + } +} +#endif diff --git a/src/lib/crypto/test/SLHDSATests.h b/src/lib/crypto/test/SLHDSATests.h new file mode 100644 index 000000000..2523dabb4 --- /dev/null +++ b/src/lib/crypto/test/SLHDSATests.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + SLHDSATests.h + + Contains test cases to test the SLHDSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SLHDSATESTS_H +#define _SOFTHSM_V2_SLHDSATESTS_H + +#include "AsymmetricAlgorithm.h" +#include + +class SLHDSATests : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(SLHDSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + + void setUp(); + void tearDown(); + +private: + // SLHDSA instance + AsymmetricAlgorithm *slhdsa; +}; + +#endif // !_SOFTHSM_V2_SLHDSATESTS_H diff --git a/src/lib/pkcs11/pkcs11.h b/src/lib/pkcs11/pkcs11.h index cd195794c..8420c5ef0 100644 --- a/src/lib/pkcs11/pkcs11.h +++ b/src/lib/pkcs11/pkcs11.h @@ -408,6 +408,7 @@ typedef unsigned long ck_key_type_t; #define CKK_GOSTR3411 (0x31UL) #define CKK_GOST28147 (0x32UL) #define CKK_EC_EDWARDS (0x40UL) +#define CKK_SLHDSA (0x80010037UL) #define CKK_VENDOR_DEFINED ((unsigned long) (1UL << 31)) @@ -485,6 +486,7 @@ typedef unsigned long ck_attribute_type_t; #define CKA_DESTROYABLE (0x172UL) #define CKA_ECDSA_PARAMS (0x180UL) #define CKA_EC_PARAMS (0x180UL) +#define CKA_SLHDSA_PARAMS (0x80000030UL) #define CKA_EC_POINT (0x181UL) #define CKA_SECONDARY_AUTH (0x200UL) #define CKA_AUTH_PIN_FLAGS (0x201UL) @@ -892,6 +894,8 @@ typedef unsigned long ck_mechanism_type_t; /* From version 3.0 */ #define CKM_EC_EDWARDS_KEY_PAIR_GEN (0x1055UL) #define CKM_EDDSA (0x1057UL) +#define CKM_SLH_KEY_PAIR_GEN (0x80010003UL) +#define CKM_SLHDSA (0x80010006UL) /* Attribute and other constants related to OTP */ #define CK_OTP_FORMAT_DECIMAL (0UL)