我的问题是,是否可以从applet本身的代码中锁定applet作为从代码中检测到的操作的对策。
显而易见的选择是使用……
GP核心规范本身不符合要求。产品符合GP标准GP 组态 。 GP配置不是免费的。 JCOP 2.4.x产品符合GP 2.2.x'现有GP 2.1.1映射指南v2.2.1'配置。顾名思义,此配置用于向后兼容性映射。基本上JCOP 2.4.x产品仅适用于GP 2.1.1产品(具有GP 2.2.x中的一些功能)。全局锁定权限对于applet是可选的。
是。这是GlobalPlatform应用程序的常见操作。您必须使用正确的权限(gp -install -privs CardLock)安装您的应用程序,并且执行此操作的代码是:
GPSystem.setCardContentState(GPSystem.APPLICATION_LOCKED);
您可以稍后解锁该应用程序
gp -unlock-applet <aid>
有趣的是,看看这种机制是如何从GlobalPlatform Card规范2.1.1演变为2.2.1(在2.3中仍然相同):
在GP 2.1.1中,只允许卡发行者(卡外实体)或OPEN(由于“例外”)启动应用程序的锁定:
发卡机构具有禁用卡上应用程序的持续执行状态的机制。可以基于OPEN处理的异常或使用外部调用的命令从OPEN内调用此机制。发卡机构是唯一可以启动应用程序锁定的实体。
方法 GPSystem.setCardContentState() 明确定义为只允许状态更改为特定于应用程序的生命周期状态(值之间的值) 0x07 和 0x7F 设置最低3位)。自从常数为 APPLICATION_LOCKED 在以后的规范中是 0x80 不允许设置此状态。在此方法的注释中也清楚地表明了这一点:
GPSystem.setCardContentState()
0x07
0x7F
APPLICATION_LOCKED
0x80
OPEN将拒绝任何转换请求 的 至 强> 生命周期国家安装或 的 已锁定 强> 。
因此,尝试将应用程序状态设置为从应用程序本身内锁定必须在实现GP 2.1.1的卡上失败。
的 更新(2016-05-20): 强> 我在一些NXP JCOP卡(声称符合GP 2.1.1)上测试了这一点,并且设置高位设置值或任何低3位清除的值确实失败了。
这在GP 2.2中有所改变。现在,允许应用程序锁定自己:
该卡具有禁用并随后重新启用卡上的继续执行状态的机制 应用。可以基于OPEN或者处理的异常从OPEN内调用该机制 从使用外部调用的命令。具有全局锁定权限的应用程序, 的 应用程序本身 强> 要么 直接或间接关联的安全域是唯一可以启动锁定的实体 应用。
GP卡规范不要求应用程序保留任何锁定自身的特定权限。
不幸的是,该方法的API规范 GPSystem.setCardContentState() 还不太清楚。首先,该方法的描述仍然表明只有值之间 0x07 和 0x7F 必须允许设置最低3位:
此方法设置当前applet上下文的特定于应用程序的生命周期状态。只要设置了3个低位,应用程序特定的生命周期状态范围为0x07至0x7F。
其次,API文档中有偏离的注释,它们是GP卡规范2.2文档的附录A和API导出文件中的JavaDoc的一部分。虽然规范中的注释改为:
OPEN应拒绝任何转入生命周期状态的转换请求; OPEN将拒绝任何转换请求 的 从 强> 生命周期国家 的 已锁定 强> ;
API导出文件(GPSystem.java和JavaDoc)中的注释与GP 2.1.1中的注释相同。
因此,如果根据规范实现此方法,它仍应拒绝将应用程序生命周期状态设置为 APPLICATION_LOCKED 。
的 更新(2016-05-20): 强> 我在NXP J3D081(JCOP v2.4.2 R2)卡上进行了测试(即声称遵守GP 2.2)。遗憾的是,设置高位设置或任何低3位清除的值都会失败。
但是,也有方法 GPRegistryEntry.setState() 。该方法的文档说明:
GPRegistryEntry.setState()
只有在调用Application对应于此GPRegistryEntry时,才接受除APPLICATION_LOCKED和APPLICATION_UNLOCKED之外的生命周期状态的转换请求。 的 应用程序应能够锁定并且不能自行解锁; 强>
因此,看看以下是否在使用相同的卡上工作将是有趣的 setCardContentState() 失败:
setCardContentState()
GPSystem.getRegistryEntry(null).setState(GPSystem.APPLICATION_LOCKED);
的 更新(2016-05-20): 强> 我在NXP J3D081(JCOP v2.4.2 R2)卡(声称符合GP 2.2)上进行了测试。不幸的是,这也失败了。顺便说一句。如果这似乎没有什么区别 null 要么 JCSystem.getAID() 用作参数 getRegistryEntry() 。
null
JCSystem.getAID()
getRegistryEntry()
的 更新(2016-06-14): 强> 根据 保罗巴斯蒂安 ,恩智浦代表已确认应用程序无法在JCOP v2.4.x卡上设置自己的锁定状态。
的 更新(2016-06-06): 强> 我在英飞凌SLE97CNFX卡(声称符合GP 2.2.1)上进行了测试,但它确实有效。我可以通过使用成功将状态设置为锁定 APPLICATION_LOCKED (0x80的)。然后将状态设置为 previous_state | 0x80 。尝试设置具有高位设置的其他状态值(例如0x8F)不起作用(正如我预期的那样)。
previous_state | 0x80
在GP 2.2.1中,该方法的文档 GPSystem.setCardContentState() 被改变了(再次)。更改说明清楚地表明该方法已更新为现在允许应用程序自行锁定(导出文件版本1.5。映射到GP 2.2.1):
导出文件版本1.5:此方法现在允许与当前applet上下文关联的应用程序自行锁定。
方法定义已更改为:
此方法允许与当前applet上下文关联的应用程序将其状态更改为特定于应用程序的生命周期状态 的 或锁定自己 强> 。应用程序无法使用此方法解锁自身。
传递给方法的state参数的值范围现在显式包含值 APPLICATION_LOCKED :
bState - 特定于应用程序的生命周期状态(0x07至0x7F,设置3个低位),或 APPLICATION_LOCKED (0x80的)。
bState
因此,实现GP 2.2.1或更高版本的卡最终应允许应用程序使用该方法将其自身的生命周期状态更改为锁定 GPSystem.setCardContentState() 。
的 更新(2016-06-06): 强> 我在英飞凌SLE97CNFX卡(声称符合GP 2.2.1(或2.3?))上进行了测试,但它确实有效。我可以通过使用成功将状态设置为锁定 APPLICATION_LOCKED (0x80的)。然后将状态设置为 previous_state | 0x80 。尝试设置具有高位设置的其他状态值(例如0x8F)不起作用(正如我预期的那样)。
如果不能将应用程序生命周期设置为状态,您可以采取哪些措施来克服问题 APPLICATION_LOCKED ,是使用特定于应用程序的生命周期状态:
public class LockableApplet extends Applet { [... applet installation / instantiation code ...] private static final byte APPLICATION_STATE_UNLOCKED = (byte)0x07; private static final byte APPLICATION_STATE_LOCKED = (byte)0x7F; public boolean select() { if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) { return false; } return true; } public void process(APDU apdu) { if (selectingApplet()) { return; } if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) { ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); } [... applet logic code ...] } }
检测到一个应该导致应用程序被锁定的问题,您可以使用以下调用锁定applet:
GPSystem.setCardContentState(APPLICATION_STATE_LOCKED);
您可以稍后通过安全域使用SET STATUS命令再次解锁应用程序。
是的,很简单:使用a private static boolean 标志并在开头检查它 process(APDU apdu) 方法:
private static boolean
process(APDU apdu)
public class MiniApplet extends Applet { public static void install(byte[] bArray, short bOffset, byte bLength) { new MiniApplet(); } protected MiniApplet() { register(); } private static final short SW_APPLET_IS_LOCKED = (short) 0x9199; //any error SW private static boolean appletLocked = false; //static -> faster access, this flag is checked each call! "private" modifier is VERY important! public void process(APDU apdu) { if (selectingApplet()) { return; //it is a good practice not to throw any exceptions on SELECT command } if (appletLocked) { ISOException.throwIt(SW_APPLET_IS_LOCKED); } if (attackDetected()) { //implement your attack detection appletLocked = true; } } }