Skip to content

Commit

Permalink
Fixed issue #707 by allowing operation OBJECT_OP_UNWRAP to modify att…
Browse files Browse the repository at this point in the history
…ributes when CKA_MODIFIABLE is true
  • Loading branch information
Antoine Lochet authored and Antoine Lochet committed Feb 6, 2025
1 parent 557b2fd commit 9e67f7e
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/lib/P11Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
101 changes: 101 additions & 0 deletions src/lib/test/SymmetricAlgorithmTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/lib/test/SymmetricAlgorithmTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9e67f7e

Please sign in to comment.