Skip to content

Commit 422b004

Browse files
committed
Added support for ML-DSA in softhsm2-util
Added missing ML-DSA cmake compiler option
1 parent 6319797 commit 422b004

3 files changed

Lines changed: 292 additions & 28 deletions

File tree

cmake/modules/CompilerOptions.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,14 @@ elseif(WITH_CRYPTO_BACKEND STREQUAL "openssl")
370370
message(STATUS "OpenSSL: Support for EDDSA is disabled")
371371
endif(ENABLE_EDDSA)
372372

373+
# acx_openssl_mldsa.m4
374+
if(ENABLE_MLDSA)
375+
set(WITH_ML_DSA 1)
376+
message(STATUS "OpenSSL: ML-DSA support enabled")
377+
else(ENABLE_MLDSA)
378+
message(STATUS "OpenSSL: Support for ML-DSA is disabled")
379+
endif(ENABLE_MLDSA)
380+
373381
# acx_openssl_gost.m4
374382
if(ENABLE_GOST)
375383
set(testfile ${CMAKE_SOURCE_DIR}/cmake/modules/tests/test_openssl_gost.c)

src/bin/util/softhsm2-util-ossl.cpp

Lines changed: 251 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -152,35 +152,57 @@ int crypto_import_key_pair
152152
#ifdef WITH_EDDSA
153153
EVP_PKEY* eddsa = NULL;
154154
#endif
155+
#ifdef WITH_ML_DSA
156+
EVP_PKEY* mldsa = NULL;
157+
#endif
155158

156-
switch (EVP_PKEY_type(EVP_PKEY_id(pkey)))
159+
int keyType = EVP_PKEY_get_id(pkey);
160+
if (keyType != EVP_PKEY_KEYMGMT)
157161
{
158-
case EVP_PKEY_RSA:
159-
case EVP_PKEY_RSA_PSS:
160-
rsa = EVP_PKEY_get1_RSA(pkey);
161-
break;
162-
case EVP_PKEY_DSA:
163-
dsa = EVP_PKEY_get1_DSA(pkey);
164-
break;
165-
#ifdef WITH_ECC
166-
case EVP_PKEY_EC:
167-
ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
168-
break;
169-
#endif
170-
#ifdef WITH_EDDSA
171-
case NID_X25519:
172-
case NID_ED25519:
173-
case NID_X448:
174-
case NID_ED448:
175-
EVP_PKEY_up_ref(pkey);
176-
eddsa = pkey;
177-
break;
178-
#endif
179-
default:
180-
fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
162+
switch (keyType)
163+
{
164+
case EVP_PKEY_RSA:
165+
case EVP_PKEY_RSA_PSS:
166+
rsa = EVP_PKEY_get1_RSA(pkey);
167+
break;
168+
case EVP_PKEY_DSA:
169+
dsa = EVP_PKEY_get1_DSA(pkey);
170+
break;
171+
#ifdef WITH_ECC
172+
case EVP_PKEY_EC:
173+
ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
174+
break;
175+
#endif
176+
#ifdef WITH_EDDSA
177+
case NID_X25519:
178+
case NID_ED25519:
179+
case NID_X448:
180+
case NID_ED448:
181+
EVP_PKEY_up_ref(pkey);
182+
eddsa = pkey;
183+
break;
184+
#endif
185+
default:
186+
fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
187+
EVP_PKEY_free(pkey);
188+
return 1;
189+
break;
190+
}
191+
} else {
192+
// Provider Keys management
193+
// ML-DSA
194+
size_t seed_len;
195+
int rv = EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ML_DSA_SEED,
196+
NULL, 0, &seed_len);
197+
198+
if(!rv) {
199+
fprintf(stderr, "ERROR: Could not get OSSL_PKEY_PARAM_ML_DSA_SEED size, rv: %d\n", rv);
181200
EVP_PKEY_free(pkey);
182-
return 1;
183-
break;
201+
return NULL;
202+
}
203+
EVP_PKEY_up_ref(pkey);
204+
mldsa = pkey;
205+
184206
}
185207
EVP_PKEY_free(pkey);
186208

@@ -209,6 +231,13 @@ int crypto_import_key_pair
209231
result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, eddsa);
210232
EVP_PKEY_free(eddsa);
211233
}
234+
#endif
235+
#ifdef WITH_ML_DSA
236+
else if (mldsa)
237+
{
238+
result = crypto_save_mldsa(hSession, label, objID, objIDLen, noPublicKey, mldsa);
239+
EVP_PKEY_free(mldsa);
240+
}
212241
#endif
213242
else
214243
{
@@ -409,7 +438,7 @@ EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
409438
if (!p8inf)
410439
{
411440
fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
412-
"Maybe it is encypted (--file-pin <PIN>)\n");
441+
"Maybe it is encypted (--file-pin <PIN>)\nError code: %");
413442
return NULL;
414443
}
415444
}
@@ -1139,3 +1168,198 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat)
11391168
}
11401169

11411170
#endif
1171+
1172+
#ifdef WITH_ML_DSA
1173+
1174+
// Save the key data in PKCS#11
1175+
int crypto_save_mldsa
1176+
(
1177+
CK_SESSION_HANDLE hSession,
1178+
char* label,
1179+
char* objID,
1180+
size_t objIDLen,
1181+
int noPublicKey,
1182+
EVP_PKEY* mldsa
1183+
)
1184+
{
1185+
mldsa_key_material_t* keyMat = crypto_malloc_mldsa(mldsa);
1186+
if (keyMat == NULL)
1187+
{
1188+
fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
1189+
return 1;
1190+
}
1191+
1192+
CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
1193+
CK_KEY_TYPE keyType = CKK_ML_DSA;
1194+
CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
1195+
if (noPublicKey)
1196+
{
1197+
ckToken = CK_FALSE;
1198+
}
1199+
CK_ATTRIBUTE pubTemplate[] = {
1200+
{ CKA_CLASS, &pubClass, sizeof(pubClass) },
1201+
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
1202+
{ CKA_LABEL, label, strlen(label) },
1203+
{ CKA_ID, objID, objIDLen },
1204+
{ CKA_TOKEN, &ckToken, sizeof(ckToken) },
1205+
{ CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
1206+
{ CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
1207+
{ CKA_WRAP, &ckFalse, sizeof(ckFalse) },
1208+
{ CKA_PARAMETER_SET, &keyMat->parameterSet, sizeof(CK_ULONG) },
1209+
{ CKA_VALUE, keyMat->pubValue, keyMat->sizePubValue },
1210+
};
1211+
CK_ATTRIBUTE privTemplate[] = {
1212+
{ CKA_CLASS, &privClass, sizeof(privClass) },
1213+
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
1214+
{ CKA_LABEL, label, strlen(label) },
1215+
{ CKA_ID, objID, objIDLen },
1216+
{ CKA_SIGN, &ckTrue, sizeof(ckTrue) },
1217+
{ CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
1218+
{ CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
1219+
{ CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
1220+
{ CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
1221+
{ CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
1222+
{ CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
1223+
{ CKA_PARAMETER_SET, &keyMat->parameterSet, sizeof(CK_ULONG) },
1224+
{ CKA_SEED, keyMat->seed, keyMat->sizeSeed },
1225+
{ CKA_VALUE, keyMat->privValue, keyMat->sizePrivValue },
1226+
};
1227+
1228+
CK_OBJECT_HANDLE hKey1, hKey2;
1229+
CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 14, &hKey1);
1230+
if (rv != CKR_OK)
1231+
{
1232+
fprintf(stderr, "ERROR: Could not save the private key in the token. "
1233+
"Maybe the algorithm is not supported.\n");
1234+
crypto_free_mldsa(keyMat);
1235+
return 1;
1236+
}
1237+
1238+
rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
1239+
crypto_free_mldsa(keyMat);
1240+
1241+
if (rv != CKR_OK)
1242+
{
1243+
p11->C_DestroyObject(hSession, hKey1);
1244+
fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
1245+
return 1;
1246+
}
1247+
1248+
printf("The key pair has been imported.\n");
1249+
1250+
return 0;
1251+
}
1252+
1253+
// Convert the OpenSSL key to binary
1254+
#define PUBPREFIXLEN 12
1255+
#define PRIVPREFIXLEN 16
1256+
1257+
mldsa_key_material_t* crypto_malloc_mldsa(EVP_PKEY* pkey)
1258+
{
1259+
1260+
if (pkey == NULL)
1261+
{
1262+
return NULL;
1263+
}
1264+
1265+
mldsa_key_material_t* keyMat = (mldsa_key_material_t*)calloc(1, sizeof(mldsa_key_material_t));
1266+
if (keyMat == NULL)
1267+
{
1268+
return NULL;
1269+
}
1270+
1271+
uint8_t seed[32];
1272+
size_t seed_len;
1273+
int rv = EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ML_DSA_SEED,
1274+
seed, sizeof(seed), &seed_len);
1275+
1276+
if(!rv) {
1277+
fprintf(stderr, "ERROR: Could not get ML-DSA seed, rv: %d", rv);
1278+
memset(seed, 0, sizeof(seed));
1279+
return NULL;
1280+
}
1281+
1282+
// let's use max priv length
1283+
uint8_t priv[MLDSAParameters::ML_DSA_87_PRIV_LENGTH];
1284+
size_t priv_len;
1285+
rv = EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
1286+
priv, sizeof(priv), &priv_len);
1287+
if(!rv) {
1288+
fprintf(stderr, "ERROR: Could not get ML-DSA private key, rv: %d", rv);
1289+
memset(seed, 0, sizeof(seed));
1290+
memset(priv, 0, sizeof(priv));
1291+
return NULL;
1292+
}
1293+
1294+
if (priv_len != MLDSAParameters::ML_DSA_44_PRIV_LENGTH &&
1295+
priv_len != MLDSAParameters::ML_DSA_65_PRIV_LENGTH &&
1296+
priv_len != MLDSAParameters::ML_DSA_87_PRIV_LENGTH)
1297+
{
1298+
fprintf(stderr, "ERROR: Unsupported ML-DSA private key length: %zu", priv_len);
1299+
memset(seed, 0, sizeof(seed));
1300+
memset(priv, 0, sizeof(priv));
1301+
return NULL;
1302+
}
1303+
1304+
uint8_t pub[MLDSAParameters::ML_DSA_87_PUB_LENGTH];
1305+
size_t pub_len;
1306+
rv = EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
1307+
pub, sizeof(pub), &pub_len);
1308+
1309+
if(!rv) {
1310+
fprintf(stderr, "ERROR: Could not get ML-DSA public key, rv: %d", rv);
1311+
memset(seed, 0, sizeof(seed));
1312+
memset(priv, 0, sizeof(priv));
1313+
return NULL;
1314+
}
1315+
1316+
keyMat->sizeSeed = seed_len;
1317+
keyMat->sizePrivValue = priv_len;
1318+
keyMat->sizePubValue = pub_len;
1319+
1320+
keyMat->seed = (CK_VOID_PTR)malloc(keyMat->sizeSeed);
1321+
keyMat->privValue = (CK_VOID_PTR)malloc(keyMat->sizePrivValue);
1322+
keyMat->pubValue = (CK_VOID_PTR)malloc(keyMat->sizePubValue);
1323+
1324+
switch (keyMat->sizePrivValue)
1325+
{
1326+
case MLDSAParameters::ML_DSA_44_PRIV_LENGTH:
1327+
keyMat->parameterSet = MLDSAParameters::ML_DSA_44_PARAMETER_SET;
1328+
break;
1329+
1330+
case MLDSAParameters::ML_DSA_65_PRIV_LENGTH:
1331+
keyMat->parameterSet = MLDSAParameters::ML_DSA_65_PARAMETER_SET;
1332+
break;
1333+
1334+
case MLDSAParameters::ML_DSA_87_PRIV_LENGTH:
1335+
keyMat->parameterSet = MLDSAParameters::ML_DSA_87_PARAMETER_SET;
1336+
break;
1337+
1338+
default:
1339+
break;
1340+
}
1341+
1342+
memcpy(keyMat->seed, seed, keyMat->sizeSeed);
1343+
memcpy(keyMat->privValue, priv, keyMat->sizePrivValue);
1344+
memcpy(keyMat->pubValue, pub, keyMat->sizePubValue);
1345+
1346+
if (!keyMat->parameterSet || !keyMat->seed || !keyMat->privValue || !keyMat->pubValue)
1347+
{
1348+
crypto_free_mldsa(keyMat);
1349+
return NULL;
1350+
}
1351+
1352+
return keyMat;
1353+
}
1354+
1355+
// Free the memory of the key
1356+
void crypto_free_mldsa(mldsa_key_material_t* keyMat)
1357+
{
1358+
if (keyMat == NULL) return;
1359+
if (keyMat->seed) free(keyMat->seed);
1360+
if (keyMat->privValue) free(keyMat->privValue);
1361+
if (keyMat->pubValue) free(keyMat->pubValue);
1362+
free(keyMat);
1363+
}
1364+
1365+
#endif

src/bin/util/softhsm2-util-ossl.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@
3838
#ifdef WITH_ECC
3939
#include <openssl/ec.h>
4040
#endif
41-
#ifdef WITH_EDDSA
41+
#if defined(WITH_EDDSA) || defined(WITH_ML_DSA)
4242
#include <openssl/evp.h>
4343
#endif
44+
#ifdef WITH_ML_DSA
45+
#include <openssl/core_names.h>
46+
#include <src/lib/crypto/MLDSAParameters.h>
47+
#endif
4448

4549
typedef struct rsa_key_material_t {
4650
CK_ULONG sizeE;
@@ -142,6 +146,27 @@ typedef struct eddsa_key_material_t {
142146
} eddsa_key_material_t;
143147
#endif
144148

149+
#ifdef WITH_ML_DSA
150+
typedef struct mldsa_key_material_t {
151+
CK_ULONG sizeSeed;
152+
CK_ULONG sizePrivValue;
153+
CK_ULONG sizePubValue;
154+
CK_ULONG parameterSet;
155+
CK_VOID_PTR seed;
156+
CK_VOID_PTR privValue;
157+
CK_VOID_PTR pubValue;
158+
mldsa_key_material_t() {
159+
sizeSeed = 0;
160+
sizePrivValue = 0;
161+
sizePubValue = 0;
162+
parameterSet = 0;
163+
seed = NULL_PTR;
164+
privValue = NULL_PTR;
165+
pubValue = NULL_PTR;
166+
}
167+
} mldsa_key_material_t;
168+
#endif
169+
145170
EVP_PKEY* crypto_read_file(char* filePath, char* filePIN);
146171

147172
// RSA
@@ -168,4 +193,11 @@ eddsa_key_material_t* crypto_malloc_eddsa(EVP_PKEY* eddsa);
168193
void crypto_free_eddsa(eddsa_key_material_t* keyMat);
169194
#endif
170195

196+
#ifdef WITH_ML_DSA
197+
// MLDSA
198+
int crypto_save_mldsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, EVP_PKEY* mldsa);
199+
mldsa_key_material_t* crypto_malloc_mldsa(EVP_PKEY* mldsa);
200+
void crypto_free_mldsa(mldsa_key_material_t* keyMat);
201+
#endif
202+
171203
#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H

0 commit comments

Comments
 (0)