diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp index dac68a3c6..0c8feef76 100644 --- a/src/lib/SoftHSM.cpp +++ b/src/lib/SoftHSM.cpp @@ -1162,7 +1162,7 @@ CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_ case CKM_AES_GCM: pInfo->ulMinKeySize = 16; pInfo->ulMaxKeySize = 32; - pInfo->flags |= CKF_ENCRYPT | CKF_DECRYPT; + pInfo->flags |= CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; break; case CKM_AES_KEY_WRAP: pInfo->ulMinKeySize = 16; @@ -2197,7 +2197,7 @@ CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech size_t bb = 8; size_t counterBits = 0; ByteString aad; - size_t tagBytes = 0; + size_t tagBits = 0; switch(pMechanism->mechanism) { #ifndef WITH_FIPS case CKM_DES_ECB: @@ -2347,13 +2347,12 @@ CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); - tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; - if (tagBytes > 128 || tagBytes % 8 != 0) + tagBits = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; + if (tagBits < 64 || tagBits > 128 || tagBits % 8 != 0) { - DEBUG_MSG("Invalid ulTagBits value"); + DEBUG_MSG("Invalid ulTagBits value %d", tagBits); return CKR_ARGUMENTS_BAD; } - tagBytes = tagBytes / 8; break; default: return CKR_MECHANISM_INVALID; @@ -2374,7 +2373,7 @@ CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech secretkey->setBitLen(secretkey->getKeyBits().size() * bb); // Initialize encryption - if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes)) + if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBits>>3)) { cipher->recycleKey(secretkey); CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); @@ -2917,7 +2916,7 @@ CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech size_t bb = 8; size_t counterBits = 0; ByteString aad; - size_t tagBytes = 0; + size_t tagBits = 0; switch(pMechanism->mechanism) { #ifndef WITH_FIPS case CKM_DES_ECB: @@ -3067,13 +3066,12 @@ CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); - tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; - if (tagBytes > 128 || tagBytes % 8 != 0) + tagBits = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; + if (tagBits > 128 || tagBits < 96 || tagBits % 8 != 0) { - DEBUG_MSG("Invalid ulTagBits value"); + DEBUG_MSG("Invalid ulTagBits value %d", tagBits); return CKR_ARGUMENTS_BAD; } - tagBytes = tagBytes / 8; break; default: return CKR_MECHANISM_INVALID; @@ -3094,7 +3092,7 @@ CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech secretkey->setBitLen(secretkey->getKeyBits().size() * bb); // Initialize decryption - if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes)) + if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBits>>3)) { cipher->recycleKey(secretkey); CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); @@ -6262,6 +6260,12 @@ CK_RV SoftHSM::WrapKeySym algo = SymAlgo::AES; break; + case CKM_AES_GCM: + if (keydata.size() % 16 != 0) + return CKR_KEY_SIZE_RANGE; + algo = SymAlgo::AES; + break; + case CKM_AES_CBC_PAD: blocksize = 16; wrappedlen = RFC5652Pad(keydata, blocksize); @@ -6298,9 +6302,51 @@ CK_RV SoftHSM::WrapKeySym ByteString iv; ByteString encryptedFinal; - + ByteString aad; + size_t tagBits = 0; + size_t counterBits = 0; + switch(pMechanism->mechanism) { + case CKM_AES_GCM: + if (pMechanism->pParameter == NULL_PTR || + pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS)) + { + DEBUG_MSG("GCM mode requires parameters"); + return CKR_ARGUMENTS_BAD; + } + iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); + memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); + aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); + memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); + tagBits = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; + if (tagBits < 96 || tagBits > 128 || tagBits % 8 != 0) + { + DEBUG_MSG("Invalid ulTagBits value %d", tagBits); + return CKR_ARGUMENTS_BAD; + } + if (!cipher->encryptInit(wrappingkey, SymMode::GCM, iv, false, counterBits, aad, tagBits>>3)) + { + cipher->recycleKey(wrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_MECHANISM_INVALID; + } + if (!cipher->encryptUpdate(keydata, wrapped)) + { + cipher->recycleKey(wrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + // Finalize encryption + if (!cipher->encryptFinal(encryptedFinal)) + { + cipher->recycleKey(wrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + wrapped += encryptedFinal; + break; + case CKM_AES_CBC: case CKM_AES_CBC_PAD: case CKM_DES3_CBC: @@ -6329,6 +6375,7 @@ CK_RV SoftHSM::WrapKeySym } wrapped += encryptedFinal; break; + default: // Wrap the key if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped)) @@ -6480,6 +6527,13 @@ CK_RV SoftHSM::C_WrapKey pMechanism->ulParameterLen != 16) return CKR_ARGUMENTS_BAD; break; + + case CKM_AES_GCM: + if (pMechanism->pParameter == NULL_PTR || + pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS)) + return CKR_ARGUMENTS_BAD; + break; + default: return CKR_MECHANISM_INVALID; } @@ -6506,21 +6560,41 @@ CK_RV SoftHSM::C_WrapKey } // 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 || 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 || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) - return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; - if ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CBC_PAD) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) - return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; - if (pMechanism->mechanism == CKM_DES3_CBC && (wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES2 || - wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES3)) - return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + switch(pMechanism->mechanism) + { + case CKM_AES_KEY_WRAP: + case CKM_AES_KEY_WRAP_PAD: + case CKM_AES_GCM: + case CKM_AES_CBC_PAD: + if (wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + +#ifndef WITH_FIPS + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; +#endif + + case CKM_DES3_CBC: + case CKM_DES3_CBC_PAD: + if (wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES2 || + wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES3) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY || + wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + } // Check if the wrapping key can be used for wrapping if (wrapKey->getBooleanValue(CKA_WRAP, false) == false) @@ -6739,6 +6813,11 @@ CK_RV SoftHSM::UnwrapKeySym algo = SymAlgo::AES; blocksize = 16; break; + + case CKM_AES_GCM: + algo = SymAlgo::AES; + blocksize = 16; + break; case CKM_DES3_CBC_PAD: algo = SymAlgo::DES3; @@ -6766,51 +6845,93 @@ CK_RV SoftHSM::UnwrapKeySym ByteString iv; ByteString decryptedFinal; + ByteString aad; + size_t tagBits = 0; + size_t counterBits = 0; CK_RV rv = CKR_OK; switch(pMechanism->mechanism) { - - case CKM_AES_CBC_PAD: - case CKM_DES3_CBC_PAD: - iv.resize(blocksize); - memcpy(&iv[0], pMechanism->pParameter, blocksize); + case CKM_AES_CBC_PAD: + case CKM_DES3_CBC_PAD: + iv.resize(blocksize); + memcpy(&iv[0], pMechanism->pParameter, blocksize); - if (!cipher->decryptInit(unwrappingkey, SymMode::CBC, iv, false)) - { - cipher->recycleKey(unwrappingkey); - CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); - return CKR_MECHANISM_INVALID; - } - if (!cipher->decryptUpdate(wrapped, keydata)) - { - cipher->recycleKey(unwrappingkey); - CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); - return CKR_GENERAL_ERROR; - } - // Finalize encryption - if (!cipher->decryptFinal(decryptedFinal)) - { - cipher->recycleKey(unwrappingkey); - CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); - return CKR_GENERAL_ERROR; - } - keydata += decryptedFinal; + if (!cipher->decryptInit(unwrappingkey, SymMode::CBC, iv, false)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_MECHANISM_INVALID; + } + if (!cipher->decryptUpdate(wrapped, keydata)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + // Finalize encryption + if (!cipher->decryptFinal(decryptedFinal)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + keydata += decryptedFinal; - if(!RFC5652Unpad(keydata,blocksize)) - { + if(!RFC5652Unpad(keydata,blocksize)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; // TODO should be another error + } + break; + + case CKM_AES_GCM: + if (pMechanism->pParameter == NULL_PTR || + pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS)) + { + DEBUG_MSG("GCM mode requires parameters"); + return CKR_ARGUMENTS_BAD; + } + iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); + memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen); + aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); + memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen); + tagBits = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits; + if (tagBits < 96 || tagBits > 128 || tagBits % 8 != 0) + { + DEBUG_MSG("Invalid ulTagBits value: %d", tagBits); + return CKR_ARGUMENTS_BAD; + } + + if (!cipher->decryptInit(unwrappingkey, SymMode::GCM, iv, false, counterBits, aad, tagBits>>3)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_MECHANISM_INVALID; + } + if (!cipher->decryptUpdate(wrapped, keydata)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + // Finalize encryption + if (!cipher->decryptFinal(decryptedFinal)) + { + cipher->recycleKey(unwrappingkey); + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return CKR_GENERAL_ERROR; + } + keydata += decryptedFinal; + break; + default: + + // Unwrap the key + CK_RV rv = CKR_OK; + if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata)) + rv = CKR_GENERAL_ERROR; cipher->recycleKey(unwrappingkey); CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); - return CKR_GENERAL_ERROR; // TODO should be another error - } - break; - - default: - // Unwrap the key - CK_RV rv = CKR_OK; - if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata)) - rv = CKR_GENERAL_ERROR; - cipher->recycleKey(unwrappingkey); - CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); } return rv; } @@ -6946,6 +7067,25 @@ CK_RV SoftHSM::C_UnwrapKey pMechanism->ulParameterLen != 8) return CKR_ARGUMENTS_BAD; break; + + case CKM_AES_GCM: + // for GCM, the shortest block is 16 bytes + authentication tag + // in this impementation, 96 bits are requested at least, in multiples of 8 bits + // possibles values are therefore: + // - 96 bits (12 bytes) + // - 104 bits (13 bytes) + // - 112 bits (14 bytes) + // - 120 bits (15 bytes) + // - 128 bits (16 bytes) + // minimum length of the overall message in bytes is therefore 16 + 12 = 28 bytes + // remainder lengths (after modulo 16) between 1 and 11 are forbidden + if ((ulWrappedKeyLen < 28) || ( (ulWrappedKeyLen % 16) && (ulWrappedKeyLen % 16) < 12) ) + return CKR_WRAPPED_KEY_LEN_RANGE; + // Does not handle optional init vector + if (pMechanism->pParameter == NULL_PTR || + pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS)) + return CKR_ARGUMENTS_BAD; + break; default: return CKR_MECHANISM_INVALID; @@ -6973,21 +7113,42 @@ CK_RV SoftHSM::C_UnwrapKey } // Check unwrapping key class and type - if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY) - return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; - if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) - 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 || 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 || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) - return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; - if ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CBC_PAD) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) - return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; - if (pMechanism->mechanism == CKM_DES3_CBC && (unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES2 || - unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES3)) - return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + switch(pMechanism->mechanism) + { + case CKM_AES_KEY_WRAP: + case CKM_AES_KEY_WRAP_PAD: + case CKM_AES_GCM: + case CKM_AES_CBC_PAD: + if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + +#ifndef WITH_FIPS + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; +#endif + + case CKM_DES3_CBC: + case CKM_DES3_CBC_PAD: + if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY || + unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES2 || + unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DES3) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY || + unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + + } // Check if the unwrapping key can be used for unwrapping if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false) diff --git a/src/lib/test/SymmetricAlgorithmTests.cpp b/src/lib/test/SymmetricAlgorithmTests.cpp index f6353f607..aaabc6422 100644 --- a/src/lib/test/SymmetricAlgorithmTests.cpp +++ b/src/lib/test/SymmetricAlgorithmTests.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include //#include @@ -64,6 +66,7 @@ WrappedMaterial rsa2048underdes56 CKM_DES_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xdf, 0xba, 0xd0, 0xdf, 0x91, 0xda, 0x3e, 0xf1, @@ -71,6 +74,8 @@ WrappedMaterial rsa2048underdes56 { // IV 0x48, 0x66, 0xc8, 0x2c, 0xe1, 0x40, 0x52, 0xa9, }, + { // AAD (GCM only) + }, { // wrapped RSA key 0x74, 0x55, 0xe1, 0x60, 0x4e, 0x73, 0x91, 0x7f, 0x2c, 0xd9, 0x8a, 0xb7, 0x0c, 0x0e, 0xc6, 0xa7, 0x15, 0x3f, 0x9d, 0x72, 0x26, 0x7f, 0xb2, 0x02, 0x49, 0xe3, 0x43, 0x1f, 0x14, 0xba, 0xdb, 0xf0, @@ -161,6 +166,7 @@ WrappedMaterial rsa2048underdes112 CKM_DES3_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xef, 0x4c, 0x9d, 0x73, 0xc8, 0x45, 0x0d, 0x31, 0x97, 0x4a, 0xfe, 0x2f, 0x9d, 0x94, 0x98, 0x54, @@ -168,6 +174,8 @@ WrappedMaterial rsa2048underdes112 { // IV 0x74, 0x83, 0xdb, 0xb8, 0xb3, 0x9f, 0x55, 0xdc, }, + { // AAD (GCM only) + }, { // wrapped RSA key 0xca, 0x83, 0xa0, 0x2f, 0x06, 0xab, 0xc5, 0xf3, 0xa6, 0x10, 0x93, 0x75, 0x93, 0x8f, 0xa0, 0x9f, 0x6e, 0x71, 0xbc, 0xa7, 0x69, 0xf8, 0x6c, 0xff, 0x92, 0xab, 0x6f, 0x08, 0xdd, 0x4b, 0xd3, 0x90, @@ -259,6 +267,7 @@ WrappedMaterial rsa2048underdes168 CKM_DES3_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xfe, 0x0e, 0x7f, 0x68, 0x9e, 0xcb, 0x23, 0x68, 0xb3, 0x51, 0xea, 0x49, 0x26, 0xf2, 0xf8, 0x49, @@ -267,6 +276,8 @@ WrappedMaterial rsa2048underdes168 { // IV 0x1e, 0x06, 0xbb, 0xa6, 0xd4, 0x3e, 0x1d, 0x05, }, + { // AAD (GCM only) + }, { // wrapped RSA key 0x45, 0x84, 0xa6, 0xc7, 0xec, 0x3c, 0x6b, 0x38, 0xbe, 0x6f, 0x0d, 0x9d, 0x3a, 0x80, 0x17, 0x2d, 0xab, 0x6b, 0x6f, 0x82, 0x5a, 0x6d, 0x8e, 0x50, 0x84, 0xf2, 0x61, 0x29, 0xc8, 0x99, 0x97, 0xac, @@ -356,6 +367,7 @@ WrappedMaterial rsa2048underaes128 CKM_AES_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xd5, 0x20, 0xbc, 0xaa, 0x9c, 0x3f, 0x1f, 0x32, @@ -365,6 +377,8 @@ WrappedMaterial rsa2048underaes128 0x55, 0x7c, 0xc6, 0xab, 0xdf, 0xee, 0xa1, 0x10, 0xeb, 0x89, 0x42, 0x31, 0x72, 0x82, 0xbc, 0xeb }, + { // AAD (GCM only) + }, { // wrapped RSA key 0x7d, 0xa7, 0xa9, 0xe9, 0x8f, 0x73, 0x76, 0xde, 0x66, 0x9d, 0x81, 0x0b, 0x6f, 0xcb, 0x17, 0x87, 0xb7, 0x2d, 0xb8, 0xc0, 0x9e, 0xec, 0x1f, 0xd5, 0x4a, 0x3a, 0x82, 0x72, 0xe4, 0x65, 0x55, 0x1e, @@ -455,6 +469,7 @@ WrappedMaterial rsa2048underaes192 CKM_AES_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xe3, 0x38, 0xb0, 0xa3, 0xa9, 0x49, 0x66, 0xf3, 0x1b, 0xe8, 0xc6, 0x3c, 0x40, 0x9d, 0xe3, 0xf2, @@ -463,6 +478,8 @@ WrappedMaterial rsa2048underaes192 { // IV 0x48, 0x5c, 0x96, 0x7e, 0x41, 0x47, 0xcf, 0x17, 0x35, 0xa3, 0x12, 0xf1, 0x76, 0x2e, 0x12, 0xdc, }, + { // AAD (GCM only) + }, { // wrapped RSA key 0x90, 0xe2, 0x9d, 0x99, 0xcb, 0xc3, 0xfe, 0x34, 0x4f, 0xe1, 0x73, 0x7b, 0xc2, 0xde, 0xed, 0xf3, 0x13, 0x4c, 0x0e, 0xa1, 0x2d, 0xfe, 0x82, 0xf3, 0x69, 0x04, 0xad, 0x8e, 0xcc, 0x23, 0x35, 0x0a, @@ -552,6 +569,7 @@ WrappedMaterial rsa2048underaes256 CKM_AES_CBC_PAD, // mechanism CKO_PRIVATE_KEY, // wrapped object class CKK_RSA, // wrapped key type + 0, // tagBits (GCM only) { { // key 0xda, 0x77, 0x34, 0x87, 0x98, 0x5c, 0xd3, 0x27, 0xc6, 0x11, 0x1a, 0x83, 0x65, 0x18, 0xb9, 0xe3, @@ -560,6 +578,8 @@ WrappedMaterial rsa2048underaes256 { // IV 0x0e, 0xee, 0x81, 0x64, 0x0d, 0x6d, 0xe1, 0x6e, 0xca, 0xbb, 0x39, 0x0c, 0xda, 0xda, 0x86, 0xe6, }, + { // AAD (GCM only) + }, { // wrapped RSA key 0x86, 0x36, 0x43, 0xcb, 0x0e, 0x85, 0xb7, 0xaa, 0x59, 0x16, 0x92, 0x70, 0x31, 0x06, 0x54, 0x22, 0xcb, 0xf8, 0x32, 0x2f, 0xfd, 0xec, 0xb6, 0xc8, 0x19, 0x6f, 0x66, 0x50, 0x2d, 0x23, 0x26, 0xe1, @@ -642,12 +662,70 @@ WrappedMaterial rsa2048underaes256 } }; +WrappedMaterial aes128underaes256gcm +{ + "AES128 wrapped under AES256 using CKM_AES_GCM", + CKK_AES, // wrapping key type + CKM_AES_GCM, // mechanism + CKO_SECRET_KEY, // wrapped object class + CKK_AES, // wrapped key type + 128, // tagBits (GCM only) + { + { // key + 0x62, 0x63, 0xdf, 0x89, 0x9b, 0xf2, 0xeb, 0xb4, 0x84, 0x66, 0xf7, 0xe5, 0x51, 0xd0, 0x2c, 0x32, + 0x59, 0x90, 0xd7, 0x0b, 0xa0, 0xec, 0x33, 0xb2, 0xdd, 0x86, 0x3f, 0x40, 0x58, 0xb3, 0xa4, 0x65, + }, + { // IV + 0xfb, 0x71, 0x20, 0x70, 0x28, 0xc8, 0xd4, 0x19, 0xd5, 0xf2, 0x0f, 0x86, 0xb8, 0x8b, 0x22, 0x6d, + }, + { // AAD (GCM only) + // No AAD specified + }, + { // wrapped AES key + 0x0c, 0x82, 0x46, 0xdd, 0x1e, 0x07, 0x29, 0xf2, 0xbb, 0x54, 0x0f, 0xbb, 0xe0, 0xdd, 0x78, 0x77, + 0xca, 0x01, 0x41, 0x1d, 0xf0, 0xdd, 0x19, 0x36, 0x79, 0x1b, 0x52, 0xaa, 0xd3, 0x3d, 0x78, 0x06, + } + } +}; + +WrappedMaterial aes256underaes256gcm +{ + "AES256 wrapped under AES256 using CKM_AES_GCM", + CKK_AES, // wrapping key type + CKM_AES_GCM, // mechanism + CKO_SECRET_KEY, // wrapped object class + CKK_AES, // wrapped key type + 128, // tagBits (GCM only) + { + { // key + 0x62, 0x63, 0xdf, 0x89, 0x9b, 0xf2, 0xeb, 0xb4, 0x84, 0x66, 0xf7, 0xe5, 0x51, 0xd0, 0x2c, 0x32, + 0x59, 0x90, 0xd7, 0x0b, 0xa0, 0xec, 0x33, 0xb2, 0xdd, 0x86, 0x3f, 0x40, 0x58, 0xb3, 0xa4, 0x65, + }, + { // IV + 0x4a, 0x82, 0xd3, 0xaa, 0x41, 0xd1, 0x1b, 0xae, 0xd0, 0x61, 0xd8, 0x9f, 0xaf, 0x22, 0x86, 0xc9, + }, + { // AAD (GCM only) + 'd', 'd', 'd', 'd', + }, + { // wrapped AES key + 0x89, 0x12, 0xa1, 0x46, 0x12, 0x1c, 0x85, 0xcc, 0x88, 0xe1, 0xa8, 0x30, 0x5b, 0xdf, 0xc0, 0x27, + 0xf1, 0xb5, 0x29, 0xba, 0xea, 0x58, 0xd9, 0x58, 0xae, 0xe1, 0xf3, 0x69, 0x37, 0xcd, 0x7b, 0x20, + 0x61, 0x18, 0x2f, 0x19, 0xc4, 0xa8, 0xa5, 0x2b, 0xba, 0x3c, 0x1e, 0x03, 0x4e, 0x84, 0xb4, 0x3e, + } + } +}; + std::vector aesCBCWrappedKeys { rsa2048underaes128, rsa2048underaes192, rsa2048underaes256, }; +std::vector aesGCMWrappedKeys { + aes128underaes256gcm, + aes256underaes256gcm, +}; + std::vector desCBCWrappedKeys { #ifndef WITH_FIPS rsa2048underdes56, @@ -657,6 +735,17 @@ std::vector desCBCWrappedKeys { }; +// a small helper function to display int as hex strings +// copied from https://stackoverflow.com/a/48643043/979318 + +template +static inline std::string hex(T val, size_t width=sizeof(T)*2) +{ + std::stringstream ss; + ss << std::setfill('0') << std::setw(width) << std::hex << (val|0); + return ss.str(); +} + CK_RV SymmetricAlgorithmTests::generateGenericKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey) { @@ -958,7 +1047,7 @@ void SymmetricAlgorithmTests::encryptDecrypt( if ( isSizeOK ) { CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv ); std::vector vDecryptedData(ulDataLen); - CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "C_Decrypt() call fails with mechanism 0x" + hex(pMechanism->mechanism,8), (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) ) ); vDecryptedData.resize(ulDataLen); CPPUNIT_ASSERT_MESSAGE("C_Encrypt C_Decrypt does not give the original", vData==vDecryptedData); } else { @@ -1142,15 +1231,38 @@ void SymmetricAlgorithmTests::aesWrapUnwrapGeneric(CK_MECHANISM_TYPE mechanismTy CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET; CK_BYTE keyPtr[128]; CK_ULONG keyLen = - mechanismType == CKM_AES_KEY_WRAP_PAD ? 125UL : 128UL; + mechanismType == CKM_AES_KEY_WRAP_PAD ? sizeof(keyPtr)-3 : sizeof(keyPtr); CK_RV rv; CK_BYTE ivPtr[16]; - if( mechanismType == CKM_AES_CBC_PAD ) { - rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, ivPtr, sizeof ivPtr) ); - CPPUNIT_ASSERT(rv == CKR_OK); - mechanism.pParameter = ivPtr; - mechanism.ulParameterLen = sizeof ivPtr; + CK_BYTE aad[64]; + CK_GCM_PARAMS gcmparams = { }; + + switch(mechanismType) + { + case CKM_AES_CBC_PAD: + rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, ivPtr, sizeof ivPtr) ); + CPPUNIT_ASSERT(rv == CKR_OK); + mechanism.pParameter = ivPtr; + mechanism.ulParameterLen = sizeof ivPtr; + break; + + case CKM_AES_GCM: + rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, ivPtr, sizeof ivPtr) ); + CPPUNIT_ASSERT(rv == CKR_OK); + rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, aad, sizeof aad) ); + CPPUNIT_ASSERT(rv == CKR_OK); + + gcmparams.pIv = ivPtr; + gcmparams.ulIvLen = sizeof ivPtr; + gcmparams.ulIvBits = gcmparams.ulIvLen<<3; + gcmparams.pAAD = aad; + gcmparams.ulAADLen = sizeof aad; + gcmparams.ulTagBits = 128; + + mechanism.pParameter = &gcmparams; + mechanism.ulParameterLen = sizeof gcmparams; + break; } CK_ATTRIBUTE attribs[] = { @@ -1647,6 +1759,7 @@ void SymmetricAlgorithmTests::testAesWrapUnwrap() aesWrapUnwrapGeneric(CKM_AES_KEY_WRAP, hSession, hKey); aesWrapUnwrapGeneric(CKM_AES_CBC_PAD, hSession, hKey); + aesWrapUnwrapGeneric(CKM_AES_GCM, hSession, hKey); aesWrapUnwrapRsa(CKM_AES_KEY_WRAP, hSession, hKey); aesWrapUnwrapRsa(CKM_AES_CBC_PAD, hSession, hKey); @@ -1668,6 +1781,11 @@ void SymmetricAlgorithmTests::testAesWrapUnwrap() { unwrapKnownKey(hSession, wrapped); } + + for ( auto &wrapped : aesGCMWrappedKeys ) + { + unwrapKnownKey(hSession, wrapped); + } } void SymmetricAlgorithmTests::testDesEncryptDecrypt() diff --git a/src/lib/test/SymmetricAlgorithmTests.h b/src/lib/test/SymmetricAlgorithmTests.h index 642be31fa..d7596502a 100644 --- a/src/lib/test/SymmetricAlgorithmTests.h +++ b/src/lib/test/SymmetricAlgorithmTests.h @@ -125,6 +125,8 @@ class WrappedMaterial { CK_KEY_TYPE m_wrappedkeytype; CK_KEY_TYPE m_wrappingkeytype; CK_MECHANISM m_mechanism; + size_t m_tagbits; // for AES GCM + CK_GCM_PARAMS m_gcm_params; // for AES GCM public: @@ -133,11 +135,13 @@ class WrappedMaterial { CK_MECHANISM_TYPE mechType, CK_OBJECT_CLASS wrappedObjectClass, CK_KEY_TYPE wrappedKeyType, + size_t tagBits, std::initializer_list il ) : m_descr ( description ), m_wrappedobjectclass ( wrappedObjectClass ), m_wrappedkeytype ( wrappedKeyType ), - m_wrappingkeytype ( wrappingKeyType ) + m_wrappingkeytype ( wrappingKeyType ), + m_tagbits ( tagBits ) { for( auto &&i : il ) { m_data.emplace_back( std::move(i) ); @@ -147,19 +151,32 @@ class WrappedMaterial { std::string description() { return m_descr; } Bytes &wrappingKeyBytes() { return m_data[0]; } - Bytes &cbcIv() { return m_data[1]; } - Bytes &wrappedKey() { return m_data[2]; }; + Bytes &iv() { return m_data[1]; } + Bytes &aad() { return m_data[2]; } + size_t tagBits() { return m_tagbits; } + Bytes &wrappedKey() { return m_data[3]; }; CK_OBJECT_CLASS &wrappedObjectClass() { return m_wrappedobjectclass; }; CK_KEY_TYPE &wrappingKeyType() { return m_wrappingkeytype; }; CK_KEY_TYPE &wrappedKeyType() { return m_wrappedkeytype; }; CK_MECHANISM &mechanism() { - // adjust mechanism to point to data provided - // we do it here and not in the constructor, - // has data() can move around as we push to the vectors - m_mechanism.pParameter = m_data[1].data(); - m_mechanism.ulParameterLen = m_data[1].size(); + if(m_mechanism.mechanism==CKM_AES_GCM) { + m_gcm_params = { + .pIv = m_data[1].data(), + .ulIvLen = m_data[1].size(), + .ulIvBits = m_data[1].size()<<3, + .pAAD = m_data[2].data(), + .ulAADLen = m_data[2].size(), + .ulTagBits = m_tagbits }; + + m_mechanism.pParameter = &m_gcm_params; + m_mechanism.ulParameterLen = sizeof(CK_GCM_PARAMS); + } else { + // other cases: pParameter points to the IV + m_mechanism.pParameter = m_data[1].data(); + m_mechanism.ulParameterLen = m_data[1].size(); + } return m_mechanism; }; }; - + #endif // !_SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H