Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6655c15
feat: add initial dockerfile do easier the build
JoaoHenrique12 Jul 2, 2025
af467c3
feat: using openssl 3.5.1 to build softhsmv2
JoaoHenrique12 Aug 15, 2025
4fa5d9c
chore: dockerfile remove ecc keys, enable only eddsa
JoaoHenrique12 Aug 22, 2025
48e8cc6
fix: install opensc and pkcs11 at begining
JoaoHenrique12 Aug 29, 2025
ae0a50e
docs: remove logs used on exploratory process
JoaoHenrique12 Nov 5, 2025
ddfc875
feat: duplicate eddsa (#2)
JoaoHenrique12 Sep 12, 2025
7988efa
chore: remove library hpcs-pkcs11 from softhsmv2
JoaoHenrique12 Nov 5, 2025
907ffb2
feat: update pkcs11 client and add slh-dsa signature (#3)
JoaoHenrique12 Oct 7, 2025
07a76cb
chore: remove dockerfile used on developing process
JoaoHenrique12 Nov 5, 2025
bb16d37
test(unit): slhdsa keypair tests added (#5)
JoaoHenrique12 Oct 28, 2025
21a981f
chore: clean repo, removing exploratory logs, hpkcs11 and Dockerfile
JoaoHenrique12 Nov 5, 2025
c4d6e59
fix(coderabbit): issue about ';' on error log, removed additional logs
JoaoHenrique12 Nov 11, 2025
778e412
fix(coderabbit): remove guard for slhdsa on oid operations
JoaoHenrique12 Nov 11, 2025
f0a9949
fix(coderabbit): return correct min/max size on OSSLSLHDSA.cpp
JoaoHenrique12 Nov 11, 2025
811dfdf
test(coderabbit): fix bytestring size for slhdsa names with shake
JoaoHenrique12 Nov 11, 2025
8f620de
fix(coderabbit): deriveKey, this function is not covered by slh-dsa
JoaoHenrique12 Nov 11, 2025
4296151
fix(coderabbit): by default detect slh-dsa on m4 files
JoaoHenrique12 Nov 11, 2025
5110c12
fix: by default disable slhdsa
JoaoHenrique12 Nov 11, 2025
ee5d1e2
fix(coderabbit): minor errors, messages and identation on m4 file
JoaoHenrique12 Nov 11, 2025
e050475
refactor(coderabbit): dry, applied on define key size for slh-dsa
JoaoHenrique12 Nov 11, 2025
05eb70c
fix: remove test file, data.txt
JoaoHenrique12 Nov 11, 2025
3db0676
fix(coderabbit): minor issue on OSSLSLHPrivateKey.h, comment
JoaoHenrique12 Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions m4/acx_crypto_backend.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
42 changes: 42 additions & 0 deletions m4/acx_openssl_slhdsa.m4
Original file line number Diff line number Diff line change
@@ -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 <openssl/evp.h>
#include <openssl/objects.h>
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}"
])
4 changes: 4 additions & 0 deletions src/bin/dump/tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ void fill_CKA_table(std::map<unsigned long, std::string> &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";
Expand Down Expand Up @@ -478,6 +479,8 @@ void fill_CKM_table(std::map<unsigned long, std::string> &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<unsigned long, std::string> &t)
Expand Down Expand Up @@ -544,6 +547,7 @@ void fill_CKK_table(std::map<unsigned long, std::string> &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<unsigned long, std::string> &t)
Expand Down
170 changes: 168 additions & 2 deletions src/bin/util/softhsm2-util-ossl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 },
};
Comment on lines +1183 to +1207
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Incorrect attribute usage for SLHDSA keys.

The CKA_SLHDSA_PARAMS attribute is being used to store the entire DER-encoded public/private key, but it should only contain the algorithm parameters (e.g., the variant name like "SLH-DSA-SHA2-128s"). The actual key material should be in CKA_VALUE or a similar attribute.

Compare with EdDSA (lines 1000-1026):

  • CKA_EC_PARAMS stores the algorithm OID (parameters)
  • CKA_EC_POINT stores the public key
  • CKA_VALUE stores the private key

For SLHDSA, you should:

  1. Extract the algorithm variant/parameters from the EVP_PKEY
  2. Store only those parameters in CKA_SLHDSA_PARAMS
  3. Store the public key material in an appropriate attribute (possibly CKA_VALUE for public keys)
  4. Store the private key material in CKA_VALUE for private keys

This aligns with the PR description noting that "private/public key values are stored DER-encoded without separating key attributes" as a limitation to be addressed.

🤖 Prompt for AI Agents
In src/bin/util/softhsm2-util-ossl.cpp around lines 1183-1207, the code
currently places entire DER-encoded public/private keys into CKA_SLHDSA_PARAMS;
update this to store only the SLH-DSA algorithm parameters (variant name/OID) in
CKA_SLHDSA_PARAMS and move the actual key blobs into the appropriate CKA_VALUE
attributes (public key into the public object's CKA_VALUE-like attribute and
private key into the private object's CKA_VALUE). Specifically: extract the
SLHDSA algorithm variant/parameters from the EVP_PKEY (or related params) and
set that buffer/length for CKA_SLHDSA_PARAMS; replace
keyMat->derPublicKey/sizePublicKey and keyMat->derPrivateKey/sizePrivateKey in
the SLHDSA params entries with the parameter blob; add CKA_VALUE entries to the
pubTemplate and privTemplate that hold the DER public and DER private key bytes
respectively (with correct lengths), and remove or adjust the incorrect
CKA_SLHDSA_PARAMS usages so attribute types and sizes match PKCS#11
expectations.


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
25 changes: 24 additions & 1 deletion src/bin/util/softhsm2-util-ossl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#ifdef WITH_ECC
#include <openssl/ec.h>
#endif
#ifdef WITH_EDDSA
#if defined(WITH_EDDSA) || defined (WITH_SLHDSA)
#include <openssl/evp.h>
#endif

Expand Down Expand Up @@ -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
Expand All @@ -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
11 changes: 11 additions & 0 deletions src/lib/P11Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
*****************************************/
Expand Down
Loading