Skip to content

Commit ce64feb

Browse files
committed
fix: check key type in C_SignInit/C_VerifyInit to prevent crash
Passing a wrong asymmetric key type (e.g. EC key) to a mismatched mechanism (e.g. CKM_RSA_PKCS) caused a crash (segfault or abort) because the code tried to read RSA attributes from an EC key object, then passed invalid data to OpenSSL. Add key type validation after the mechanism switch in both functions, returning CKR_KEY_TYPE_INCONSISTENT on mismatch. Also convert the GOST catch-all else branch to an explicit else-if(isGOST) check. Regression tests use cross-matched asymmetric keys (EC key with RSA mechanisms, RSA key with ECDSA/EdDSA mechanisms) to verify the fix. Without the fix, C_SignInit accepts the wrong key type and the subsequent C_Sign crashes.
1 parent 3e6e6c3 commit ce64feb

File tree

3 files changed

+222
-16
lines changed

3 files changed

+222
-16
lines changed

src/lib/SoftHSM.cpp

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,6 +4190,9 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
41904190
if (!isMechanismPermitted(key, pMechanism->mechanism))
41914191
return CKR_MECHANISM_INVALID;
41924192

4193+
// Get key info
4194+
CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
4195+
41934196
// Get the asymmetric algorithm matching the mechanism
41944197
AsymMech::Type mechanism = AsymMech::Unknown;
41954198
void* param = NULL;
@@ -4202,13 +4205,15 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
42024205
#ifdef WITH_ECC
42034206
bool isECDSA = false;
42044207
#endif
4208+
#ifdef WITH_GOST
4209+
bool isGOST = false;
4210+
#endif
42054211
#ifdef WITH_EDDSA
42064212
bool isEDDSA = false;
42074213
#endif
42084214
#ifdef WITH_ML_DSA
42094215
bool isMLDSA = false;
42104216
MLDSAMechanismParam mldsaParam;
4211-
CK_KEY_TYPE keyType;
42124217
#endif
42134218
switch(pMechanism->mechanism) {
42144219
case CKM_RSA_PKCS:
@@ -4463,10 +4468,12 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
44634468
case CKM_GOSTR3410:
44644469
mechanism = AsymMech::GOST;
44654470
bAllowMultiPartOp = false;
4471+
isGOST = true;
44664472
break;
44674473
case CKM_GOSTR3410_WITH_GOSTR3411:
44684474
mechanism = AsymMech::GOST_GOST;
44694475
bAllowMultiPartOp = true;
4476+
isGOST = true;
44704477
break;
44714478
#endif
44724479
#ifdef WITH_EDDSA
@@ -4478,8 +4485,6 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
44784485
#endif
44794486
#ifdef WITH_ML_DSA
44804487
case CKM_ML_DSA:
4481-
// Get key info
4482-
keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
44834488
if (keyType != CKK_ML_DSA)
44844489
{
44854490
return CKR_KEY_TYPE_INCONSISTENT;
@@ -4527,6 +4532,24 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
45274532
return CKR_MECHANISM_INVALID;
45284533
}
45294534

4535+
// Validate key type (ML-DSA is checked inside its switch case above)
4536+
if (isRSA && keyType != CKK_RSA)
4537+
return CKR_KEY_TYPE_INCONSISTENT;
4538+
if (isDSA && keyType != CKK_DSA)
4539+
return CKR_KEY_TYPE_INCONSISTENT;
4540+
#ifdef WITH_ECC
4541+
if (isECDSA && keyType != CKK_EC)
4542+
return CKR_KEY_TYPE_INCONSISTENT;
4543+
#endif
4544+
#ifdef WITH_GOST
4545+
if (isGOST && keyType != CKK_GOSTR3410)
4546+
return CKR_KEY_TYPE_INCONSISTENT;
4547+
#endif
4548+
#ifdef WITH_EDDSA
4549+
if (isEDDSA && keyType != CKK_EC_EDWARDS)
4550+
return CKR_KEY_TYPE_INCONSISTENT;
4551+
#endif
4552+
45304553
AsymmetricAlgorithm* asymCrypto = NULL;
45314554
PrivateKey* privateKey = NULL;
45324555
if (isRSA)
@@ -4630,9 +4653,9 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
46304653
}
46314654
}
46324655
#endif
4633-
else
4634-
{
46354656
#ifdef WITH_GOST
4657+
else if (isGOST)
4658+
{
46364659
asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
46374660
if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
46384661

@@ -4649,10 +4672,12 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
46494672
CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
46504673
return CKR_GENERAL_ERROR;
46514674
}
4652-
#else
4653-
return CKR_MECHANISM_INVALID;
4675+
}
46544676
#endif
4655-
}
4677+
else
4678+
{
4679+
return CKR_MECHANISM_INVALID;
4680+
}
46564681

46574682
// Initialize signing
46584683
if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
@@ -5269,6 +5294,9 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
52695294
if (!isMechanismPermitted(key, pMechanism->mechanism))
52705295
return CKR_MECHANISM_INVALID;
52715296

5297+
// Get key info
5298+
CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
5299+
52725300
// Get the asymmetric algorithm matching the mechanism
52735301
AsymMech::Type mechanism = AsymMech::Unknown;
52745302
void* param = NULL;
@@ -5281,13 +5309,15 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
52815309
#ifdef WITH_ECC
52825310
bool isECDSA = false;
52835311
#endif
5312+
#ifdef WITH_GOST
5313+
bool isGOST = false;
5314+
#endif
52845315
#ifdef WITH_EDDSA
52855316
bool isEDDSA = false;
52865317
#endif
52875318
#ifdef WITH_ML_DSA
52885319
bool isMLDSA = false;
52895320
MLDSAMechanismParam mldsaParam;
5290-
CK_KEY_TYPE keyType;
52915321
#endif
52925322
switch(pMechanism->mechanism) {
52935323
case CKM_RSA_PKCS:
@@ -5540,10 +5570,12 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
55405570
case CKM_GOSTR3410:
55415571
mechanism = AsymMech::GOST;
55425572
bAllowMultiPartOp = false;
5573+
isGOST = true;
55435574
break;
55445575
case CKM_GOSTR3410_WITH_GOSTR3411:
55455576
mechanism = AsymMech::GOST_GOST;
55465577
bAllowMultiPartOp = true;
5578+
isGOST = true;
55475579
break;
55485580
#endif
55495581
#ifdef WITH_EDDSA
@@ -5555,8 +5587,6 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
55555587
#endif
55565588
#ifdef WITH_ML_DSA
55575589
case CKM_ML_DSA:
5558-
// Get key info
5559-
keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
55605590
if (keyType != CKK_ML_DSA)
55615591
{
55625592
return CKR_KEY_TYPE_INCONSISTENT;
@@ -5604,6 +5634,24 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
56045634
return CKR_MECHANISM_INVALID;
56055635
}
56065636

5637+
// Validate key type (ML-DSA is checked inside its switch case above)
5638+
if (isRSA && keyType != CKK_RSA)
5639+
return CKR_KEY_TYPE_INCONSISTENT;
5640+
if (isDSA && keyType != CKK_DSA)
5641+
return CKR_KEY_TYPE_INCONSISTENT;
5642+
#ifdef WITH_ECC
5643+
if (isECDSA && keyType != CKK_EC)
5644+
return CKR_KEY_TYPE_INCONSISTENT;
5645+
#endif
5646+
#ifdef WITH_GOST
5647+
if (isGOST && keyType != CKK_GOSTR3410)
5648+
return CKR_KEY_TYPE_INCONSISTENT;
5649+
#endif
5650+
#ifdef WITH_EDDSA
5651+
if (isEDDSA && keyType != CKK_EC_EDWARDS)
5652+
return CKR_KEY_TYPE_INCONSISTENT;
5653+
#endif
5654+
56075655
AsymmetricAlgorithm* asymCrypto = NULL;
56085656
PublicKey* publicKey = NULL;
56095657
if (isRSA)
@@ -5707,9 +5755,9 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
57075755
}
57085756
}
57095757
#endif
5710-
else
5711-
{
57125758
#ifdef WITH_GOST
5759+
else if (isGOST)
5760+
{
57135761
asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
57145762
if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
57155763

@@ -5726,10 +5774,12 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
57265774
CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
57275775
return CKR_GENERAL_ERROR;
57285776
}
5729-
#else
5730-
return CKR_MECHANISM_INVALID;
5777+
}
57315778
#endif
5732-
}
5779+
else
5780+
{
5781+
return CKR_MECHANISM_INVALID;
5782+
}
57335783

57345784
// Initialize verifying
57355785
if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))

src/lib/test/SignVerifyTests.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,3 +1285,155 @@ void SignVerifyTests::testMacSignVerify()
12851285
macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
12861286
}
12871287

1288+
// C_SignInit with mismatched key type must return CKR_KEY_TYPE_INCONSISTENT,
1289+
// not accept the key and crash during C_Sign.
1290+
void SignVerifyTests::testSignInitWrongKeyType()
1291+
{
1292+
CK_RV rv;
1293+
CK_SESSION_HANDLE hSession;
1294+
1295+
// Just make sure that we finalize any previous tests
1296+
CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
1297+
1298+
rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
1299+
CPPUNIT_ASSERT(rv == CKR_OK);
1300+
1301+
rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
1302+
CPPUNIT_ASSERT(rv == CKR_OK);
1303+
1304+
rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
1305+
CPPUNIT_ASSERT(rv == CKR_OK);
1306+
1307+
// EC private key with RSA/DSA mechanisms
1308+
CK_OBJECT_HANDLE hEcPub = CK_INVALID_HANDLE, hEcPriv = CK_INVALID_HANDLE;
1309+
#ifdef WITH_ECC
1310+
rv = generateEC("P-256", hSession, IN_SESSION, IS_PUBLIC, IN_SESSION, IS_PUBLIC, hEcPub, hEcPriv);
1311+
CPPUNIT_ASSERT(rv == CKR_OK);
1312+
1313+
// RSA mechanisms with EC key
1314+
CK_MECHANISM_TYPE rsaMechs[] = {
1315+
CKM_RSA_PKCS, CKM_RSA_X_509,
1316+
CKM_SHA1_RSA_PKCS, CKM_SHA256_RSA_PKCS,
1317+
CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS
1318+
};
1319+
for (size_t i = 0; i < sizeof(rsaMechs)/sizeof(rsaMechs[0]); i++)
1320+
{
1321+
CK_MECHANISM mechanism = { rsaMechs[i], NULL_PTR, 0 };
1322+
rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hEcPriv) );
1323+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1324+
}
1325+
1326+
// DSA mechanisms with EC key
1327+
CK_MECHANISM_TYPE dsaMechs[] = { CKM_DSA, CKM_DSA_SHA1, CKM_DSA_SHA256 };
1328+
for (size_t i = 0; i < sizeof(dsaMechs)/sizeof(dsaMechs[0]); i++)
1329+
{
1330+
CK_MECHANISM mechanism = { dsaMechs[i], NULL_PTR, 0 };
1331+
rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hEcPriv) );
1332+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1333+
}
1334+
#endif
1335+
1336+
// RSA private key with ECDSA/EdDSA mechanisms
1337+
CK_OBJECT_HANDLE hRsaPub = CK_INVALID_HANDLE, hRsaPriv = CK_INVALID_HANDLE;
1338+
rv = generateRSA(hSession, IN_SESSION, IS_PUBLIC, IN_SESSION, IS_PUBLIC, hRsaPub, hRsaPriv);
1339+
CPPUNIT_ASSERT(rv == CKR_OK);
1340+
1341+
#ifdef WITH_ECC
1342+
// ECDSA mechanisms with RSA key
1343+
CK_MECHANISM_TYPE ecdsaMechs[] = { CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDSA_SHA256 };
1344+
for (size_t i = 0; i < sizeof(ecdsaMechs)/sizeof(ecdsaMechs[0]); i++)
1345+
{
1346+
CK_MECHANISM mechanism = { ecdsaMechs[i], NULL_PTR, 0 };
1347+
rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hRsaPriv) );
1348+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1349+
}
1350+
#endif
1351+
1352+
#ifdef WITH_EDDSA
1353+
// EdDSA mechanism with RSA key
1354+
{
1355+
CK_MECHANISM mechanism = { CKM_EDDSA, NULL_PTR, 0 };
1356+
rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hRsaPriv) );
1357+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1358+
}
1359+
#endif
1360+
1361+
C_Logout(hSession);
1362+
C_CloseSession(hSession);
1363+
}
1364+
1365+
// Same as above but for C_VerifyInit.
1366+
void SignVerifyTests::testVerifyInitWrongKeyType()
1367+
{
1368+
CK_RV rv;
1369+
CK_SESSION_HANDLE hSession;
1370+
1371+
// Just make sure that we finalize any previous tests
1372+
CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
1373+
1374+
rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
1375+
CPPUNIT_ASSERT(rv == CKR_OK);
1376+
1377+
rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
1378+
CPPUNIT_ASSERT(rv == CKR_OK);
1379+
1380+
rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
1381+
CPPUNIT_ASSERT(rv == CKR_OK);
1382+
1383+
// EC public key with RSA/DSA mechanisms
1384+
CK_OBJECT_HANDLE hEcPub = CK_INVALID_HANDLE, hEcPriv = CK_INVALID_HANDLE;
1385+
#ifdef WITH_ECC
1386+
rv = generateEC("P-256", hSession, IN_SESSION, IS_PUBLIC, IN_SESSION, IS_PUBLIC, hEcPub, hEcPriv);
1387+
CPPUNIT_ASSERT(rv == CKR_OK);
1388+
1389+
// RSA mechanisms with EC key
1390+
CK_MECHANISM_TYPE rsaMechs[] = {
1391+
CKM_RSA_PKCS, CKM_RSA_X_509,
1392+
CKM_SHA1_RSA_PKCS, CKM_SHA256_RSA_PKCS,
1393+
CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS
1394+
};
1395+
for (size_t i = 0; i < sizeof(rsaMechs)/sizeof(rsaMechs[0]); i++)
1396+
{
1397+
CK_MECHANISM mechanism = { rsaMechs[i], NULL_PTR, 0 };
1398+
rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession, &mechanism, hEcPub) );
1399+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1400+
}
1401+
1402+
// DSA mechanisms with EC key
1403+
CK_MECHANISM_TYPE dsaMechs[] = { CKM_DSA, CKM_DSA_SHA1, CKM_DSA_SHA256 };
1404+
for (size_t i = 0; i < sizeof(dsaMechs)/sizeof(dsaMechs[0]); i++)
1405+
{
1406+
CK_MECHANISM mechanism = { dsaMechs[i], NULL_PTR, 0 };
1407+
rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession, &mechanism, hEcPub) );
1408+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1409+
}
1410+
#endif
1411+
1412+
// RSA public key with ECDSA/EdDSA mechanisms
1413+
CK_OBJECT_HANDLE hRsaPub = CK_INVALID_HANDLE, hRsaPriv = CK_INVALID_HANDLE;
1414+
rv = generateRSA(hSession, IN_SESSION, IS_PUBLIC, IN_SESSION, IS_PUBLIC, hRsaPub, hRsaPriv);
1415+
CPPUNIT_ASSERT(rv == CKR_OK);
1416+
1417+
#ifdef WITH_ECC
1418+
// ECDSA mechanisms with RSA key
1419+
CK_MECHANISM_TYPE ecdsaMechs[] = { CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDSA_SHA256 };
1420+
for (size_t i = 0; i < sizeof(ecdsaMechs)/sizeof(ecdsaMechs[0]); i++)
1421+
{
1422+
CK_MECHANISM mechanism = { ecdsaMechs[i], NULL_PTR, 0 };
1423+
rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession, &mechanism, hRsaPub) );
1424+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1425+
}
1426+
#endif
1427+
1428+
#ifdef WITH_EDDSA
1429+
// EdDSA mechanism with RSA key
1430+
{
1431+
CK_MECHANISM mechanism = { CKM_EDDSA, NULL_PTR, 0 };
1432+
rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession, &mechanism, hRsaPub) );
1433+
CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
1434+
}
1435+
#endif
1436+
1437+
C_Logout(hSession);
1438+
C_CloseSession(hSession);
1439+
}

src/lib/test/SignVerifyTests.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class SignVerifyTests : public TestsBase
5252
#ifdef WITH_ML_DSA
5353
CPPUNIT_TEST_PARAMETERIZED(testMLDSASignVerify, {CKP_ML_DSA_44, CKP_ML_DSA_65, CKP_ML_DSA_87});
5454
#endif
55+
CPPUNIT_TEST(testSignInitWrongKeyType);
56+
CPPUNIT_TEST(testVerifyInitWrongKeyType);
5557
CPPUNIT_TEST_SUITE_END();
5658

5759
public:
@@ -66,6 +68,8 @@ class SignVerifyTests : public TestsBase
6668
#ifdef WITH_ML_DSA
6769
void testMLDSASignVerify(CK_ULONG parameterSet);
6870
#endif
71+
void testSignInitWrongKeyType();
72+
void testVerifyInitWrongKeyType();
6973

7074
protected:
7175
CK_RV generateRSA(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);

0 commit comments

Comments
 (0)