Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SmartCard-显式初始化SCP02通道 #31

Open
chenpengcong opened this issue Jun 6, 2020 · 1 comment
Open

SmartCard-显式初始化SCP02通道 #31

chenpengcong opened this issue Jun 6, 2020 · 1 comment

Comments

@chenpengcong
Copy link
Owner

chenpengcong commented Jun 6, 2020

本文是自己学习SCP02(Secure Channel Protocol '02')的一次记录, 分析如何基于SCP02与安全域进行安全通信

本文规范细节参考GlobalPlatform Card Specification 2.2.1, 下文引用该文档时会简称GPC2.2.1

测试环境

  • 一张实现了GPC2.2.1的智能卡

首先, 根据GPC2.2.1-E.1.1章节可知

  • SCP02支持多种配置选项, 比如可以配置初始化安全通道使用显式(explicit)模式还是隐式(implicit)模式, 使用3个安全通道密钥(S-ENC, S-MAC和DEK)还是一个基本密钥(base key)等
  • 安全域的SCP02配置由"i"参数决定

所以与安全域建立SCP02通道前需要确定安全域的SCP02 i参数的值

这里我已经事先创建好一个SCP02 i值为0x55的安全域,下文介绍在不知道的情况下如何获取

根据GPC2.2.1-H.2 Structure of Card Recognition Data章节描述

Tag '64'. The OID {globalPlatform 4 scp i} identifies the Secure Channel Protocol of the Issuer Security Domain. "scp" identifies the Secure Channel Protocol identifier as defined in section 10.7 - Secure Channel Protocol Identifier. "i" identifies the eventual implementation options as defined in appendix D.1.1 - SCP01 Secure Channel for SCP01, appendix E.1.1 - SCP02 Secure Channel for SCP02 or appendix F.1.1 - SCP10 Secure Channel for SCP10

可以得知SCP02 i参数的值在Card Recognition Data的Tag '64'中

Card Recognition Data可以使用GET DATA指令获取到, 具体参考GPC2.2.1-11.3 GET DATA Command, 以我的测试卡为例,具体的APDU交互如下

>> 00A40400 10 A0000000660000000000000000000002 # SELECT SD
<< 6F188410A0000000660000000000000000000002A5049F6501FF 9000
>> 80CA0066 00 # GET DATA
<< 663D733B06072A864886FC6B01600B06092A864886FC6B020202630906072A864886FC6B03640B06092A864886FC6B040255640B06092A864886FC6B048000 9000

GET DATA响应中640B06092A864886FC6B040255就包含了SCP02 i参数

64 # Application tag 4
0B # LENGTH
06 # OID TAG
09 # OID LENGTH
2A864886FC6B040255# {globalPlatform 4 scp i}

参考GPC2.2.1-H.1 Data Values章节, 可对2A864886FC6B040255进一步解析

2A864886FC6B # 表示globalPlatform OID, 固定值
04 # 固定值
02 # 表示SCP 02
55 # i值

因此我的测试卡的安全域的SCP02 i参数的值为0x55

每个位的含义见Table E-1: Values of Parameter "i"

b8 b7 b6 b5 b4 b3 b2 b1 Description
Reserved 1 3 Secure Channel Keys
Reserved 0 1 Secure Channel base key
Reserved 1 C-MAC on unmodified APDU
Reserved 0 C-MAC on modified APDU
Reserved 1 Initiation mode explicit
Reserved 0 Initiation mode implicit
Reserved 1 ICV set to MAC over AID
Reserved 0 ICV set to zero
Reserved 1 ICV encryption for C-MAC session
Reserved 0 No ICV encryption
Reserved 1 R-MAC support
Reserved 0 No R-MAC support
Reserved 1 Well-known pseudo-random algorithm (card challenge)
Reserved 0 Unspecified card challenge generation method

可以看出我的卡使用了

  • 3 Secure Channel Keys
  • C-MAC on modified APDU
  • Initiation mode explicit
  • ICV set to zero
  • ICV encryption for C-MAC session
  • No R-MAC support
  • Well-known pseudo-random algorithm (card challenge)

根据GPC2.2.1-E1.2.1 Explicit Secure Channel Initiation的描述可知显式初始化SCP02安全通道由INITIALIZE UPDATE和EXTERNAL AUTHENTICATE两个指令完成, 初始化与安全域之间通道的流程如下

Explicit Secure Channel Initiation Flow

接下来通过实际APDU交互来分析这过程的细节, 首先执行SELECT和INITIALIZE UDPATE(详见E.5.1)指令

>> 00A40400 10 A0000000660000000000000000000002 # SELECT SD
<< 6F188410A0000000660000000000000000000002A5049F6501FF 9000
>> 80500000 08 1234567891234567 # INITIALIZE UDPATE
<< 0002000000000000000020020000B17EECA5CEB90D4AC851271C3C0D 9000

这里INITIALIZE UPDATE的Host challenge我随意赋值为1234567891234567

INITIALIZE UPDATE响应数据的各个字段表示如下

00020000000000000000 # key diversification data
2002 # Key information
0000 # Sequence Counter
B17EECA5CEB9 # Card challenge
0D4AC851271C3C0D # Card cryptogram

响应的Key information中的Key Version Number为20, 意味着我们需要用version为20的密钥来初始化通道, 这里version为20的3把密钥S-ENC,S-MAC和DEK都是已知的, 值为00112233445566778899aabbccddeeff

首先卡外实体需要验证Card cryptogram是否正确, 即上图中Verify card cryptogram这一步骤

Card Cryptogram的计算规则见GCP2.2.1-E.4.2 Authentication Cryptograms in Explicit Secure Channel Initiation及E.4.2.1 Card Authentication Cryptogram章节, 总结如下

  • 签名算法:Full Triple DES MAC, 实际上就是3DES-CBC
  • 填充方式: 附录B.4的DES Padding, 实际上就是7816-4 padding
  • 密钥:S-ENC session key(16字节)
  • 初始向量(IV):全0(8字节)
  • 待加密数据:host challenge + Sequence Counter + card challenge

除了S-ENC session key还未计算,其余数据都是已知的, 接下来查看S-ENC session key的计算规则, 在GPC2.2.1-E.4.1 DES Session Keys章节有对其进行描述,总结如下

  • 加密算法:3DES-CBC
  • 填充方式:填充'00'直到16字节
  • 密钥:S-ENC(16字节)
  • 初始向量:全0(8字节)
  • 待加密数据:'0182' + Sequence CounterF

到这一步已经可以计算出S-ENC session key,再进一步可以计算出Card cryptogram进行验证

以上面的实际APDU数据计算S-ENC session key

这里我直接用openssl工具进行计算,

$ printf "\x01\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | openssl enc -e -des-ede-cbc -nopad -iv 0000000000000000 -K 00112233445566778899aabbccddeeff | xxd -p

9eac5b939b1d2a6643fd9d31498b4f5a # 输出结果

得到S-ENC session key的值为9eac5b939b1d2a6643fd9d31498b4f5a, 接下来计算Card cryptogram

$ printf "\x12\x34\x56\x78\x91\x23\x45\x67\x00\x00\xB1\x7E\xEC\xA5\xCE\xB9\x80\x00\x00\x00\x00\x00\x00\x00" | openssl enc -e -des-ede-cbc -nopad -iv 0000000000000000 -K 9eac5b939b1d2a6643fd9d31498b4f5a | xxd -p
086f962b8c815b500a32cba04daa6f0f0d4ac851271c3c0d # 输出结果

得到Card cryptogram为0d4ac851271c3c0d, 与INITIALIZE UPDATE Response的Card cryptogram一致, 因此对卡的校验通过

接下来执行EXTERNAL AUTHENTICATE命令(详见GPC2.2.1-E.5.2),需要计算Host cryptogram及命令的C-MAC

Host cryptogram的计算规则见GCP2.2.1-E.4.2 Authentication Cryptograms in Explicit Secure Channel Initiation及E.4.2.2 Host Authentication Cryptogram章节,与Card Cryptogram类似, 总结如下

  • 签名算法:Full Triple DES MAC
  • 填充方式: DES Padding
  • 密钥:S-ENC session key(16字节)
  • 初始向量:全0(8字节)
  • 待签名数据:Sequence Counter + card challenge + host challenge
  • Card Cryptogram长度:8字节

到这里所有值已知,可以直接计算出Host Cryptogram

$ printf "\x00\x00\xB1\x7E\xEC\xA5\xCE\xB9\x12\x34\x56\x78\x91\x23\x45\x67\x80\x00\x00\x00\x00\x00\x00\x00" | openssl enc -e -des-ede-cbc -nopad -iv 0000000000000000 -K 9eac5b939b1d2a6643fd9d31498b4f5a | xxd -p
5cee0bb614aae6f6fa7ff14a2465b36cfc5bf6c2f09036a4 #输出结果

得到Host Cryptogram为fc5bf6c2f09036a4

C-MAC的计算规则见GPC2.2.1-E.4.4 APDU Command C-MAC Generation and Verification章节, 总结如下

  • 签名算法:Single DES Plus Final Triple DES(详见GPC2.2.1附录B.1.2.2)
  • 填充方式:DES Padding
  • 密钥:S-MAC session key
  • 初始向量: 对于EXTERNAL AUTHENTICATE初始向量为全0, 而后续指令的ICV为上一条命令的C-MAC
  • 待签名数据:CLA ~ Data, 不包含Le
  • C-MAC长度:8字节

需要特别注意的是由于C-MAC是APDU数据域的一部分, 会影响APDU指令的CLA及Lc,所以有两种方式来计算C-MAC

  • 先计算C-MAC再改变APDU
  • 先改变APDU再计算C-MAC

在GPC2.2.1-E.4.4对这两种方式有详细描述, 分别对应C-MAC Generation on Unmodified APDU及C-MAC Generation on Modified APDU

具体使用哪种方式取决于SCP02 i值的b2位,因为我的卡的SCP02 i值的b2位为0,所以使用的是C-MAC on modified APDU

首先计算S-MAC session key,具体参考GPC2.2.1-E.4.1,与前面计算S-ENC session key类似,变化部分为

  • 密钥:S-MAC(16字节)
  • 待加密数据:'0101' + Sequence Counter

以上面的实际APDU数据计算S-MAC session key

$  printf "\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | openssl enc -e -des-ede-cbc -nopad -iv 0000000000000000 -K 00112233445566778899aabbccddeeff | xxd -p
5bd6cd7b488a759d6b461d2c2951b947 # 输出结果

得到S-MAC session key为5bd6cd7b488a759d6b461d2c2951b947

接下来计算C-MAC,这里简单介绍下签名算法Single DES Plus Final Triple DES,更详细的请参考规范

比如待签名数据为n块块大小为8字节的数据,计算C-MAC过程如下

  1. 使用S-MAC session key的左8字节作为密钥, 对前面n-1块数据进行DES-CBC加密。
  2. 取第一步加密结果最后8字节作为初始向量IV,使用S-MAC session key 16字节作为密钥,对第n块数据进行3DES-CBC加密,得到的8字节结果就是C-MAC

以本次测试的实际APDU为例, 添加C-MAC前的EXTERNAL AUTHENTICATE指令(Modified APDU)如下

84 82 01 00 10 fc5bf6c2f09036a4

这里我指定Security level为C-MAC(P1=01),即后续指令需要带C-MAC,详见GPC规范对EXTERNAL AUTHENTICATE指令的介绍

进行DES Padding填充后数据为8482010010fc5bf6c2f09036a4800000

第一步,对前面n-1块数据进行DES加密, 因为待加密数据就16字节, 所以n为2

$ printf "\x84\x82\x01\x00\x10\xfc\x5b\xf6" | openssl enc -e -des-cbc -nopad -iv 0000000000000000 -K 5bd6cd7b488a759d | xxd -p
1b085b3ab00b0622 # 输出结果

加密结果最后8字节为1b085b3ab00b0622

接下来进行第二步计算

$ printf "\xc2\xf0\x90\x36\xa4\x80\x00\x00" | openssl enc -e -des-ede-cbc -nopad -iv 1b085b3ab00b0622  -K 5bd6cd7b488a759d6b461d2c2951b947 | xxd -p
a0305253a7003098 # 输出结果

得到C-MAC为a0305253a7003098

到这里EXTERNAL AUTHENTICATE指令就构造完成了,实际交互如下

>> 84820100 10 fc5bf6c2f09036a4a0305253a7003098 # EXTERNAL AUTHENTICATE
<< 9000

到这里与安全域之间的SCP02通道就初始化完成了

完整的APDU交互命令如下

>> 00A40400 10 A0000000660000000000000000000002 # SELECT SD
<< 6F188410A0000000660000000000000000000002A5049F6501FF 9000
>> 80500000 08 1234567891234567 # INITIALIZE UDPATE
<< 0002000000000000000020020000B17EECA5CEB90D4AC851271C3C0D 9000
>> 84820100 10 FC5BF6C2F09036A4A0305253A7003098 # EXTERNAL AUTHENTICATE
<< 9000

需要注意的是我在执行EXTERNAL AUTHENTICATE时指定Security level为C-MAC, 所以后续的APDU的C-MAC的计算需要使用上一条指令的C-MAC作为ICV, 且我的卡的安全域的SCP02 i值启用了ICV encryption for C-MAC session选项,需要参考E.3.4-ICV Encryption对ICV进行加密

参考:

  • GlobalPlatform Card Specification Version 2.2.1
@chenpengcong chenpengcong changed the title Card-显式初始化SCP02通道 SmartCard-显式初始化SCP02通道 Jul 4, 2020
@zzq20061951
Copy link

very good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants