jp ddlZddlZddlmZddlmZmZddlmZddl m Z m Z m Z m Z ddl mZddlmZddlmZddlmZmZdd lmZdd lmZdd lmZejeZd ed e dedefdZ!d(dedefdZ"dedefdZ#GddZ$dZ%dZ&dZ'Gddeej(Z)Gdde)Z*ddlm+Z+dd l,m-Z-d)d ed!eded"ee def d#Z.Gd$d%Z/Gd&d'e)Z0dS)*N)Optional)DES3DES)strxor)StructInt8ubInt16ubConst)Bytes)b2h)bertlv_parse_lenbertlv_encode_len)parse_command_apdu) SecureChannel) PySimLoggerconstantcounterbase_keyreturnct|dksJ|dkr|dksJt|dksJ||ddzdz}tj|tjd}||S)Nrbigs )lento_bytesrnewrMODE_CBCencrypt)rrrderivation_dataciphers O/home/jenkins/jenkins/workspace/simtester-sanitize/pySim/global_platform/scp.pyscp02_key_derivationr$"s x==A     a<>/ * **scH|dz t||zz }|dzd|zzS)uH Pad bytestring s: add '€' and ''* so the result to be multiple of BS.)r)r'BSls r#pad80r.,s- 1s1vv{A w;q  r%paddedc\|d}|ddksJ|ddS)z7Remove the customary 80 00 00 ... padding used for AES.r+N)rstrip)r/strippeds r#unpad80r52s8}}U##H B<4     CRC=r%cjeZdZdZdZdZdZdZdZdde d e d e fd Z de d e fd Z dde ddfdZd efdZdS)Scp02SessionKeysz,A single set of GlobalPlatform session keys.ssssr&Fdata reset_icvrc tj|jddtj}tj|jddtj}t |d}t |dz}|rdn|j}|}t|D]C} |t|t|d| zd| dzz}D| |}||}t dt|t|t||jr |j||_n||_|S)zGPad and calculate MAC according to B.1.2.2 - Single DES plus final 3DESNr&rr)zmac_1des(%s,icv=%s) -> %s)rrc_macMODE_ECBr.ricvranger rbytesdecryptlogdebugr des_icv_enc) selfr8r9ed padded_dataqr=his r# calc_mac_1deszScp02SessionKeys.calc_mac_1desBs; GDJrrNCL 1 1 GDJqrrNCL 1 1D!nn    !&4kkDH q F FA &E+ac!QqS'k*B$C$CDDEEAA IIaLL IIaLL -s4yy#c((CFFKKK   '//22DHHDHr%c tj|jtj}t |d}t |dz}d}t|D]C}|t|t|d|zd|dzz}Dt dt|t||S)Nr&rr)zmac_3des(%s) -> %s)rrencrr<r.rr>r rr?rArBr )rDr8rErGrHrIrJs r# calc_mac_3deszScp02SessionKeys.calc_mac_3desUs HTXs| , ,D!nn    ! q F FA &E+ac!QqS'k*B$C$CDDEEAA &D 3q66:::r%Tr card_keys GpCardKeysetcd|_||_||_t|j|j|j|_t|j|j|j|_t|j |j|j |_ t|j |j|j |_ |r,tj|jddtjnd|_dSNr&)r=rrOr$DERIV_CONST_CMACmacr;DERIV_CONST_RMACr_macDERIV_CONST_ENCrMDERIV_CONST_DENCdekdata_encrrr<rC)rDrrO icv_encrypts r#__init__zScp02SessionKeys.__init___s ")$*?y}]] )$*?y}]] '(3<@@@UYr%c d|jj|j|jrt |jndt |jt |jt |jt |jfzS)Nz8%s(CTR=%u, ICV=%s, ENC=%s, D-ENC=%s, MAC-C=%s, MAC-R=%s)None) __class____name__rr=r rMrZr;rVrDs r#__str__zScp02SessionKeys.__str__iseI'7\s48}}}V\DH s4=113tz??C OOMUU Ur%NFT)r` __module__ __qualname____doc__rSrUrWrX blocksizer?boolrKrNintr\strrbr%r#r7r7:s66""!O"I%DU&%EZZZZZZZUUUUUUUr%r7PceZdZdZd%dddefdZedefdZedefd Z edefd Z edefd Z de fd Z d&dededefdZdedefdZejdedefdZejdeedefdZejdefdZejd'dedefdZdedefdZdedefdZejd edefd!Zejd"edefd#Zd$S)(SCPzWAbstract base class containing some common interface + functionality for SCP protocols.rrOrPlchan_nrcjdkrnt|drfjt|jd|jddzvr5t d|jj|jd|jdfznSt|drCtfd|jDr#t |jjd|j||_ |_ d|_ d|_ d|_ dS) Nr kvn_ranger)z7%s cannot be used with KVN outside range 0x%02x..0x%02x kvn_rangesc\g|](}jt|d|ddzv)S)rr))kvnr>).0xrOs r# z SCP.__init__..s6VVV qtQqT!V)<)<<VVVr%z2 cannot be used with KVN outside permitted ranges F)rwhasattrr>rt ValueErrorr_r`allrurrrOskmac_on_unmodifiedsecurity_level)rDrOrrs ` r#r\z SCP.__init__ts/: =A    T; ' ' M=E$.*;T^A=Nq=P$Q$QQQ !Z"&."94>!;Ldn]^N_!`"abbbRT< ( ( MVVVVdoVVVWW M "&."9"9"94??"LMMM! "!&"r%rc|jdzS)zShould we perform C-MAC?r)rras r#do_cmacz SCP.do_cmac"T))r%c|jdzS)zShould we perform R-MAC?rrras r#do_rmacz SCP.do_rmacrr%c|jdzS)zShould we perform C-ENC?rrras r#do_cencz SCP.do_cencrr%c|jdzS)zShould we perform R-ENC? rras r#do_rencz SCP.do_rencrr%c.d|jj|jfzS)Nz%s[%02x])r_r`rras r#rbz SCP.__str__sT^4d6IJJJr%FTsmb8c:|rdnd}|r |tz}||jzS)Nr2r)CLA_SMrr)rDrrrets r#_clazSCP._clas."ddd  ,CT]""r%apduc>|ddzr|j|g|Ri|S|S)Nrr2)_wrap_cmd_apdurDrargskwargss r# wrap_cmd_apduzSCP.wrap_cmd_apdus< 7T> >&4&t=d===f== = r%cdS)z6Method implementation to be provided by derived class.Nrlrs r#rzSCP._wrap_cmd_apdus  r%host_challengecdSNrlrDrs r#gen_init_update_apduzSCP.gen_init_update_apdu r%resp_bincdSrrl)rDrs r#parse_init_update_respzSCP.parse_init_update_resprr%r)rcdSrrl)rDrs r#gen_ext_auth_apduzSCP.gen_ext_auth_apdurr%keyct||jjz}|r8tt|||d|zzzS||S)zEncrypt a key with the DEK.r+)rr~rhr dek_encrypt)rDrnum_pads r# encrypt_keyzSCP.encrypt_keysec((TW..  Y$SXX..1A1A#PWBW1X1XX X$$$r% encrypted_keyct||jjzr1||}t |\}}|d|S||S)zDecrypt a key with the DEK.N)rr~rh dek_decryptr )rDr decryptedkey_len remainders r# decrypt_keyzSCP.decrypt_keysh }   1 1 3((77I!1)!W>WY\]a]qYrYrsssssr%rc||_t|t|jjddg|jzdzS) Generate INITIALIZE UPDATE APDU.rr&r+)rr?rINS_INIT_UPDATErOrwrs r#rzSCP02.gen_init_update_apdus?,diikk?DN4F1MNNQUQddgnnnr%rcR|j|}|d|_t|d|j|_t |j||j|j |j |dkrtddS)z$Parse response to INITIALZIE UPDATE.rrrcard cryptogram doesn't matchN) constr_iurparserr7rOr~rArBrrrr|rDrresps r#rzSCP02.parse_init_update_resp!s$$X.."#34"4 #6GG $' !!$"5t7JKKK  4(9#: : :<== = ; :r%rc|dzrtd||_|jr1t|t |jddg}n1t|dt |jddg}|j||jzd}t|dt |jddg|jz|zS)$Generate EXTERNAL AUTHENTICATE APDU.z*R-MAC/R-ENC for SCP02 not implemented yet.rr&Tr) NotImplementedErrorrrr?r INS_EXT_AUTHr~rKr)rDrheaderrTs r#rzSCP02.gen_ext_auth_apdu+s D  T%&RSS S,  ! XDIIKKt7JAqQRRFFDIIdOO\4;NPQSUVWWFg##FT-A$A4HHdiioo|T5H!RPQQTXThhknnnr%rctdt||js|St |\}}}}|dksJ|dksJ|dz}|dz}|d}|dz} |dzs |t zr$||d| ks Jd|jr|} |} n|d z} |t z} |j t| g|d d zt| gz|z} |j r\tj |jjtjd } | t%|d }t'|}|d z }t|d | g|d d zt|gz|z| z}|d ks|dkr|dz }|S)z7Wrap Command APDU for SCP02: calculate MAC and encrypt.wrap_cmd_apdu(%s)rr2Fz CLA mismatchr&r)rorTrr+)rArBr rrrrrr~rKr?rrrrMrrr r.r)rDrrrcaselcler8clarmlcclacrTks r#rzSCP02._wrap_cmd_apdu8s %s4yy111| K1$77r2tSyyyySyyyy d  d 1g 4Z : ?v ?$))E2........  ! CDDq&C>A99U4^^,,DTB adiib))*++d1Q3i7%++ELsR 199 GOD r%swrsp_apduc|Srrl)rDrrs r#unwrap_rsp_apduzSCP02.unwrap_rsp_apdujsr%)rr)r`rerfrgrr rr r rrur\r?rrrrrrjrrr __classcell__r_s@r#rrsJJuuRyy0)F2BEE'NN%g-/?a/HJ[\a\abc\d\dJdffJ,t tTl;J*****)E)e)))) *U*u**** t5t%tttt oo5ooooo >u>>>> o o ou o o o o050e0000d%5Ur%r)AES)CMACcontextr-c0dtdtfd}|t|dz}tdt |t |t |||dz}t|dksJd|z}d}d }t||krl|d z|d d zt|gz|z} |||| z }|dz }|d krt dt||kl|d|S)z.prfws"xT3''..000r%Nr&z5scp03_kdf(constant=%s, context=%s, base_key=%s, l=%u)r)s r%r+rrrzOverflow in SP800 108 counter)r?rrArBr rr|) rrrr-r output_lenlabelrJdkinfos r#scp03_key_derivationrss@11U1111 y MMA IIEs8}}VYZaVbVbdghpdqdqstuuuaJ x==A     ( "E A B b''J  wAu!5!55qc BWL cc(D!!! Q v::<== = b''J   kzk?r%ceZdZdZdZdZdZdZdZdZ dd d e d e fd Z d e fdZ de fdZ ddefdZdde dede fdZdde dede fdZdS)Scp03SessionKeysr+rrrOrPrrc||z}t|j||j|_t|j||j|_t|j||j|_d|_ d|_ dS)Nr) rDERIV_CONST_KDERIV_S_ENCrMs_encDERIV_CONST_KDERIV_S_MACrTs_macDERIV_CONST_KDERIV_S_RMACs_rmacmac_chaining_valueblock_nr)rDrOrrrs r#r\zScp03SessionKeys.__init__so >1)$*GR[R_`` )$*GR[R_`` *4+I7T]Tabb #/ r%rc|j|z}tj|j|t}||_|S)zCompute C-MAC for given to-be-transmitted APDU. Returns the full 16-byte MAC, caller must truncate it if needed for S8 mode. ciphermod)rrrr rr)rDr cmac_inputcmac_vals r# calc_cmaczScp03SessionKeys.calc_cmacsB,t3 8DJ cBBBIIKK"*r% rdata_and_swc||j|z}tj|j|tS)zCompute R-MAC for given received R-APDU data section. Returns the full 16-byte MAC, caller must truncate it if needed for S8 mode.r)rrrr rr)rDr rmac_inputs r# calc_rmaczScp03SessionKeys.calc_rmacs6,|; x Z3???FFHHHr%F is_responsec|s|xjdz c_|j|jd}|r d|ddz}tdg|jz}t j|jtj|}||}t dt||t||S)zObtain the ICV value computed as described in 6.2.6. This method has two modes: * is_response=False for computing the ICV for C-ENC. Will pre-increment the counter. * is_response=True for computing the ICV for R-DEC.r)rr*Nrz'_get_icv(data=%s, is_resp=%s) -> icv=%s) rrrhr?rrr rr rArBr )rDrr8ivr"r=s r#_get_icvzScp03SessionKeys._get_icvs   MMQ MM}%%dne<<  &T!""X%D A3' ( (S\266nnT"" ;SYY UXY\U]U]^^^ r%r8rctj|jtj||}||Sr)rrr rrr rDr8rr"s r#_encryptzScp03SessionKeys._encrypt7S\4==3M3MNN~~d###r%Tctj|jtj||}||Sr)rrr rrr@rs r#_decryptzScp03SessionKeys._decryptr!r%Nrcrd)r`rerfDERIV_CONST_AUTH_CGRAM_CARDDERIV_CONST_AUTH_CGRAM_HOSTDERIV_CONST_CARD_CHLG_GENrr r rhr?r\rrrirr r#rlr%r#rrs")") '&& 'I . % Y^    eIeIIII D*$$U$$%$$$$ $$U$$$$$$$$r%rcleZdZdZededz dez eddez dedz d ed z d eed z Z d dgZ fdZ de de fdZ de de fdZdZd%dee de fdZde fdZd&dede fdZd'de d ede fd!Zd"e d#e de fd$ZxZS)(SCP03zQSecure Channel Protocol (SCP) 03 as specified in GlobalPlatform v2.3 Amendment D.rrri_paramrc|jjSr_s_modectxs r#zSCP03.s 35<r%rc|jjSrr,r/s r#r1zSCP03.s CELr%sequence_counterr0?c|dd|_|j|_tj|i|dS)Nr.r&)popr.rrr\rs r#r\zSCP03.__init__sCjj1--   $)&)))))r%rrctj|jjtjd}||SNr)rrrOrYrr rs r#rzSCP03.dek_encrypts.+S\:FF~~i(((r%rctj|jjtjd}||Sr9)rrrOrYrr@rs r#rzSCP03.dek_decrypts.+S\:FF~~j)))r%ctdt|jt|j|j|jz}t |jj||jj|j dz|_ t |jj ||jj|j dz|_ tdt|j t|j dS)Nrr&)r-r) rArBr rrrr~r$r r.rr%r)rDrs r#rzSCP03._compute_cryptogramss :C@SW>WY\]a]qYrYrsssssr%Nrc | d|jz}t||jkrtd|jz||_t |t |jjdt|g|zdzS)rNr+z$Host Challenge must be %u bytes longr) r.rr|rr?rrrOrwrs r#rzSCP03.gen_init_update_apdus  !$t{2N ~  $+ - -CdkQRR R,diikk?DN4F3~K^K^_``cqqt{{{r%rct|dvrtd|j||j}|d|_|d|_t|j|j |j|_ t |j | |j|dkrtddS) z$Parse response to INITIALIZE UPDATE.)-rr4z,Invalid length of Initialize Update Response)r.rr*rrN)rr|rrr.rr*rrOrr~rArBrrrs r#rzSCP03.parse_init_update_resps x== P P PKLL L$$Xdk$BB"#34I "4>43FH[\\ $' !!###  4(9#: : :<== = ; :r%r)rc||_t|t|jd|jg}|||jzdS)rrT) skip_cenc)rr?rrr.rr)rDrrs r#rzSCP03.gen_ext_auth_apdu sP, \43F4;WXX!!&4+?"?4!PPPr%FrrActdt||js|S|d}|d}|d}|d}t |\}}} } |dksJ| dksJ|dz}| dz} |jro|sm|dkr|jxjdz c_nQt| d} t| }|dkrtd |z|j | } ||j z} | dkrtd | |j fz|d ztz} t| |||| g| z}|j|}||d |j z }|d ks|dkr|dz }|S)z7Wrap Command APDU for SCP03: calculate MAC and encrypt.rrr)rrrrrz > >r%rrrc)r`rerfrgrr rr COptionalrrtr\r?rrrrrrrjrrirrrrs@r#r(r(s[[uuRyy0)F2BEE'NNT]^dTd(/G/G)H)HH)%%0H0H*I*II*99UU1XX+>+>>@@Jt I***** )E)e))))*U*u****ttt||8E?|e|||| >u > > > >QQQuQQQQ2252T2e2222h%5Ur%r()r&r)1rloggingtypingrCryptodome.CipherrrCryptodome.Util.strxorr constructrrr r rOosmocom.constructr osmocom.utilsr osmocom.tlvr r pySim.utilsrpySim.secure_channelr pySim.logrgetr`rAr?rjr$r.r5r7rrrABCrqrrCryptodome.Hashrrrr(rlr%r#r^s $ ''''''''))))))444444444444++++++######;;;;;;;;******......!!!!!!koh+5+3+%+E++++!!U!U!!!! Ee2U2U2U2U2U2U2U2Uh J J J J J -J J J ZmmmmmCmmmb"!!!!! 55EhWZmgl:A$A$A$A$A$A$A$A$HLLLLLCLLLLLr%