)g(*dZddlmZmZddlZddlmZmZmZmZddlm Z ddl m Z m Z ddlmZmZmZmZmZmZmZmZddlmZdd lmZmZmZmZmZdd lm Z dd l!m"Z"ej#eeefZ$d e%d e%de%fdZ&ded e%defdZ'GddZ(dS)z? pySim: SIM Card commands according to ISO 7816-4 and TS 11.11 )ListTupleN) ConstructStructConstSelect)Optional)LV filter_dict)rpadlpadb2hh2bh2ii2h str_sanitizeHexstr)bertlv_encode_len)sw_match expand_hexSwHexstrResTuple SwMatchstr) SwMatchError)LinkBaseclalchan_nrreturnc|dkr&|dz dvr |dz|dzzStd||fz|dkr)|dz dvr|d z|dz d zzStd||fztd ) z1Embed a logical channel number into the CLA byte.)r z4Undefined how to use CLA %2X with logical channel %u)r$z(logical channel outside of range 0 .. 15) ValueError)rrs Z,dnd,e ddWedXe d^e de fd_Z?dWedXe de fd`Z@dWedXe de fdaZAdKe de fdbZBdKe de fdcZCdvdfedgedeee effdhZDdie de fdjZEdmd;edefdkZFdFedee effdlZGd'S)wSimCardCommandsaGClass providing methods for various card-specific commands such as SELECT, READ BINARY, etc. Historically one instance exists below CardBase, but with the introduction of multiple logical channels there can be multiple instances. The lchan number will then be patched into the CLA byte by the respective instance. r transportrcL||_d|_||_d|_d|_dS)N0000a0)_tpsel_ctrlrr.scp)selfr4rs r+__init__zSimCardCommands.__init__Cs)    r-rcbt|j|}|j|_|j|_|S)zLFork a per-lchan specific SimCardCommands instance off the current instance.)r4r)r3r8r.r9)r;rrets r+ fork_lchanzSimCardCommands.fork_lchanKs-$(xHHH} }  r-c2|jrd|jjz SdS)zYMaximum length of the command apdu data section. Depends on secure channel protocol used.)r:overheadr;s r+ max_cmd_lenzSimCardCommands.max_cmd_lenRs# 8 ** *3r-Tpdu apply_lchanc|r(t|dd|j|ddz}|jr%|j|jj|S|j|S)aSends an APDU and auto fetch response data Args: pdu : string of hexadecimal characters (ex. "A0A40000023F00") apply_lchan : apply the currently selected lchan to the CLA byte before sending Returns: tuple(data, sw), where data : string (in hex) of returned data (ex. "074F4EFFFF") sw : string (in hex) of status word (ex. "9000") rN)r1rr:send_apdu_wrapperr8 send_apdu)r;rErFs r+rJzSimCardCommands.send_apduZsp  D QqS4=99CGCC 8 +8--dh.@#FF F8%%c** *r-9000swc|r(t|dd|j|ddz}|jr&|j|jj||S|j||S)aXSends an APDU and check returned SW Args: pdu : string of hexadecimal characters (ex. "A0A40000023F00") sw : string of 4 hexadecimal characters (ex. "9000"). The user may mask out certain digits using a '?' to add some ambiguity if needed. apply_lchan : apply the currently selected lchan to the CLA byte before sending Returns: tuple(data, sw), where data : string (in hex) of returned data (ex. "074F4EFFFF") sw : string (in hex) of status word (ex. "9000") rrHN)r1rr:rIr8send_apdu_checksw)r;rErLrFs r+rNz!SimCardCommands.send_apdu_checkswlst  D QqS4=99CGCC 8 78--dh.H#rRR R8--c266 6r-rinsp1p2 cmd_constrcmd_data resp_constrc x|r||nd} |rtt| gnd} |rdnd} d||||| t | | g} || |\} }| r0t |t| }nd}||fS)aBuild and sends an APDU using a 'construct' definition; parses response. Args: cla : string (in hex) ISO 7816 class byte ins : string (in hex) ISO 7816 instruction byte p1 : string (in hex) ISO 7116 Parameter 1 byte p2 : string (in hex) ISO 7116 Parameter 2 byte cmd_cosntr : defining how to generate binary APDU command data cmd_data : command data passed to cmd_constr resp_cosntr : defining how to decode binary APDU response data apply_lchan : apply the currently selected lchan to the CLA byte before sending Returns: Tuple of (decoded_data, sw) 00rFN) buildrlenjoinrrJr parser)r;rrOrPrQrRrSrTrFcmdlclerEdatarLrsps r+send_apdu_constrz SimCardCommands.send_apdu_constrs -5>483JKK KRyr-fcpcddlm}|gd}|}|dddkrtd|ddzt |ddd}t |dddz|krd}nGt |dd d}t |dddz|krd }td ||d}||S) Nr)TLV) 828384a58a8b8c80abc68188rH62z>Tag of the FCP template does not match, expected 62 but got %sr r%r&z%Cannot determine length of TLV-length) pytlv.TLVrjrer*intrZr\)r;rhrj tlvparser exp_tlv_lenskiptlvs r+ __parse_fcpzSimCardCommands.__parse_fcps* "!!!!!C<<<== iikk qs8t  PSVWXYZWZS[[]] ]#ac(B'' s122w<<1  + +DDc!A#h++K3qrr7||q K//DEE E$%%js###r-c|jdkr;||d}|d}t|dddSt|ddddS) N0004rkr r"r%r9_SimCardCommands__parse_fcpry)r;r tlv_parsedfile_descriptors r+ __record_lenzSimCardCommands.__record_lense =F " "))!B%00J(.Oqs+R00 0quRU|R(( (r-c|jdkr1||d}t|ddSt|ddddS)Nrrrrr%r r"r)r;rrs r+__lenzSimCardCommands.__lensW =F " "))!B%00Jz$',, ,quQqSz2&& &r-c4|jS)z.Return the ATR of the currently inserted card.)r8get_atrrCs r+rzSimCardCommands.get_atrsx!!!r-dir_listcg}t|ts|g}|D]T}||jdz|jzdz|zdz\}}|||f|dkr|cSU|S)zj Try to select a specified path Args: dir_list : list of hex-string FIDs a402rWrK) isinstancelistrJr.r9append)r;rrvir`rLs r+try_select_pathzSimCardCommands.try_select_paths(D)) " zH  A~~dmd&:T]&JT&QTU&UX\&\]]HD" IItRj ! ! !V||  r-cg}t|ts|g}|D]/}||\}}||0|S)zExecute SELECT for an entire list/path of FIDs. Args: dir_list: list of FIDs representing the path to select Returns: list of return values (FCP in hex encoding) for each element of the path )rr select_filer)r;rrrr`_sws r+ select_pathzSimCardCommands.select_paths^(D)) " zH  A((++ID# IIdOOOO r-fidc^||jdz|jzdz|zdzS)zoExecute SELECT a given file by FID. Args: fid : file identifier as hex string rrrW)rNr.r9r;rs r+rzSimCardCommands.select_files7%%dmd&:T]&JT&QTW&WZ^&^___r-c<||jdzS)z*Execute SELECT to switch to the parent DF a40304rNr.rCs r+select_parent_dfz SimCardCommands.select_parent_dfs%%dmh&>???r-aidcdtt|dzdzdd}||jdzdz|z|zdzS) zzExecute SELECT a given Applicaiton ADF. Args: aid : application identifier as hex string 0rHxNr0404rW)formatrZrNr.)r;raidlens r+ select_adfzSimCardCommands.select_adfs[s3xx1}c222BCC8%%dmd&:V&Cf&Ls&RUY&YZZZr-Neflengthoffsetc||}t|ddkrdS||||z }|dkrdSd}d}||krt|j||z }|jd||z|fzz} ||\} } n,#t$r} | d|z| d} ~ wwxYw|| z }||z }||k|| fS)aExecute READD BINARY. Args: ef : string or list of strings indicating name or path of transparent EF length : number of bytes to read offset : byte offset in file from which to start reading rrNNNrVz b0%04x%02xzfailed to read (offset %d)) rrZ_SimCardCommands__lenminrDr.rN Exceptionadd_note) r;rrrr total_data chunk_offset chunk_lenrEr`rLes r+ read_binaryzSimCardCommands.read_binary)s*   R  qu::??< >ZZ]]V+F A::<  V##D,f\.ABBI- 5yAABC 11#66bb    7&@AAA  $ J I %LV##2~sB!! C +CC r`c4||t|dz|}|d|kr@td|d|dddS)aVerify contents of transparent EF. Args: ef : string or list of strings indicating name or path of transparent EF data : hex string of expected data offset : byte offset in file from which to start verifying rHrz%Binary verification failed (expected , got )N)rrZrer*)r;rr`rress r+__verify_binaryzSimCardCommands.__verify_binaryHsr3t99>6:: q6<<>>TZZ\\ ) )* c!fllnnnn.// / * )r-Fverifyconservec||}t||}t|dz}|r6 ||||\}} ||krd| fSn#t$rYnwxYw||d} d} | |krt |j|| z } |jd|| z| fzz|| dz| | zdzz} | | \}}n.#t$r!}| d| | fz|d}~wwxYw| |z } | | z } | |k|r| |||| |fS)aKExecute UPDATE BINARY. Args: ef : string or list of strings indicating name or path of transparent EF data : hex string of data to be written offset : byte offset in file from which to start writing verify : Whether or not to verify data after write rHNrVrz d6%04x%02xz5failed to write chunk (chunk_offset %d, chunk_len %d)) binary_sizerrZrrrrrDr.rNr_SimCardCommands__verify_binary)r;rr`rrrfile_len data_length data_currentrLrrrrE chunk_datachunk_swrs r+ update_binaryzSimCardCommands.update_binaryUs##B''$))$ii1n    #'#3#3B V#L#L b4''8O(         [((D,kL.HIII- 5yAAB\!^l9&>TZZ\\ ) )* c!fllnnnn.// / * )r- force_lenleftpadc||}||} t|| }|rt|dz} nyt|dz| kr$t d| t|dzfzt|dz| kr)|rt || dz}nt || dz}|rB |||\} } | d| dz} | |krd| fSn#t$rYnwxYw|j d|| fzz|z} | | }|r| ||||S)a,Execute UPDATE RECORD. Args: ef : string or list of strings indicating name or path of linear fixed EF rec_no : record number to read data : hex string of data to be written force_len : enforce record length by using the actual data length verify : verify data by re-reading the record conserve : read record and compare it with data, skip write on match leftpad : apply 0xff padding from the left instead from the right side. rHz;Data length exceeds record length (expected max %d, got %d)rNz dc%02x04%02x) rrrrZr*r r rrr.rN_SimCardCommands__verify_record) r;rrr`rrrrrrrrLrEs r+ update_recordzSimCardCommands.update_recordsr""&&s++ $ ++  6TaJJ4yyA~ ** !^D Qb0"0111Ta*,,6j1n55DDj1n55D   #'#3#3B#?#? b+AjlN; 4''8O(      }~0DDDL$$S))  3  VT 2 2 2 s /C== D  D cV||}||S)zDetermine the record size of given file. Args: ef : string or list of strings indicating name or path of linear fixed EF )rrr;rrs r+ record_sizezSimCardCommands.record_sizes+   R   ###r-c||}||||zS)zDetermine the number of records in given file. Args: ef : string or list of strings indicating name or path of linear fixed EF )rrrrs r+ record_countzSimCardCommands.record_counts:   R zz!}} 1 1! 4 444r-cV||}||S)zDetermine the size of given transparent file. Args: ef : string or list of strings indicating name or path of transparent EF )rrrs r+rzSimCardCommands.binary_sizes'   R zz!}}r-tagfirstc@|rd|z}nd}||S)Nz80cb008001%02x0080cb0000rN)r;rrrEs r+_retrieve_datazSimCardCommands._retrieve_datas/  $,CCC%%c***r-c||}t|ddkrdSd}||d\}}||z }|dvr#||d\}}||z }|dv#||fS) zExecute RETRIEVE DATA, see also TS 102 221 Section 11.3.1. Args ef : string or list of strings indicating name or path of transparent EF tag : BER-TLV Tag of value to be retrieved rrrrVTr)62f162f2F)rrZr)r;rrrrr`rLs r+ retrieve_datazSimCardCommands.retrieve_datas   R  qu::??< &&s$&77bd $$$**3e*<>&3,d>;; ;c"3CJJM"B"BCCD D5jc((LL  )nnq   !2$"2!23Hxu==IE2E!$"2"3"34I )nnq  byr-randct|dkrtd|ddg|d|zdzdS) zrExecute RUN GSM ALGORITHM. Args: rand : 16 byte random data as hex string (RAND) z Invalid rand3f007f20 a088000010rWrK)rL)rZr*rrN)r;rs r+run_gsmzSimCardCommands.run_gsm4s] t99??^,, , &&)***%%lT&9D&@V%LLLr-3gautncontextc tdtz dttz }ttddtz }ttddtz dtz dtz d ttz }t ||}||d }|d krd } n|d krd} nt d|z||jdd| |||\} } d| vrd| i} nd| i} | | fS)zExecute AUTHENTICATE (USIM/ISIM). Args: rand : 16 byte random data as hex string (RAND) autn : 8 byte Autentication Token (AUTN) context : 16 byte random data ('3g' or 'gsm') rrautsrckikkc)rrrrugsmrrzUnsupported context '%s'rvrWsynchronisation_failuresuccessful_3g_authentication)rr COptionalrrr*rgr.) r;rrr AuthCmd3GAuthResp3GSyncFailAuthResp3GSuccess AuthResp3GrSrQr`rLr>s r+ authenticatezSimCardCommands.authenticate?s6"9fYr]]&:;; #E'NNF2I>>"5>>58T"Wd2gtT]^`TaTaOabb.0ABB  $// d??BB   BB7'ABB B22 M4r9h LL r T>>,d3CC148CRyr-c,|dS)z:Execute a STATUS command as per TS 102 221 Section 11.1.2.80F20000rrCs r+statuszSimCardCommands.status\s%%j111r-c B||jddddddS)zBExecute DECATIVATE FILE command as per TS 102 221 Section 11.1.14.04rWN)rgr.rCs r+deactivate_filezSimCardCommands.deactivate_file`s&,,T]D$dTXZ^___r-cB||jdz|zS)zExecute ACTIVATE FILE command as per TS 102 221 Section 11.1.15. Args: fid : file identifier as hex string 44000002rrs r+ activate_filezSimCardCommands.activate_fileds$ %%dmj&@3&FGGGr-payloadcf||jdt|dz|fzzS)z9Execute CREATE FILE command as per TS 102 222 Section 6.3z e00000%02x%srH)rNr.rZr;rs r+ create_filezSimCardCommands.create_filels3%%dmnG VWY`Ga6a&abbbr-cV|dt|dz|fzS)z:Execute RESIZE FILE command as per TS 102 222 Section 6.10z80d40000%02x%srHrNrZrs r+ resize_filezSimCardCommands.resize_fileps+%%&6#g,,/79S&STTTr-cB||jdz|zS)z9Execute DELETE FILE command as per TS 102 222 Section 6.4e4000002rrs r+ delete_filezSimCardCommands.delete_filet"%%dmj&@3&FGGGr-cB||jdz|zS)z:Execute TERMINATE DF command as per TS 102 222 Section 6.7e6000002rrs r+ terminate_dfzSimCardCommands.terminate_dfxr"r-cB||jdz|zS)z:Execute TERMINATE EF command as per TS 102 222 Section 6.8e8000002rrs r+ terminate_efzSimCardCommands.terminate_ef|r"r-c<||jdzS)zBExecute TERMINATE CARD USAGE command as per TS 102 222 Section 6.9fe000000rrCs r+terminate_card_usagez$SimCardCommands.terminate_card_usages%%dmj&@AAAr-openmodec`|dkrd}nd}|jd||fzz}||S)zExecute MANAGE CHANNEL command as per TS 102 221 Section 11.1.17. Args: mode : logical channel operation code ('open' or 'close') lchan_nr : logical channel number (1-19, 0=assigned by UICC) closerrz 70%02x%02x)r.rN)r;r-rrPrEs r+manage_channelzSimCardCommands.manage_channelsB 7??BBBmlb(^;;%%c***r-c4|jS)zPhysically reset the card)r8 reset_cardrCs r+r2zSimCardCommands.reset_cardsx""$$$r-op_namechv_nopin_codec t|drHtd||t|t |dfz|dkrt |d|jjdS)N63cxz9Failed to %s chv_no 0x%02X with code 0x%s, %i tries left.r$rK)r RuntimeErrorrupperryrr8rf)r;r3r4r5rLs r+_chv_process_swzSimCardCommands._chv_process_sws B   UZ 'X1D1D1F1FBqE S TUU U <<r648+BCC C >$-&"8FVO"Lt"SVX"XYYb XvtR888bzr-puk_codectt|dtt|dz}||jdzd|zzdz|z\}}|d|||||fS)zUnblock a given CHV (Card Holder Verification == PIN) Args: chv_no : chv number (1=CHV1, 2=CHV2, ...) puk_code : puk code as hex string pin_code : new chv code as hex string r%2C00r>10unblockr@)r;r4rCr5rAr`rLs r+ unblock_chvzSimCardCommands.unblock_chvs#h-- $ $tCMM2'>'> >>>$-&"8FVO"Lt"SVX"XYYb Y"===bzr- new_pin_codectt|dtt|dz}||jdzd|zzdz|z\}}|d|||||fS)zChange a given CHV (Card Holder Verification == PIN) Args: chv_no : chv number (1=CHV1, 2=CHV2, ...) pin_code : current chv code as hex string new_pin_code : new chv code as hex string r%2400r>rFchanger@)r;r4r5rIrAr`rLs r+ change_chvzSimCardCommands.change_chvs#h-- $ $tC ,=,=r'B'B B>>$-&"8FVO"Lt"SVX"XYYb Xvx<<<bzr-ctt|d}||jdzd|zzdz|z\}}|d|||||fS)zDisable a given CHV (Card Holder Verification == PIN) Args: chv_no : chv number (1=CHV1, 2=CHV2, ...) pin_code : current chv code as hex string new_pin_code : new chv code as hex string r%2600r>r?disabler@r;r4r5rAr`rLs r+ disable_chvzSimCardCommands.disable_chvsm#h-- $ $>>$-&"8FVO"Lt"SVX"XYYb Y"===bzr-ctt|d}||jdzd|zzdz|z\}}|d|||||fS)zEnable a given CHV (Card Holder Verification == PIN) Args: chv_no : chv number (1=CHV1, 2=CHV2, ...) pin_code : chv code as hex string r%2800r>r?enabler@rQs r+ enable_chvzSimCardCommands.enable_chvsm#h-- $ $>>$-&"8FVO"Lt"SVX"XYYb Xvx<<<bzr-cZ|dt|dz|fzdS)zlSend one ENVELOPE command to the SIM Args: payload : payload as hex string z80c20000%02x%srHFrXrrs r+envelopezSimCardCommands.envelopes3 %%&6#g,,/79S&Sch%iiir-cnt|dz}|d|z|zd\}}||fS)zeSend TERMINAL PROFILE to card Args: payload : payload as hex string rHz 80100000%02xFrX)rZrN)r;rrr`rLs r+terminal_profilez SimCardCommands.terminal_profilesE 'lla' ))>K+G7*Rbg)hhbbzr-< min_len_secs max_len_secscdtdtfd}dtdtfd}||}||}|d|z|zd\}}||d d } |d d } | | |fS) zSend SUSPEND UICC to the card. Args: min_len_secs : mimumum suspend time seconds max_len_secs : maximum suspend time seconds secsrc||dkrd|dzzS|dkrd|dzzS|dkrd|dzzS|dkrd|dzzSd |zS) Ni/ z04%02xiQz03%02xiz02%02xr[z01%02xz00%02x)r`s r+encode_durationz5SimCardCommands.suspend_uicc..encode_durationsr{""4K#899x4H#566u}}4E?33rzz42:..d? "r-encc|dd}t|ddd}|dkr|dzdzdzdzS|dkr |dzdzdzS|d kr|dzdzS|d kr|dzS|d kr|Std ) NrHr rrr!r[03r01rWzTime unit must be 0x00..0x04)rr*)rd time_unitrs r+decode_durationz5SimCardCommands.suspend_uicc..decode_durationsBQBIQqS]]1%FD  {2~b(++D  {2~b((D  {2~%D  {"D   ;<< e)TTbbzr-cD|d||fz\}}||fS)Nz %02xca%04x00r)r;rrr`rLs r+get_datazSimCardCommands.get_datas,)).C:*EFFbbzr-c@|d|z\}}||fS)Nz 807800%02x00r)r;rr`rLs r+ get_identityzSimCardCommands.get_identity$s()).G*DEEbbzr-)r)T)rKT)Nr)rFF)FFFF)FF)r)r,r)r[r\)H__name__ __module__ __qualname____doc__rryr<r?propertyrDrboolrrJrrNrrdictrrbrgrrrrrrPathrrrrrstrrrrrrrrrrrrrrrrrrrrr!r%r(r+r0r2r:rBrHrMrRrVrXrZrprtrvrxrbr-r+r3r3>s ))(c3+<SX++V++++++$77V77RV7bj7777*W[FV]f#)8AOS_deikses_t<PTFVQW-6BHW`)3HLX]^bdl^lXm0$v$$$$L)))))'#''''"""""V h"DT&\"`v`(````@(@@@@[f[[[[[dCH> / / /S / / / /UZ',/$/$/$F/$C/$T/$ $/$19/$/$/$/$b +d +C +H + + + + /$ / /3 / / / /TYTY333c33D3"36:3MQ3^f3333j$d$s$$$$5t55555ds++#+d+h++++38(++f+T+X++++CQUbj> MF Mx M M M Mvx:22222`````HHHHHHHc6chccccU6UhUUUUHvH(HHHHHH8HHHHHH8HHHHBhBBBB + +3 +3 +h + + + +%F%%%%DsDCD6DxDDDD  F x     #         f QY     #  H       8    jj8jjjj8%<%<%<%rs* 666666666666++++++--------NNNNNNNNNNNNNNNNNNNN))))))LLLLLLLLLLLLLL))))))$$$$$$|FDL()EEEEEEE$5V5s5v5555 h h h h h h h h h h r-