softhsm/softhsm-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch
2014-10-08 09:03:58 -04:00

375 lines
14 KiB
Diff

diff -Naur softhsm-2.0.0b1-orig/src/lib/cryptoki_compat/pkcs11.h softhsm-2.0.0b1/src/lib/cryptoki_compat/pkcs11.h
--- softhsm-2.0.0b1-orig/src/lib/cryptoki_compat/pkcs11.h 2014-09-09 20:05:14.000000000 -0400
+++ softhsm-2.0.0b1/src/lib/cryptoki_compat/pkcs11.h 2014-10-07 13:57:22.460010567 -0400
@@ -902,6 +902,8 @@
#define CKG_MGF1_SHA512 (0x00000004)
#define CKG_MGF1_SHA224 (0x00000005)
+#define CKZ_DATA_SPECIFIED (0x00000001)
+
struct ck_rsa_pkcs_oaep_params {
ck_mechanism_type_t hash_alg;
unsigned long mgf;
diff -Naur softhsm-2.0.0b1-orig/src/lib/SoftHSM.cpp softhsm-2.0.0b1/src/lib/SoftHSM.cpp
--- softhsm-2.0.0b1-orig/src/lib/SoftHSM.cpp 2014-10-07 13:56:04.284955056 -0400
+++ softhsm-2.0.0b1/src/lib/SoftHSM.cpp 2014-10-07 13:57:25.478089923 -0400
@@ -815,7 +815,7 @@
case CKM_RSA_PKCS_OAEP:
pInfo->ulMinKeySize = rsaMinSize;
pInfo->ulMaxKeySize = rsaMaxSize;
- pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
break;
case CKM_DES_KEY_GEN:
case CKM_DES2_KEY_GEN:
@@ -1941,22 +1941,9 @@
isRSA = true;
break;
case CKM_RSA_PKCS_OAEP:
- if (pMechanism->pParameter == NULL_PTR ||
- pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
- {
- ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
- return CKR_ARGUMENTS_BAD;
- }
- if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
- {
- ERROR_MSG("hashAlg must be CKM_SHA_1");
- return CKR_ARGUMENTS_BAD;
- }
- if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
- {
- ERROR_MSG("mgf must be CKG_MGF1_SHA1");
- return CKR_ARGUMENTS_BAD;
- }
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
mechanism = AsymMech::RSA_PKCS_OAEP;
isRSA = true;
@@ -4969,25 +4956,42 @@
ByteString& wrapped
)
{
- size_t bb = 8;
+ const size_t bb = 8;
AsymAlgo::Type algo = AsymAlgo::Unknown;
AsymMech::Type mech = AsymMech::Unknown;
+ CK_ULONG modulus_length;
switch(pMechanism->mechanism) {
case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
algo = AsymAlgo::RSA;
- mech = AsymMech::RSA_PKCS;
- CK_ULONG modulus_length;
if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
return CKR_GENERAL_ERROR;
modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
// adjust key bit length
modulus_length /= bb;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mech = AsymMech::RSA_PKCS;
// RFC 3447 section 7.2.1
if (keydata.size() > modulus_length - 11)
return CKR_KEY_SIZE_RANGE;
break;
+ case CKM_RSA_PKCS_OAEP:
+ mech = AsymMech::RSA_PKCS_OAEP;
+ // SHA-1 is the only supported option
+ // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
+ if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
+ return CKR_KEY_SIZE_RANGE;
+ break;
+
default:
return CKR_MECHANISM_INVALID;
}
@@ -5004,6 +5008,7 @@
switch(pMechanism->mechanism) {
case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
{
cipher->recyclePublicKey(publicKey);
@@ -5050,6 +5055,7 @@
Session* session = (Session*)handleManager->getSession(hSession);
if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+ CK_RV rv;
// Check the mechanism, only accept advanced AES key wrapping and RSA
switch(pMechanism->mechanism)
{
@@ -5065,6 +5071,12 @@
pMechanism->ulParameterLen != 0)
return CKR_ARGUMENTS_BAD;
break;
+ case CKM_RSA_PKCS_OAEP:
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
+ break;
+
default:
return CKR_MECHANISM_INVALID;
}
@@ -5081,7 +5093,7 @@
CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
// Check user credentials for the wrapping key
- CK_RV rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
+ rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
if (rv != CKR_OK)
{
if (rv == CKR_USER_NOT_LOGGED_IN)
@@ -5093,13 +5105,13 @@
// Check wrapping key class and type
if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
- if (pMechanism->mechanism == CKM_RSA_PKCS && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
- if (pMechanism->mechanism == CKM_RSA_PKCS && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
// Check if the wrapping key can be used for wrapping
@@ -5133,8 +5145,8 @@
CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
return CKR_KEY_NOT_WRAPPABLE;
- // CKM_RSA_PKCS can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA
- if (pMechanism->mechanism == CKM_RSA_PKCS && keyClass != CKO_SECRET_KEY)
+ // CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA & section 2.1.8 PKCS #1 RSA OAEP
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
return CKR_KEY_NOT_WRAPPABLE;
// Verify the wrap template attribute
@@ -5338,6 +5350,12 @@
algo = AsymAlgo::RSA;
mode = AsymMech::RSA_PKCS;
break;
+
+ case CKM_RSA_PKCS_OAEP:
+ algo = AsymAlgo::RSA;
+ mode = AsymMech::RSA_PKCS_OAEP;
+ break;
+
default:
return CKR_MECHANISM_INVALID;
}
@@ -5353,6 +5371,7 @@
switch(pMechanism->mechanism) {
case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
{
cipher->recyclePrivateKey(unwrappingkey);
@@ -5398,6 +5417,7 @@
Session* session = (Session*)handleManager->getSession(hSession);
if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+ CK_RV rv;
// Check the mechanism
switch(pMechanism->mechanism)
{
@@ -5424,6 +5444,11 @@
case CKM_RSA_PKCS:
// Input length checks needs to be done later when unwrapping key is known
break;
+ case CKM_RSA_PKCS_OAEP:
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
+ break;
default:
return CKR_MECHANISM_INVALID;
@@ -5441,7 +5466,7 @@
CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
// Check user credentials
- CK_RV rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
+ rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
if (rv != CKR_OK)
{
if (rv == CKR_USER_NOT_LOGGED_IN)
@@ -5457,9 +5482,9 @@
return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
- if (pMechanism->mechanism == CKM_RSA_PKCS && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
- if (pMechanism->mechanism == CKM_RSA_PKCS && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
// Check if the unwrapping key can be used for unwrapping
@@ -9152,3 +9177,47 @@
return bOK;
}
+
+CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
+{
+ // This is a programming error
+ if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
+ ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
+ {
+ ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
+ if (params->hashAlg != CKM_SHA_1)
+ {
+ ERROR_MSG("hashAlg must be CKM_SHA_1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->mgf != CKG_MGF1_SHA1)
+ {
+ ERROR_MSG("mgf must be CKG_MGF1_SHA1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->source != CKZ_DATA_SPECIFIED)
+ {
+ ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->pSourceData != NULL)
+ {
+ ERROR_MSG("pSourceData must be NULL");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->ulSourceDataLen != 0)
+ {
+ ERROR_MSG("ulSourceDataLen must be 0");
+ return CKR_ARGUMENTS_BAD;
+ }
+ return CKR_OK;
+}
diff -Naur softhsm-2.0.0b1-orig/src/lib/SoftHSM.h softhsm-2.0.0b1/src/lib/SoftHSM.h
--- softhsm-2.0.0b1-orig/src/lib/SoftHSM.h 2014-09-09 20:05:23.000000000 -0400
+++ softhsm-2.0.0b1/src/lib/SoftHSM.h 2014-10-07 13:57:24.178055740 -0400
@@ -407,5 +407,7 @@
OSObject *unwrapKey,
ByteString &keydata
);
+
+ CK_RV MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism);
};
diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.cpp softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.cpp
--- softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.cpp 2014-09-09 20:05:14.000000000 -0400
+++ softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.cpp 2014-10-07 13:57:22.461010593 -0400
@@ -165,6 +165,51 @@
CPPUNIT_ASSERT(memcmp(plainText, &recoveredText[ulRecoveredTextLen-sizeof(plainText)], sizeof(plainText)) == 0);
}
+// Check that RSA OAEP mechanism properly validates all input parameters
+void AsymEncryptDecryptTests::rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey)
+{
+ // This is only supported combination of parameters
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_OAEP, NULL, 0 };
+ CK_RV rv;
+
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.pParameter = &oaepParams;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.ulParameterLen = sizeof(oaepParams);
+
+ oaepParams.hashAlg = CKM_AES_CBC;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.hashAlg = CKM_SHA_1;
+ oaepParams.mgf = CKG_MGF1_SHA256;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.mgf = CKG_MGF1_SHA1;
+ oaepParams.source = CKZ_DATA_SPECIFIED - 1;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.source = CKZ_DATA_SPECIFIED;
+ oaepParams.pSourceData = &oaepParams;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.ulSourceDataLen = sizeof(oaepParams);
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.pSourceData = NULL;
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+}
+
void AsymEncryptDecryptTests::testRsaEncryptDecrypt()
{
CK_RV rv;
@@ -203,6 +248,7 @@
rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
CPPUNIT_ASSERT(rv == CKR_OK);
+ rsaOAEPParams(hSessionRO,hPublicKey);
rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey);
rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.h softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.h
--- softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.h 2014-09-09 20:05:14.000000000 -0400
+++ softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.h 2014-10-07 13:57:22.462010619 -0400
@@ -52,6 +52,7 @@
protected:
CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
void rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+ void rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey);
};
#endif // !_SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymWrapUnwrapTests.cpp softhsm-2.0.0b1/src/lib/test/AsymWrapUnwrapTests.cpp
--- softhsm-2.0.0b1-orig/src/lib/test/AsymWrapUnwrapTests.cpp 2014-09-09 20:05:23.000000000 -0400
+++ softhsm-2.0.0b1/src/lib/test/AsymWrapUnwrapTests.cpp 2014-10-07 13:57:25.480089976 -0400
@@ -155,7 +155,7 @@
void AsymWrapUnwrapTests::rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
{
CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
- CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, 1, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
CK_BYTE cipherText[2048];
CK_ULONG ulCipherTextLen;
CK_BYTE symValue[64];
@@ -273,4 +273,5 @@
CPPUNIT_ASSERT(rv == CKR_OK);
rsaWrapUnwrap(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
+ rsaWrapUnwrap(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
}