From 9e67f7ef73c17ac6f15e33e76e70618a751995ba Mon Sep 17 00:00:00 2001 From: Antoine Lochet Date: Fri, 27 Oct 2023 17:56:30 +0200 Subject: [PATCH] Fixed issue #707 by allowing operation OBJECT_OP_UNWRAP to modify attributes when CKA_MODIFIABLE is true --- src/lib/P11Attributes.cpp | 4 +- src/lib/test/SymmetricAlgorithmTests.cpp | 101 +++++++++++++++++++++++ src/lib/test/SymmetricAlgorithmTests.h | 1 + 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/src/lib/P11Attributes.cpp b/src/lib/P11Attributes.cpp index fc9ab0041..937f043fb 100644 --- a/src/lib/P11Attributes.cpp +++ b/src/lib/P11Attributes.cpp @@ -411,13 +411,13 @@ CK_RV P11Attribute::update(Token* token, bool isPrivate, CK_VOID_PTR pValue, CK_ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki. // Attributes cannot be changed if CKA_MODIFIABLE is set to false - if (!isModifiable() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) { + if (!isModifiable() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_UNWRAP) { ERROR_MSG("An object is with CKA_MODIFIABLE set to false is not modifiable"); return CKR_ATTRIBUTE_READ_ONLY; } // Attributes cannot be modified if CKA_TRUSTED is true on a certificate object. - if (isTrusted() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) { + if (isTrusted() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_UNWRAP) { if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_CERTIFICATE) { ERROR_MSG("A trusted certificate cannot be modified"); diff --git a/src/lib/test/SymmetricAlgorithmTests.cpp b/src/lib/test/SymmetricAlgorithmTests.cpp index 3aeb1e7c2..82c56ff05 100644 --- a/src/lib/test/SymmetricAlgorithmTests.cpp +++ b/src/lib/test/SymmetricAlgorithmTests.cpp @@ -1186,6 +1186,107 @@ void SymmetricAlgorithmTests::aesWrapUnwrapGeneric(CK_MECHANISM_TYPE mechanismTy CPPUNIT_ASSERT(rv == CKR_OK); } +void SymmetricAlgorithmTests::aesWrapUnwrapNonModifiableGeneric(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) +{ + CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 }; + CK_BBOOL bFalse = CK_FALSE; + CK_BBOOL bTrue = CK_TRUE; + CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY; + CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET; + CK_BYTE keyPtr[128]; + CK_ULONG keyLen = + mechanismType == CKM_AES_KEY_WRAP_PAD ? 125UL : 128UL; + + 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_ATTRIBUTE attribs[] = { + { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }, + { CKA_CLASS, &secretClass, sizeof(secretClass) }, + { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) }, + { CKA_TOKEN, &bFalse, sizeof(bFalse) }, + { CKA_PRIVATE, &bTrue, sizeof(bTrue) }, + { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }, // Wrapping is allowed even on sensitive objects + { CKA_VALUE, keyPtr, keyLen } + }; + CK_OBJECT_HANDLE hSecret; + + rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, keyPtr, keyLen) ); + CPPUNIT_ASSERT(rv == CKR_OK); + + hSecret = CK_INVALID_HANDLE; + rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) ); + CPPUNIT_ASSERT(rv == CKR_OK); + CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE); + + CK_BYTE_PTR wrappedPtr = NULL_PTR; + CK_ULONG wrappedLen = 0UL; + CK_ULONG zero = 0UL; + CK_ULONG rndKeyLen = keyLen; + if (mechanismType == CKM_AES_KEY_WRAP_PAD) + rndKeyLen = (keyLen + 7) & ~7; + rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) ); + CPPUNIT_ASSERT(rv == CKR_KEY_UNEXTRACTABLE); + rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) ); + CPPUNIT_ASSERT(rv == CKR_OK); + + attribs[0].pValue = &bTrue; + + hSecret = CK_INVALID_HANDLE; + rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) ); + CPPUNIT_ASSERT(rv == CKR_OK); + CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE); + + // Estimate wrapped length + rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) ); + CPPUNIT_ASSERT(rv == CKR_OK); + + auto wrapOverhead = [mechanismType]() { + return (mechanismType == CKM_AES_KEY_WRAP || mechanismType == CKM_AES_KEY_WRAP_PAD) ? 8 : 16; + }; + CPPUNIT_ASSERT(wrappedLen == rndKeyLen + wrapOverhead() ); + + wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen); + CPPUNIT_ASSERT(wrappedPtr != NULL_PTR); + rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) ); + CPPUNIT_ASSERT(rv == CKR_OK); + CPPUNIT_ASSERT(wrappedLen == rndKeyLen + wrapOverhead() ); + + // This should always fail because wrapped data have to be longer than 0 bytes + zero = 0; + rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &zero) ); + CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL); + + CK_ATTRIBUTE nattribs[] = { + { CKA_CLASS, &secretClass, sizeof(secretClass) }, + { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) }, + { CKA_TOKEN, &bFalse, sizeof(bFalse) }, + { CKA_PRIVATE, &bTrue, sizeof(bTrue) }, + { CKA_ENCRYPT, &bFalse, sizeof(bFalse) }, + { CKA_DECRYPT, &bTrue, sizeof(bTrue) }, + { CKA_MODIFIABLE, &bFalse, sizeof(bFalse) }, + { CKA_SIGN, &bFalse,sizeof(bFalse) }, + { CKA_VERIFY, &bTrue, sizeof(bTrue) } + }; + CK_OBJECT_HANDLE hNew; + + hNew = CK_INVALID_HANDLE; + rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nattribs, sizeof(nattribs)/sizeof(CK_ATTRIBUTE), &hNew) ); + CPPUNIT_ASSERT(rv == CKR_OK); + CPPUNIT_ASSERT(hNew != CK_INVALID_HANDLE); + + free(wrappedPtr); + wrappedPtr = NULL_PTR; + rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) ); + CPPUNIT_ASSERT(rv == CKR_OK); +} + inline void SymmetricAlgorithmTests::aesWrapUnwrapRsa(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { wrapUnwrapRsa(mechanismType, hSession, hKey); diff --git a/src/lib/test/SymmetricAlgorithmTests.h b/src/lib/test/SymmetricAlgorithmTests.h index 094c1b07f..7d60fb576 100644 --- a/src/lib/test/SymmetricAlgorithmTests.h +++ b/src/lib/test/SymmetricAlgorithmTests.h @@ -88,6 +88,7 @@ class SymmetricAlgorithmTests : public TestsBase size_t messageSize, bool isSizeOK=true); void aesWrapUnwrapGeneric(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); + void aesWrapUnwrapNonModifiableGeneric(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); void aesWrapUnwrapRsa(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); void desWrapUnwrapRsa(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); CK_RV generateRsaPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);