Skip to content

Commit 21beaf3

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

3 files changed

Lines changed: 293 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: 252 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -152,35 +152,58 @@ 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:
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+
#ifdef WITH_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);
200+
EVP_PKEY_free(pkey);
201+
return NULL;
202+
}
175203
EVP_PKEY_up_ref(pkey);
176-
eddsa = pkey;
177-
break;
178-
#endif
179-
default:
180-
fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
181-
EVP_PKEY_free(pkey);
182-
return 1;
183-
break;
204+
mldsa = pkey;
205+
#endif
206+
184207
}
185208
EVP_PKEY_free(pkey);
186209

@@ -209,6 +232,13 @@ int crypto_import_key_pair
209232
result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, eddsa);
210233
EVP_PKEY_free(eddsa);
211234
}
235+
#endif
236+
#ifdef WITH_ML_DSA
237+
else if (mldsa)
238+
{
239+
result = crypto_save_mldsa(hSession, label, objID, objIDLen, noPublicKey, mldsa);
240+
EVP_PKEY_free(mldsa);
241+
}
212242
#endif
213243
else
214244
{
@@ -409,7 +439,7 @@ EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
409439
if (!p8inf)
410440
{
411441
fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
412-
"Maybe it is encypted (--file-pin <PIN>)\n");
442+
"Maybe it is encypted (--file-pin <PIN>)\nError code: %");
413443
return NULL;
414444
}
415445
}
@@ -1139,3 +1169,198 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat)
11391169
}
11401170

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