)gp ddlZddlZddlmZddlmZmZddlmZddl m Z m Z m Z m Z mZddl mZddlmZddlmZmZddlmZdd lmZejeZeejd ed ed ed efdZ d&ded efdZ!ded efdZ"GddZ#dZ$dZ%dZ&Gddeej'Z(Gdde(Z)ddlm*Z*ddl+m,Z,d'd eded ed eed ef d!Z-Gd"d#Z.Gd$d%e(Z/dS)(N)Optional)DES3DES)strxor)StructBytesInt8ubInt16ubConst)b2h)bertlv_parse_lenbertlv_encode_len)parse_command_apdu) SecureChannelconstantcounterbase_keyreturnct|dksJ|dkr|dksJt|dksJ||ddzdz}tj|tjd}||S)Nrbigs )lento_bytesrnewrMODE_CBCencrypt)rrrderivation_dataciphers G/home/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"unpad80r41s8}}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-ricvrangerrbytesdecryptloggerdebugr des_icv_enc) selfr7r8ed padded_dataqr<his r" calc_mac_1deszScp02SessionKeys.calc_mac_1desAs; GDJrrNCL 1 1 GDJqrrNCL 1 1D!nn    !&4kkDH q F FA &E+ac!QqS'k*B$C$CDDEEAA IIaLL IIaLL 0#d))SXXs1vvNNN   '//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=rrr>r@rAr )rCr7rDrFrGrHrIs r" calc_mac_3deszScp02SessionKeys.calc_mac_3desTs HTXs| , ,D!nn    ! q F FA &E+ac!QqS'k*B$C$CDDEEAA )3t99c!ff===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<rrNr#DERIV_CONST_CMACmacr:DERIV_CONST_RMACr_macDERIV_CONST_ENCrLDERIV_CONST_DENCdekdata_encrrr;rB)rCrrN 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 rLrYr:rUrCs r"__str__zScp02SessionKeys.__str__hseI'7\s48}}}V\DH s4=113tz??C OOMUU Ur$NFT)r_ __module__ __qualname____doc__rRrTrVrW blocksizer>boolrJrMintr[strrar$r"r6r69s66""!O"I%DU&%EZZZZZZZUUUUUUUr$r6PceZdZdZd%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.rrNrOlchan_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=).0xrNs r" z SCP.__init__..s6VVV qtQqT!V)<)<<VVVr$z2 cannot be used with KVN outside permitted ranges F)rvhasattrr=rs ValueErrorr^r_allrtrqrNskmac_on_unmodifiedsecurity_level)rCrNrqs ` r"r[z SCP.__init__ss/: =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(rr`s r"do_cmacz SCP.do_cmac"T))r$c|jdzS)zShould we perform R-MAC?rrr`s r"do_rmacz SCP.do_rmacrr$c|jdzS)zShould we perform C-ENC?rrr`s r"do_cencz SCP.do_cencrr$c|jdzS)zShould we perform R-ENC? rr`s r"do_rencz SCP.do_rencrr$c.d|jj|jfzS)Nz%s[%02x])r^r_rr`s r"raz SCP.__str__sT^4d6IJJJr$FTsmb8c:|rdnd}|r |tz}||jzS)Nr1r)CLA_SMrq)rCrrrets r"_clazSCP._clas."ddd  ,CT]""r$apduc>|ddzr|j|g|Ri|S|S)Nrr1)_wrap_cmd_apdurCrargskwargss r" wrap_cmd_apduzSCP.wrap_cmd_apdus< 7T> >&4&t=d===f== = r$cdS)z6Method implementation to be provided by derived class.Nrkrs r"rzSCP._wrap_cmd_apdus  r$host_challengecdSNrkrCrs r"gen_init_update_apduzSCP.gen_init_update_apdu r$resp_bincdSrrk)rCrs r"parse_init_update_respzSCP.parse_init_update_resprr$r(rcdSrrk)rCrs r"gen_ext_auth_apduzSCP.gen_ext_auth_apdurr$keyct||jjz}|r8tt|||d|zzzS||S)zEncrypt a key with the DEK.r*)rr}rgr dek_encrypt)rCrnum_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}rg dek_decryptr )rCr decryptedkey_len remainders r" decrypt_keyzSCP.decrypt_keysh }   1 1 3((77I!1)!rabcabstractmethodrrrrrrrrrrkr$r"rprpqsaa/#/#./#C/#/#/#/#b****X*****X*****X*****X*KKKKK##t###### %U  5 e      8E? u      u        u    %u%%%%%33%3333*  E e      U u      r$rpc BeZdZdZededz dez eddez dedz d ed z Z d d gd d gddggZ fdZ de de fdZ de de fdZde de fdZd"de de fdZde fdZd#dede fdZde de fdZde d e de fd!ZxZS)$SCP02z@An instance of the GlobalPlatform SCP02 secure channel protocol. key_div_data key_ver seq_countercard_challengecard_cryptogramr%r(r/pcHd|_tj|i|dSrQ)overheadsuperr[rCrrr^s r"r[zSCP02.__init__s, $)&)))))r$rrctj|jjddtj}||SrQ)rrrNrXr;rrCrr!s r"rzSCP02.dek_encrypt s5+BQB/>>~~i(((r$rctj|jjddtj}||SrQ)rrrNrXr;r?rCrr!s r"rzSCP02.dek_decrypts5+BQB/>>~~j)))r$rctdt|t||j|jjdd|z|z|_|j|j|jjddz|z|_ tdt|jt|j dS)N&host_challenge(%s), card_challenge(%s)rr(host_cryptogram(%s), card_cryptogram(%s)) r@rAr r}rMrrhost_cryptogramrr)rCrrs r"_compute_cryptogramszSCP02._compute_cryptogramss =s>?R?RTWXfTgTghhh#w44TW_5M5MaQV5W5WZh5hky5yzz#w44T5H47?KcKcdeglKmKm5mp~5~ ?TEYAZAZ\_`d`t\u\uvvvvvr$rc||_t|t|jjddg|jzdzS) Generate INITIALIZE UPDATE APDU.rr%r*)rr>rINS_INIT_UPDATErNrvrs 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_iurparserr6rNr}r@rArrrr{rCrresps r"rzSCP02.parse_init_update_resps$$X.."#34"4 #6GG TW !!$"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) NotImplementedErrorrr~r>r INS_EXT_AUTHr}rJr)rCrheaderrSs 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)rr1Fz CLA mismatchr%r(rnrTrr*)r@rAr rrrrr~r}rJr>rrrrLrrrr-r)rCrrrcaselcler7clarmlcclacrSks r"rzSCP02._wrap_cmd_apdu5s (#d))444| K1$77r2tSyyyySyyyy d  d 1g 4Z : ?v ?$))E2........  ! CDDq&C>A99U4^^,,DTB adiib))*++d1Q3i7%++ELsR 199 GOD r$swrsp_apduc|Srrk)rCrrs r"unwrap_rsp_apduzSCP02.unwrap_rsp_apdugsr$)rr)r_rdrerfrrr r r rrtr[r>rrrrrrirrr __classcell__r^s@r"rrsJJuuRyy0)F2BEE'NN%g-/?a/HJ[\a\abc\d\dJdffJ,t tTl;J*****)E)e))))*U*u****w5w%wwww 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.prfts"xT3''..000r$Nr%z5scp03_kdf(constant=%s, context=%s, base_key=%s, l=%u)r(s r$r*rrrzOverflow in SP800 108 counter)r>rr@rAr rr{) rrrr,r output_lenlabelrIdkinfos r"scp03_key_derivationrps@11U1111 y MMA  LLH#h--Y\]dYeYegjksgtgtvwxxxaJ 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*rrrNrOrrc||z}t|j||j|_t|j||j|_t|j||j|_d|_ d|_ dS)Nr) rDERIV_CONST_KDERIV_S_ENCrLs_encDERIV_CONST_KDERIV_S_MACrSs_macDERIV_CONST_KDERIV_S_RMACs_rmacmac_chaining_valueblock_nr)rCrNrrrs 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)r rrr rr)rCr 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)r rrr rr)rCr 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=False for computing the ICV for R-DEC.r(rr)Nrz'_get_icv(data=%s, is_resp=%s) -> icv=%s) rrrgr>rrrrrr@rAr )rCrr7ivr!r<s r"_get_icvzScp03SessionKeys._get_icvs   MMQ MM}%%dne<<  &T!""X%D A3' ( (S\266nnT"" >D ;X[\_X`X`aaa r$r7rctj|jtj||}||Sr)rrrrrrrCr7rr!s r"_encryptzScp03SessionKeys._encrypt7S\4==3M3MNN~~d###r$Tctj|jtj||}||Sr)rrrrrr?rs r"_decryptzScp03SessionKeys._decryptr r$Nrbrc)r_rdreDERIV_CONST_AUTH_CGRAM_CARDDERIV_CONST_AUTH_CGRAM_HOSTDERIV_CONST_CARD_CHLG_GENrr r rgr>r[rrrhrrr"rkr$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"r0zSCP03.s CELr$sequence_counterr0?c|dd|_|j|_tj|i|dS)Nr-r%)popr-rrr[rs r"r[zSCP03.__init__sCjj1--   $)&)))))r$rrctj|jjtjd}||SNr)rrrNrXrrrs r"rzSCP03.dek_encrypts.+S\:FF~~i(((r$rctj|jjtjd}||Sr8)rrrNrXrr?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) r@rAr rrrr}r#r r-rr$r)rCrs r"rzSCP03._compute_cryptogramss =s4CV?W?WY\]a]pYqYqrrr%(;;3DG4WY`bfbibosws~@AtA B B B3DG4WY`bfbibosws~@AtA B B B ?TEYAZAZ\_`d`t\u\uvvvvvr$Nrc | d|jz}t||jkrtd|jz||_t |t |jjdt|g|zdzS)rNr*z$Host Challenge must be %u bytes longr) r-rr{rr>rrrNrvrs 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.)-rr3z,Invalid length of Initialize Update Response)r-rr)rrN)rr{rrr-rr)rrNrr}r@rArrrs r"rzSCP03.parse_init_update_resps x== P P PKLL L$$Xdk$BB"#34I "4>43FH[\\ TW !!###  4(9#: : :<== = ; :r$r(rc||_t|t|jd|jg}|||jzdS)rrT) skip_cenc)rr>rrr-rr)rCrrs r"rzSCP03.gen_ext_auth_apdusP, \43F4;WXX!!&4+?"?4!PPPr$Frr@ctdt||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(rrrrrzr)rCrr@rinsp1p2rrrcmd_datarFrmclacmacs r"rzSCP03._wrap_cmd_apdus (#d))444| K1g1g !W !W#5d#;#; r2xSyyyySyyyy d  d  < 9 9qyy  A%   $Hb11 %%99$%cgi%jkkk7++K884; #::cgjlplwfxxyy yd f$dCR-..9w  && \dk\"" 199 GOD r$rrcPtd|||js |jrJ|S|dkr |ddvr|S|d|j }||j d}|j||zd|j}||krtd|d||jry|j|}tdt|t|}tdt||S) Nz#unwrap_rsp_apdu(sw=%s, rsp_apdu=%s)sr)bcz$R-MAC value not matching: received: z , computed: z decrypted: %szresponse_data: %s) r@rArrr-r}rr{r"r r4)rCrr response_datarmacrmac_exprs r"rzSCP03.unwrap_rsp_apduCs4  :BIII| | # # #O   Al!:!:O 4;,/  &7$$]R%788$+F 8  *W[W[W[]e]efgg g < B((77I LL#i.. 9 9 9#I..M LL,c-.@.@ A A Ar$rrrb)r_rdrerfrrr r COptionalrrsr[r>rrrrrrrirrhrrrrs@r"r'r's[[uuRyy0)F2BEE'NNT]^dTd(/G/G)H)HH)%%0H0H*I*II*99UU1XX+>+>>@@Jt I***** )E)e))))*U*u****www||8E?|e|||| >u > > > >QQQuQQQQ2252T2e2222h%5Ur$r')r%r)0rloggingtypingrCryptodome.CipherrrCryptodome.Util.strxorr constructrrr r r rN osmocom.utilsr osmocom.tlvr r pySim.utilsrpySim.secure_channelr getLoggerr_r@setLevelDEBUGr>rir#r-r4r6rrrABCrprrCryptodome.Hashrrrr'rkr$r"r]s$ ''''''''))))));;;;;;;;;;;;;;++++++;;;;;;;;******......  8 $ $ +5+3+%+E++++!!U!U!!!! Ee2U2U2U2U2U2U2U2Uh J J J J J -J J J ZkkkkkCkkk^"!!!!! 55EhWZmgl:A$A$A$A$A$A$A$A$HLLLLLCLLLLLr$