Skip to content

Commit 046a174

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

2 files changed

Lines changed: 308 additions & 31 deletions

File tree

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

Lines changed: 275 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -152,36 +152,66 @@ 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+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
160+
int keyType = EVP_PKEY_get_id(pkey);
161+
if (keyType != EVP_PKEY_KEYMGMT)
157162
{
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;
163+
switch (keyType)
164+
#else
165+
switch (EVP_PKEY_type(EVP_PKEY_id(pkey)))
169166
#endif
170-
#ifdef WITH_EDDSA
171-
case NID_X25519:
172-
case NID_ED25519:
173-
case NID_X448:
174-
case NID_ED448:
167+
168+
{
169+
case EVP_PKEY_RSA:
170+
case EVP_PKEY_RSA_PSS:
171+
rsa = EVP_PKEY_get1_RSA(pkey);
172+
break;
173+
case EVP_PKEY_DSA:
174+
dsa = EVP_PKEY_get1_DSA(pkey);
175+
break;
176+
#ifdef WITH_ECC
177+
case EVP_PKEY_EC:
178+
ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
179+
break;
180+
#endif
181+
#ifdef WITH_EDDSA
182+
case NID_X25519:
183+
case NID_ED25519:
184+
case NID_X448:
185+
case NID_ED448:
186+
EVP_PKEY_up_ref(pkey);
187+
eddsa = pkey;
188+
break;
189+
#endif
190+
default:
191+
fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
192+
EVP_PKEY_free(pkey);
193+
return 1;
194+
break;
195+
}
196+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
197+
} else {
198+
// Provider Keys management
199+
#ifdef WITH_ML_DSA
200+
size_t len;
201+
int rv = (EVP_PKEY_is_a(pkey, "ML-DSA-44") ||
202+
EVP_PKEY_is_a(pkey, "ML-DSA-65") ||
203+
EVP_PKEY_is_a(pkey, "ML-DSA-87"));
204+
if (!rv) {
205+
fprintf(stderr, "ERROR: Cannot handle this algorithm, rv: %d\n", rv);
206+
EVP_PKEY_free(pkey);
207+
return 1;
208+
}
175209
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;
210+
mldsa = pkey;
211+
#endif
212+
184213
}
214+
#endif
185215
EVP_PKEY_free(pkey);
186216

187217
int result = 0;
@@ -209,6 +239,13 @@ int crypto_import_key_pair
209239
result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, eddsa);
210240
EVP_PKEY_free(eddsa);
211241
}
242+
#endif
243+
#ifdef WITH_ML_DSA
244+
else if (mldsa)
245+
{
246+
result = crypto_save_mldsa(hSession, label, objID, objIDLen, noPublicKey, mldsa);
247+
EVP_PKEY_free(mldsa);
248+
}
212249
#endif
213250
else
214251
{
@@ -348,7 +385,7 @@ int crypto_import_certificate
348385
}
349386
}
350387

351-
printf("The certificate has been imported.\n");
388+
printf("The certificate with label=%s has been imported.\n", label);
352389

353390
ret = 0;
354391

@@ -505,7 +542,7 @@ int crypto_save_rsa
505542
return 1;
506543
}
507544

508-
printf("The key pair has been imported.\n");
545+
printf("The RSA key pair with label=%s has been imported.\n", label);
509546

510547
return 0;
511548
}
@@ -674,7 +711,7 @@ int crypto_save_dsa
674711
return 1;
675712
}
676713

677-
printf("The key pair has been imported.\n");
714+
printf("The DSA key pair with label=%s has been imported.\n", label);
678715

679716
return 0;
680717
}
@@ -815,7 +852,7 @@ int crypto_save_ecdsa
815852
return 1;
816853
}
817854

818-
printf("The key pair has been imported.\n");
855+
printf("The ECDSA key pair with label=%s has been imported.\n", label);
819856

820857
return 0;
821858
}
@@ -1032,7 +1069,7 @@ int crypto_save_eddsa
10321069
return 1;
10331070
}
10341071

1035-
printf("The key pair has been imported.\n");
1072+
printf("The EDDSA key pair with label=%s has been imported.\n", label);
10361073

10371074
return 0;
10381075
}
@@ -1139,3 +1176,211 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat)
11391176
}
11401177

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

0 commit comments

Comments
 (0)