使 JavaCard 小程序可更新的正确方法是啥?

Posted

技术标签:

【中文标题】使 JavaCard 小程序可更新的正确方法是啥?【英文标题】:What is the correct approach to make a JavaCard applet updatable?使 JavaCard 小程序可更新的正确方法是什么? 【发布时间】:2021-06-22 17:10:24 【问题描述】:

我希望能够在分发给客户后更新 Applet。 如果我们需要更新小程序,我不想让他们把芯片寄回给我。 我想给一个脚本在他们的读卡器中运行。

问题是为了更新小程序,我需要给他们一个带有解锁密钥的脚本,但我不想给他们密钥。

有什么方法可以签署一个新的小程序,JavaCard (GlobalPlatform) 会知道它是一个原始的小程序,然后才会安装它?

我想也许可以创建具有安装权限的新小程序(有类似的东西吗?),它将负责安装新的小程序。

【问题讨论】:

【参考方案1】:

您有多种选择:

    如果您的卡片支持SCP11c,您可以创建卡片外脚本。这样您就可以将安装脚本发送给您的客户端。但是我没有听说过支持这种模式的卡,但我也没有搜索过。

      您使用经典的 SCP02/SCP03 为您的小程序创建一个专用的安全域。您仍然必须提供该域的密钥,但您的客户端至少不能再与其他安全域中的其他数据交互。如果该卡仅适用于一个租户,您仍然可以使用发行者安全域。卡必须支持这个,可能不支持。 为防止您的客户端安装任意内容,您可以使用 DAP 验证。安全域必须具有此特权并且必须为其配备密钥。 DAP 验证将签名附加到您的小程序数据,该数据由安全域检查。必须匹配,否则无法安装小程序。卡必须支持这个,也许不支持。您也可以将“安装令牌”用于类似目的,同时检查所有安装参数。 为防止您的代码被检查 - 它是字节代码,尽管难以阅读,但仍可能显示您正在做的事情 - 您可以加密小程序代码。加密加载文件块是规范中要在此处查找的术语,您必须再次将此权限授予安全域。

    设置支持远程内容管理的服务器。您必须为您的客户端提供代理实现,以代理读卡器和服务器之间的 APDU 数据。 GP RAM specification 描述了这样一个系统,但您也可以使用自己的(更简单的)实现。您的服务器必须组装所有 APDU 命令,将其发送到代理,代理将提供 APDU 响应。您可以在后台使用 PC/SC 和 a remote smart card 的标准工具。例如。我写了GPShell,也许可以和它一起使用。但是,您也可以将其实现为真正的服务器,而不是一起编写脚本工具,例如使用custom connection plugin 和GlobalPlatform。如果您在 Java 环境中开发,还有一些可用的 java 库可能更方便。这种方法是最灵活的一种,它还为您的客户提供了一种方便的方式来获得更新通知。

查看GP 2.3.1 以获取有关我给出的提示的更多信息。这完全取决于您的卡支持什么,以及您是否可以找到一些也支持此功能的工具和库。

【讨论】:

谢谢听起来很有趣。关于 2.3,我在规范中查找了 Ciphered load file 块,但没有找到。我不明白如何在安全域中加密字节码和解密。由于您不能仅从 CAP 文件从 byte[] 安装或在 APDU 中发送字节码。不?关于2.2,使用gp.jar安装时没有找到DAP参数,请问设置DAP密钥和以后安装的选项是什么? 关于加密加载文件块查看“C.1.3 加载文件数据块解密密钥”。基本上,它是一个额外的 DES/AES 密钥,必须存储在卡上,并由场外实体用于加密文件,并在卡上使用相同的密钥进行解密。我不知道有任何卡支持它,也没有操作系统工具支持它。 DAP 验证也不是标准功能。 gp.jar 可能不支持。同样,我不知道有任何操作系统工具支持它。选项3是我认为您最好的选择,其他一切都缺乏支持。它也是一个键,例如一个用于签署小程序的 RSA 密钥已加载。 我参与了选项 3 的解决方案的构建,并且效果很好,我们甚至将其与单独的安全域相结合,因此这是一条有效的路径。组织上的挑战是分发代理程序 @PaulBastian 只是为了确保我理解正确。在我们使用 APDU 命令安装新的小程序时,我们只使用代理在卡和服务器之间创建安全通道?【参考方案2】:

(扩展answer given by k_o_)

    使用具有伪随机挑战的安全通道协议,引用 GP 2.2。修改 D

安全通道用于在发行时和发行后个性化卡。的模式 使用伪随机卡挑战的安全通道协议允许离线准备 卡不存在时的个性化脚本以及在卡上处理这些脚本而不 与准备脚本的实体建立在线连接。

我知道的选项是:

带有“i”参数的SCP02设置了“b7”(通常是“i=55”)——参见例如GP 卡规范 2.3.1,E1.1 和 E.4.2.3 部分

带有“i”参数且设置了“b5”的SCP03——参见例如GP 卡规范 2.2 修订版 D,第 4.1.5、6.2.2.1 节

您需要为所有已部署的卡存储额外信息(至少是计数器值)。

(如果我没记错的话)您需要为每张已部署的卡生成唯一的脚本(假设使用了不同的卡密钥)。

请注意,可能会发生一些讨厌的 MITM 攻击(例如,过早终止个性化脚本)。

(我有一个 SCP02 i=55 的概念验证实现,效果很好)


    如果您的更新只会更改小程序逻辑的一小部分(并且您提前知道哪些部分),那么您可以:

通过远程更改配置使这些部分可配置并执行更新

实现执行这些部分的虚拟机并远程更新其字节码

(我在 Java Card 小程序中实现了一个简单的虚拟机,性能足以完成简单的加密任务)


一些补充说明:

使用 APDU 代理(k_o_ 答案中的选项 3)- 使用具有完整性和机密性的安全通道(如果可能,包括 R-MAC)- 在没有应用适当保护的情况下可能会发生令人讨厌的 MITM 攻击(假设更新发生在不安全的环境中)环境)

如果您的小程序实例包含任何需要在更新中保留的状态信息(数据),它会变得更加复杂

【讨论】:

我还考虑过添加带有伪随机挑战的解决方案 4,但知道计数器和可能的不同步问题应该是个问题。任何如何使计数器保持同步的想法,如果它们已经漂移,例如通过在读卡器中本地使用它们,然后再次使用 OTA? @k_o_ 因为计数器增量需要成功的身份验证,所以它不应该不受控制地漂移(通常你不想混合几种“更新”方法)。当然,您需要一些方法来检查更新脚本的成功/失败(我为每个单个 APDU 使用了一个正则表达式,它必须匹配来自 base16 卡的响应(在 99% 的情况下它是“.*9000$”) . 当卡响应不匹配并且完整的更新跟踪被发送到服务器时,脚本因失败而中止(如果卡响应不敏感,您可能希望在所有情况下都这样做)... ...如果我没记错的话,计数器值可以通过GET DATA 检索,因此您可以在在线检查更新时将其报告给服务器。 @k_o_ 更新:计数器值可通过GET_DATA 作为标签'C1'(默认密钥版本号的序列计数器)获得 我知道标签 C1,但不幸的是我至少有一张卡片没有报告它。

以上是关于使 JavaCard 小程序可更新的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

安装后将 Javacard 小程序标记为隐式可选(默认小程序)

主机应用程序如何在 Netbeans 中的模拟智能卡上查询 javacard 小程序?

呈现和关闭模式小部件流的正确方法是啥?

访问可以更新的罐装应用资源的正确方法是啥?

更新通过通知点击带到前台的当前活动的正确方法是啥?

如何从 Javacard 制作 EMV 卡?