Skip to content

Commit 426f30c

Browse files
authored
Merge pull request #165 from miyazakh/f-311
f-311:C_WrapKey does not check `CKA_EXTRACTABLE` on the key being wrapped
2 parents 8194c25 + 2879d60 commit 426f30c

3 files changed

Lines changed: 170 additions & 8 deletions

File tree

src/crypto.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6838,7 +6838,15 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
68386838
* @return CKR_CRYPTOKI_NOT_INITIALIZED when library not initialized.
68396839
* CKR_SESSION_HANDLE_INVALID when session handle is not valid.
68406840
* CKR_ARGUMENTS_BAD when pMechanism or pulWrappedKeyLen is NULL.
6841-
* CKR_OBJECT_HANDLE_INVALID when a key object handle is not valid.
6841+
* CKR_OBJECT_HANDLE_INVALID when hKey object handle is not valid.
6842+
* CKR_WRAPPING_KEY_HANDLE_INVALID when hWrappingKey handle is not
6843+
* valid.
6844+
* CKR_KEY_UNEXTRACTABLE when hKey has CKA_EXTRACTABLE set to
6845+
* CK_FALSE.
6846+
* CKR_KEY_NOT_WRAPPABLE when hKey has CKA_WRAP_WITH_TRUSTED set to
6847+
* CK_TRUE but hWrappingKey does not have CKA_TRUSTED set to CK_TRUE,
6848+
* or when the key class/type combination is not supported for
6849+
* wrapping.
68426850
* CKR_MECHANISM_INVALID when the mechanism is not supported with this
68436851
* type of operation.
68446852
*/
@@ -6858,6 +6866,8 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession,
68586866
CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
68596867
word32 serialSize = 0;
68606868
byte* serialBuff = NULL;
6869+
CK_BBOOL getVar;
6870+
CK_ULONG getVarLen = sizeof(CK_BBOOL);
68616871

68626872
WOLFPKCS11_ENTER("C_WrapKey");
68636873
#ifdef DEBUG_WOLFPKCS11
@@ -6889,6 +6899,14 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession,
68896899
if (ret != 0)
68906900
return CKR_OBJECT_HANDLE_INVALID;
68916901

6902+
ret = WP11_Object_GetAttr(key, CKA_EXTRACTABLE, &getVar, &getVarLen);
6903+
if (ret != 0) {
6904+
return CKR_KEY_NOT_WRAPPABLE;
6905+
}
6906+
if (getVar == CK_FALSE) {
6907+
return CKR_KEY_UNEXTRACTABLE;
6908+
}
6909+
68926910
ret = WP11_Object_Find(session, hWrappingKey, &wrappingKey);
68936911
if (ret != 0)
68946912
return CKR_WRAPPING_KEY_HANDLE_INVALID;
@@ -6897,6 +6915,20 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession,
68976915
if (ret != CKR_OK)
68986916
return ret;
68996917

6918+
/* key can only be wrapped by a trusted wrapping key */
6919+
getVarLen = sizeof(CK_BBOOL);
6920+
ret = WP11_Object_GetAttr(key, CKA_WRAP_WITH_TRUSTED,
6921+
&getVar, &getVarLen);
6922+
if (ret == CKR_OK && getVar == CK_TRUE) {
6923+
CK_BBOOL trustedVar = CK_FALSE;
6924+
CK_ULONG trustedVarLen = sizeof(CK_BBOOL);
6925+
ret = WP11_Object_GetAttr(wrappingKey, CKA_TRUSTED,
6926+
&trustedVar, &trustedVarLen);
6927+
if (ret != CKR_OK || trustedVar != CK_TRUE) {
6928+
return CKR_KEY_NOT_WRAPPABLE;
6929+
}
6930+
}
6931+
69006932
wrapkeyType = WP11_Object_GetType(wrappingKey);
69016933

69026934
keyType = WP11_Object_GetType(key);

tests/pkcs11mtt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1821,7 +1821,7 @@ static CK_RV test_wrap_unwrap_key(void* args)
18211821
ret = get_generic_key(session, wrappingKeyData, sizeof(wrappingKeyData),
18221822
CK_FALSE, &wrappingKey);
18231823
if (ret == CKR_OK) {
1824-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
1824+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
18251825
&key);
18261826
}
18271827
if (ret == CKR_OK) {

tests/pkcs11test.c

Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5760,7 +5760,7 @@ static CK_RV test_aes_wrap_unwrap_key(void* args)
57605760

57615761
ret = get_aes_128_key(session, NULL, 0, &wrappingKey);
57625762
if (ret == CKR_OK) {
5763-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
5763+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
57645764
&key);
57655765
}
57665766
if (ret == CKR_OK) {
@@ -5804,7 +5804,7 @@ static CK_RV test_aes_wrap_unwrap_pad_key(void* args)
58045804

58055805
ret = get_aes_128_key(session, NULL, 0, &wrappingKey);
58065806
if (ret == CKR_OK) {
5807-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
5807+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
58085808
&key);
58095809
}
58105810
if (ret == CKR_OK) {
@@ -5854,7 +5854,7 @@ static CK_RV test_wrap_unwrap_key(void* args)
58545854
ret = get_generic_key(session, wrappingKeyData, sizeof(wrappingKeyData),
58555855
CK_FALSE, &wrappingKey);
58565856
if (ret == CKR_OK) {
5857-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
5857+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
58585858
&key);
58595859
}
58605860
if (ret == CKR_OK) {
@@ -5952,6 +5952,134 @@ static CK_RV test_wrap_unwrap_key(void* args)
59525952

59535953
return ret;
59545954
}
5955+
5956+
/* Regression test: C_WrapKey on a key with CKA_EXTRACTABLE=CK_FALSE must
5957+
* return CKR_KEY_UNEXTRACTABLE (PKCS#11 spec 2.1.4). */
5958+
static CK_RV test_wrap_key_unextractable(void* args)
5959+
{
5960+
CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args;
5961+
CK_RV ret;
5962+
CK_MECHANISM mech = { CKM_AES_KEY_WRAP, NULL, 0 };
5963+
CK_OBJECT_HANDLE wrappingKey = CK_INVALID_HANDLE;
5964+
CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
5965+
byte wrappedKey[40], keyData[16];
5966+
CK_ULONG wrappedKeyLen = sizeof(wrappedKey);
5967+
//CK_BBOOL ckfalse = CK_FALSE;
5968+
CK_ATTRIBUTE wrapKeyTmpl[] = {
5969+
{ CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) },
5970+
{ CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType) },
5971+
{ CKA_VALUE, aes_128_key, sizeof(aes_128_key) },
5972+
{ CKA_WRAP, &ckTrue, sizeof(ckTrue) },
5973+
};
5974+
CK_ULONG wrapKeyTmplCnt = sizeof(wrapKeyTmpl) / sizeof(*wrapKeyTmpl);
5975+
CK_ATTRIBUTE nonExtractTmpl[] = {
5976+
{ CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) },
5977+
{ CKA_KEY_TYPE, &genericKeyType, sizeof(genericKeyType) },
5978+
{ CKA_VALUE, keyData, sizeof(keyData) },
5979+
{ CKA_EXTRACTABLE, &ckFalse, sizeof(CK_BBOOL) },
5980+
};
5981+
CK_ULONG nonExtractTmplCnt = sizeof(nonExtractTmpl) /
5982+
sizeof(*nonExtractTmpl);
5983+
5984+
memset(keyData, 0x42, sizeof(keyData));
5985+
5986+
ret = funcList->C_CreateObject(session, wrapKeyTmpl, wrapKeyTmplCnt,
5987+
&wrappingKey);
5988+
CHECK_CKR(ret, "Create AES wrapping key for unextractable test");
5989+
if (ret == CKR_OK) {
5990+
ret = funcList->C_CreateObject(session, nonExtractTmpl,
5991+
nonExtractTmplCnt, &key);
5992+
CHECK_CKR(ret, "Create non-extractable key");
5993+
}
5994+
if (ret == CKR_OK) {
5995+
ret = funcList->C_WrapKey(session, &mech, wrappingKey, key,
5996+
wrappedKey, &wrappedKeyLen);
5997+
CHECK_CKR_FAIL(ret, CKR_KEY_UNEXTRACTABLE,
5998+
"Wrap non-extractable key must return CKR_KEY_UNEXTRACTABLE");
5999+
}
6000+
6001+
funcList->C_DestroyObject(session, wrappingKey);
6002+
funcList->C_DestroyObject(session, key);
6003+
6004+
return ret;
6005+
}
6006+
6007+
/* Regression test: C_WrapKey on a key with CKA_WRAP_WITH_TRUSTED=CK_TRUE must
6008+
* return CKR_KEY_NOT_WRAPPABLE when the wrapping key lacks CKA_TRUSTED, and
6009+
* succeed when the wrapping key has CKA_TRUSTED=CK_TRUE. */
6010+
static CK_RV test_wrap_key_wrap_with_trusted(void* args)
6011+
{
6012+
CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args;
6013+
CK_RV ret;
6014+
CK_MECHANISM mech = { CKM_AES_KEY_WRAP, NULL, 0 };
6015+
CK_OBJECT_HANDLE untrustedKey = CK_INVALID_HANDLE;
6016+
CK_OBJECT_HANDLE trustedKey = CK_INVALID_HANDLE;
6017+
CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
6018+
byte wrappedKey[40], keyData[16];
6019+
CK_ULONG wrappedKeyLen;
6020+
CK_BBOOL ckTrusted = CK_TRUE;
6021+
CK_ATTRIBUTE untrustedWrapTmpl[] = {
6022+
{ CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) },
6023+
{ CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType) },
6024+
{ CKA_VALUE, aes_128_key, sizeof(aes_128_key) },
6025+
{ CKA_WRAP, &ckTrue, sizeof(ckTrue) },
6026+
};
6027+
CK_ULONG untrustedWrapTmplCnt = sizeof(untrustedWrapTmpl) /
6028+
sizeof(*untrustedWrapTmpl);
6029+
CK_ATTRIBUTE trustedWrapTmpl[] = {
6030+
{ CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) },
6031+
{ CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType) },
6032+
{ CKA_VALUE, aes_128_key, sizeof(aes_128_key) },
6033+
{ CKA_WRAP, &ckTrue, sizeof(ckTrue) },
6034+
{ CKA_TRUSTED, &ckTrusted, sizeof(CK_BBOOL) },
6035+
};
6036+
CK_ULONG trustedWrapTmplCnt = sizeof(trustedWrapTmpl) /
6037+
sizeof(*trustedWrapTmpl);
6038+
CK_ATTRIBUTE wwtTmpl[] = {
6039+
{ CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) },
6040+
{ CKA_KEY_TYPE, &genericKeyType, sizeof(genericKeyType) },
6041+
{ CKA_VALUE, keyData, sizeof(keyData) },
6042+
{ CKA_EXTRACTABLE, &ckTrue, sizeof(ckTrue) },
6043+
{ CKA_WRAP_WITH_TRUSTED, &ckTrusted, sizeof(CK_BBOOL) },
6044+
};
6045+
CK_ULONG wwtTmplCnt = sizeof(wwtTmpl) / sizeof(*wwtTmpl);
6046+
6047+
memset(keyData, 0x55, sizeof(keyData));
6048+
6049+
ret = funcList->C_CreateObject(session, untrustedWrapTmpl,
6050+
untrustedWrapTmplCnt, &untrustedKey);
6051+
CHECK_CKR(ret, "Create untrusted AES wrapping key");
6052+
if (ret == CKR_OK) {
6053+
ret = funcList->C_CreateObject(session, trustedWrapTmpl,
6054+
trustedWrapTmplCnt, &trustedKey);
6055+
CHECK_CKR(ret, "Create trusted AES wrapping key");
6056+
}
6057+
if (ret == CKR_OK) {
6058+
ret = funcList->C_CreateObject(session, wwtTmpl, wwtTmplCnt, &key);
6059+
CHECK_CKR(ret, "Create CKA_WRAP_WITH_TRUSTED key");
6060+
}
6061+
/* Wrap with untrusted key must fail */
6062+
if (ret == CKR_OK) {
6063+
wrappedKeyLen = sizeof(wrappedKey);
6064+
ret = funcList->C_WrapKey(session, &mech, untrustedKey, key,
6065+
wrappedKey, &wrappedKeyLen);
6066+
CHECK_CKR_FAIL(ret, CKR_KEY_NOT_WRAPPABLE,
6067+
"Wrap CKA_WRAP_WITH_TRUSTED key with untrusted wrapping key");
6068+
}
6069+
/* Wrap with trusted key must succeed */
6070+
if (ret == CKR_OK) {
6071+
wrappedKeyLen = sizeof(wrappedKey);
6072+
ret = funcList->C_WrapKey(session, &mech, trustedKey, key,
6073+
wrappedKey, &wrappedKeyLen);
6074+
CHECK_CKR(ret, "Wrap CKA_WRAP_WITH_TRUSTED key with trusted wrapping key");
6075+
}
6076+
6077+
funcList->C_DestroyObject(session, untrustedKey);
6078+
funcList->C_DestroyObject(session, trustedKey);
6079+
funcList->C_DestroyObject(session, key);
6080+
6081+
return ret;
6082+
}
59556083
#endif /* HAVE_AES_KEYWRAP && !WOLFPKCS11_NO_STORE */
59566084

59576085
#ifndef NO_DH
@@ -6339,7 +6467,7 @@ static CK_RV test_rsa_wrap_unwrap_key(void* args)
63396467

63406468
/* Create a secret key to wrap */
63416469
if (ret == CKR_OK) {
6342-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
6470+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
63436471
&key);
63446472
}
63456473

@@ -6364,7 +6492,7 @@ static CK_RV test_rsa_wrap_unwrap_key(void* args)
63646492

63656493
/* Test getting wrapped key length */
63666494
if (ret == CKR_OK) {
6367-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
6495+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
63686496
&key);
63696497
if (ret == CKR_OK) {
63706498
CK_ULONG testLen = 0;
@@ -6409,7 +6537,7 @@ static CK_RV test_rsa_wrap_unwrap_key(void* args)
64096537
/* Test buffer too small error */
64106538
if (ret == CKR_OK) {
64116539
/* Create fresh key for this test since original was destroyed */
6412-
ret = get_generic_key(session, keyData, sizeof(keyData), CK_FALSE,
6540+
ret = get_generic_key(session, keyData, sizeof(keyData), CK_TRUE,
64136541
&key);
64146542
if (ret == CKR_OK) {
64156543
CK_ULONG smallLen = 1;
@@ -15994,6 +16122,8 @@ static TEST_FUNC testFunc[] = {
1599416122
PKCS11TEST_FUNC_SESS_DECL(test_aes_wrap_unwrap_key),
1599516123
PKCS11TEST_FUNC_SESS_DECL(test_aes_wrap_unwrap_pad_key),
1599616124
PKCS11TEST_FUNC_SESS_DECL(test_wrap_unwrap_key),
16125+
PKCS11TEST_FUNC_SESS_DECL(test_wrap_key_unextractable),
16126+
PKCS11TEST_FUNC_SESS_DECL(test_wrap_key_wrap_with_trusted),
1599716127
#endif /* HAVE_AES_KEYWRAP && !WOLFPKCS11_NO_STORE */
1599816128
#if (!defined(NO_RSA) && !defined(WOLFPKCS11_NO_STORE))
1599916129
PKCS11TEST_FUNC_SESS_DECL(test_rsa_wrap_unwrap_key),

0 commit comments

Comments
 (0)