如果派生密钥的CKA_DERIVE = 0

时间:2019-08-29 07:29:49

标签: pkcs#11

我是PKCS#11库的开发人员。我认为函数C_DeriveKey应该失败,并显示错误代码

  

CKR_KEY_FUNCTION_NOT_PERMITTED

如果键具有CKA_DERIVE=0。但是此错误代码未作为specification documentC_DeriveKey的可能返回值列出。在这种情况下,C_DeriveKey将返回正确的错误代码?

1 个答案:

答案 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_INCONSISTENTreference):

      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_DECRYPTreference)的检查,但返回CKR_KEY_TYPE_INCONSISTENT,这与CKR_KEY_FUNCTION_NOT_PERMITTED规范中给出的示例相反。

  • SoftHSMv2返回CKR_KEY_FUNCTION_NOT_PERMITTEDreference):

      // 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_ENCRYPTCKA_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作为我们正在讨论的场景的返回代码。这表明他们还认为后者更适合返回代码。