首页 > 解决方案 > 如果派生密钥 CKA_DERIVE=0,C_DeriveKey 的正确错误代码是什么

问题描述

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

CKR_KEY_FUNCTION_NOT_PERMITTED

如果键有。但是此错误代码未在规范文档CKA_DERIVE=0中列为可能的返回值。在这种情况下要返回的正确错误代码是什么?C_DeriveKeyC_DeriveKey

标签: pkcs#11

解决方案


我同意这个案例的规范不是很清楚。有一个更新版本的规范可用(2020 年 3 月的 v3.0,链接),但它并没有带来更多的清晰度。我会考虑以下几点:

返回值的一般说明

5.1 节中关于返回值的介绍给出了以下免责声明(链接):

由于 Cryptoki 规范的复杂性,建议 Cryptoki 应用程序在解释 Cryptoki 函数的返回值时尝试给一些余地。我们试图尽可能完整地指定 Cryptoki 函数的行为;尽管如此,大概还是有一些差距。 例如,很遗憾,可能适用于特定 Cryptoki 函数的特定错误代码实际上并未作为可能的错误代码列在该函数的描述中。

最后一部分直接承认每个函数的可能返回值列表可能不完整。因此,如果函数应返回此值的原因还有其他原因,则未将其列为可能的返回代码可能不具有权威性C_DeriveKeyCKR_KEY_FUNCTION_NOT_PERMITTED

返回码的定义

第 5.1.6 节给出了以下定义(链接):

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的键上调用的情况。我发现的大多数实现根本没有实现该功能(即它们总是 return )。对于实现此功能的库,我观察到以下行为:CKA_DERIVECK_FALSEC_DeriveKeyCKR_FUNCTION_NOT_SUPPORTED

  • OpenSC返回CKR_KEY_TYPE_INCONSISTENT参考):

      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参考):

      // 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如果没有设置标志(参考),即如果机制不支持派生,则返回,但这与检查CKA_DERIVE密钥的标志不同。

  • illumos-gate(IllumOS 是已停产的 OpenSolaris 的一个分支)也在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改为返回,然后CKR_KEY_FUNCTION_NOT_PERMITTED提交中将其更改为。提交消息的相关部分似乎是6177650 Wrong error code returned when key does not allow requested operation. 该 ID 指的是 OpenSolaris 错误跟踪器中的票证,该票证已不再在线。这里有一个错误跟踪器的存档,但不幸的是,它不包含有关此票证的任何信息。

在这些参考实现中,就其使用范围而言,我认为 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_DecryptInitCKA_DECRYPTCKR_KEY_FUNCTION_NOT_PERMITTED

  • OpenSolaris/IllumOS 故意从 切换CKR_KEY_TYPE_INCONSISTENTCKR_KEY_FUNCTION_NOT_PERMITTED作为我们正在讨论的场景的返回码。这表明他们还认为后者是更合适的返回代码。


推荐阅读