我是PKCS#11库的开发人员。我认为函数C_DeriveKey应该失败,并显示错误代码
CKR_KEY_FUNCTION_NOT_PERMITTED
如果键具有CKA_DERIVE=0
。但是此错误代码未作为specification document中C_DeriveKey
的可能返回值列出。在这种情况下,C_DeriveKey
将返回正确的错误代码?
答案 0 :(得分:0)
我同意对这种情况的说明不是很清楚。该规范有一个更新的版本(2020年3月起为v3.0,link),但对此并没有带来更多的清晰度。我将考虑以下因素:
第5.1节中对返回值的介绍提供了以下免责声明(link):
由于Cryptoki规范的复杂性,建议Cryptoki应用程序在解释Cryptoki函数的返回值时尝试给予一些回旋余地。我们已经尝试尽可能完整地指定Cryptoki函数的行为。但是,可能存在一些差距。 例如,很可能不幸的是,可能不适用于特定Cryptoki功能的特定错误代码实际上并未在该功能的描述中列出来。
最后一部分直接承认,每个函数的可能返回值列表可能不完整。因此,如果函数有其他原因应返回此值,则C_DeriveKey
未将CKR_KEY_FUNCTION_NOT_PERMITTED
列为可能的返回代码可能没有权威性。
第5.1.6节给出了以下定义(link):
CKR_KEY_FUNCTION_NOT_PERMITTED:尝试将密钥用于加密目的,即密钥属性未设置为允许这样做。例如,要使用密钥执行加密,该密钥必须将其CKA_ENCRYPT属性设置为CK_TRUE(该密钥必须具有CKA_ENCRYPT属性这一事实意味着该密钥不能为私钥)。此返回值的优先级低于CKR_KEY_TYPE_INCONSISTENT。
CKR_KEY_TYPE_INCONSISTENT:指定的密钥不是用于指定机制的正确密钥类型。此返回值的优先级高于CKR_KEY_FUNCTION_NOT_PERMITTED。
根据这个定义,我可以得出结论:CKR_KEY_TYPE_INCONSISTENT
对于我们正在讨论的场景不是正确的返回码,因为它将机制与密钥的“类型”相关联。如果我们从CKA_KEY_TYPE
的意义上理解“类型”,则它与属性CKA_DERIVE
完全无关。
此外,在CKA_ENCRYPT
的定义中以属性CKR_KEY_FUNCTION_NOT_PERMITTED
为例。此属性与CKA_DERIVE
非常相似,即CKA_ENCRYPT
控制密钥是否可以用于加密,而CKA_DERIVE
控制密钥是否可以用于导出。因此,如果CKR_KEY_FUNCTION_NOT_PERMITTED
是未设置CKA_ENCRYPT
的情况下的正确返回码,则似乎也是合理的,它也是未设置CKA_DERIVE
的情况下的正确返回码。
我查看了一些PKCS#11库,以检查它们如何处理在将C_DeriveKey
设置为CKA_DERIVE
的键上调用CK_FALSE
的情况。我发现大多数实现都根本不实现C_DeriveKey
函数(即,它们总是返回CKR_FUNCTION_NOT_SUPPORTED
)。对于确实实现此功能的库,我观察到以下行为:
OpenSC返回CKR_KEY_TYPE_INCONSISTENT
(reference):
CK_ATTRIBUTE derive_attribute = { CKA_DERIVE, &can_derive, sizeof(can_derive) };
...
rv = object->ops->get_attribute(session, object, &derive_attribute);
if (rv != CKR_OK || !can_derive) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
我还检查了OpenSC如何处理类似于CKA_DERIVE
的其他属性。似乎C_EncryptInit
函数未在OpenSC中实现(大概是因为这是公钥操作?),但是C_DecryptInit
是未实现的。此函数实现对CKA_DECRYPT
(reference)的检查,但返回CKR_KEY_TYPE_INCONSISTENT
,这与CKR_KEY_FUNCTION_NOT_PERMITTED
规范中给出的示例相反。
SoftHSMv2返回CKR_KEY_FUNCTION_NOT_PERMITTED
(reference):
// Check if key can be used for derive
if (!key->getBooleanValue(CKA_DERIVE, false))
return CKR_KEY_FUNCTION_NOT_PERMITTED;
openCryptoki:我找不到CKA_DERIVE
的任何支票。他们会根据机制的功能标志检查CKF_DERIVE
并返回CKR_MECHANISM_INVALID
(如果未设置标志(reference),即机制是否不支持派生,但不返回。就像根据密钥的标志检查CKA_DERIVE
一样。
illumos-gate(IllumOS是已终止的OpenSolaris的分支)在其软键实现(reference)中也返回CKR_KEY_FUNCTION_NOT_PERMITTED
:
/* Check to see if key object allows for derivation. */
if (!(basekey_p->bool_attr_mask & DERIVE_BOOL_ON)) {
rv = CKR_KEY_FUNCTION_NOT_PERMITTED;
goto clean_exit1;
}
有趣的是,在旧版代码中,他们返回了CKR_KEY_TYPE_INCONSISTENT
,然后在this提交中将其更改为CKR_KEY_FUNCTION_NOT_PERMITTED
。提交消息的相关部分似乎是6177650 Wrong error code returned when key does not allow requested operation
。该ID指的是OpenSolaris Bug跟踪器中的票证,该票证不再在线。有一个错误跟踪程序here的存档,但不幸的是,它没有包含有关此故障单的任何信息。
在这些参考实现中,就使用范围而言,我认为OpenSC是最权威的。
基于上述考虑,我认为CKR_KEY_FUNCTION_NOT_PERMITTED
是适合我们正在讨论的场景的返回码。以下参数支持此功能:
该规范明确承认每个功能的可能返回代码列表可能不完整。因此,没有为CKR_KEY_FUNCTION_NOT_PERMITTED
列出C_DeriveKey
并不是有力的反驳。
该规范明确列出了CKA_ENCRYPT
,以作为CKR_KEY_FUNCTION_NOT_PERMITTED
是适当的返回码的示例。属性CKA_ENCRYPT
与CKA_DERIVE
类似,因此返回代码也适用于CKA_DERIVE
似乎是合理的。
CKR_KEY_TYPE_INCONSISTENT
的规范表明,它与机制和密钥类型之间的关系有关,而不与其他密钥属性有关。
在我们讨论的场景中,OpenSC使用CKR_KEY_TYPE_INCONSISTENT
,但是在未设置C_DecryptInit
的情况下,OpenSC还将返回代码用于CKA_DECRYPT
,这与示例相反在CKR_KEY_FUNCTION_NOT_PERMITTED
的规范中给出。
故意将OpenSolaris / IllumOS从CKR_KEY_TYPE_INCONSISTENT
切换到CKR_KEY_FUNCTION_NOT_PERMITTED
作为我们正在讨论的场景的返回代码。这表明他们还认为后者更适合返回代码。