使用Desfire本机包装的APDU与卡进行通信时,必须使用命令和响应的哪一部分来计算CMAC?

成功认证后,我具有以下 session 密钥:

Session Key: 7CCEBF73356F21C9191E87472F9D0EA2

然后,当我发送GetKeyVersion命令时,卡将返回以下我要验证的CMAC:
<< 90 64 00 00 01 00 00
>> 00 3376289145DA8C27 9100

我已经根据“NIST特殊出版物800-38B”实施了CMAC算法,并确保它是正确的。但是我不知道必须使用命令和响应APDU的哪些部分来计算CMAC。

我正在使用TDES,所以MAC为8字节。

最佳答案

最近几天,我一直在研究完全相同的问题,我想至少可以为您提供一些建议。使一切“如此”花费了一些时间,并且在某些情况下,很难理解NXP的文档(假设您可以访问)。

因此,您可能知道,您需要在发送和接收时计算CMAC(并更新init vec)。每次将其计算为下一个加密操作的初始化vec(CMAC或加密等)时,都需要保存CMAC。

计算示例的CMAC时,要馈入CMAC算法的数据是INS字节(0x64)和命令数据(0x00)。当然,这将由CMAC指定进行填充等。但是请注意,您不会在整个APDU包装(即90 64 00 00 01 00 00)中计算CMAC,而仅使用INS字节和数据有效负载。

接收时,您需要获取数据(0x00)和第二个状态字节(也为0x00),并根据该值计算CMAC。在此示例中这并不重要,但是顺序在这里很重要。您使用响应正文(不包括CMAC),然后使用SW2。

请注意,实际上仅发送了一半的CMAC-CMAC应该产生16个字节,而卡正在发送前8个字节。

还有其他一些因素阻止了我:

  • 我计算的 session 密钥不正确-如果事情没有如您所愿
  • 出现,则值得仔细检查
  • 我将文档解释为说整个APDU结构用于计算CMAC(很难以其他方式读取它们)

    我仍在正确计算“写入数据”命令的响应。命令成功,但是我无法验证CMAC。我确实知道写入数据不是用CMAC填充填充的,而只是用零填充的-尚不确定我还错过了什么。

    最后,这是一个通过我的日志与卡片进行通信的真实示例:
  • 身份验证已完成(AES),并且 session 密钥被确定为F92E48F9A6C34722A90EA29CFA0C3D12;初始vec为零
  • 我将发送“获取密钥版本”命令(如您的示例所示),以便我通过6400计算CMAC并获取1200551CA7E2F49514A1324B7E3428F1(现在是我的下一次计算的初始化vec)
  • 90640000010000发送到卡并接收00C929939C467434A8(状态为9100)。
  • 通过00 00计算CMAC并获取C929939C467434A8A29AB2C40B977B83(并更新init vec以进行下一次计算)
  • 步骤4中CMAC的前半部分与步骤3中从卡收到的8个字节匹配
  • 09-11 20:03