idZddlmZmZmZmZmZmZmZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlmZmZddlmZddlmZmZmZmZmZmZmZmZddlmZddlm Z m!Z!m"Z"dd l#m$Z$m%Z%dd l&m'Z'dd l(m)Z)dd l*m+Z+ee,ee,ee,d ffZ-ee,ee,fZ.GddZ/Gdde/Z0Gdde0Z1Gdde0Z2GddZ3Gdde/Z4Gdde4Z5Gdde4Z6Gdde6Z7Gd d!e5Z8Gd"d#e4Z9d$e:d%e;fd&Z<Gd'd(Z=Gd)d*e j>Z?Gd+d,Z@dS)-aRepresentation of the ISO7816-4 filesystem model. The File (and its derived classes) represent the structure / hierarchy of the ISO7816-4 smart card file system with the MF, DF, EF and ADF entries, further sub-divided into the EF sub-types Transparent, Linear Fixed, etc. The classes are intended to represent the *specification* of the filesystem, not the actual contents / runtime state of interacting with a given smart card. )castOptionalIterableListDictTupleUnionN) CommandSetwith_default_category)toBytes)h2bb2his_hexauto_int auto_uint8 auto_uint16 is_hexstr JsonEncoder)bertlv_parse_one) filter_dictparse_constructbuild_construct)sw_match decomposeATR)js_path_modify)SimCardCommands) SwMatchError.ceZdZdZgdZdgZ d'dedededed ed d ed d eefdZ dZ de deefdZ d(de defdZ d(de deefdZdedfdZdddeedfdZdedfdZdgfdedeedffdZdgfdeedeedffdZgfdeedffdZgfdeefdZd efd!Zd"Zd#eefd$Zed%e fd&ZdS))CardFilezBase class for all objects in the smart card filesystem. Serve as a common ancestor to all other file types; rarely used directly. ).../MF3f00NfidsfidnamedescparentCardDFprofile CardProfileservicecTt|ts|td|r|}||_||_||_||_||_|jr,|j|kr!|jr|j |||_ ||_ g|_ dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy profile : Card profile that this file should be part of service : Service (SST/UST/IST) associated with the file Nzfid is mandatory) isinstanceCardADF ValueErrorlowerr%r&r'r(r)add_filer+r-shell_commands)selfr%r&r'r(r)r+r-s >/home/jenkins/workspace/simtester-sanitize/pySim/filesystem.py__init__zCardFile.__init__>s$(( 1S[/00 0  ))++C    ; '4;$..48. K  & & &   c,|jr|jS|jSNr'r%r5s r6__str__zCardFile.__str__^s 9 9 8Or8 prefer_namereturnc0|r|jr|jS|jSr:r;r5r>s r6 _path_elementzCardFile._path_elementds"  49 9 8Or8TcRd||S)zReturn fully qualified path to file as string. Args: prefer_name : Preferably build path of names; fall-back to FIDs as required r")joinfully_qualified_pathrAs r6fully_qualified_path_strz!CardFile.fully_qualified_path_strjs$ xx11+>>???r8c|jr&|j|kr|j|}ng}||}|r|||S)zReturn fully qualified path to file as list of FID or name strings. Args: prefer_name : Preferably build path of names; fall-back to FIDs as required )r)rErBappend)r5r>retelems r6rEzCardFile.fully_qualified_pathrsh ; 4;$..+22;??CCC!!+..   JJt    r8c|jr%|j|kr|j}ng}|r|||S)zLReturn fully qualified path to file as list of CardFile instance references.)r)fully_qualified_path_fobjrH)r5rIs r6rLz"CardFile.fully_qualified_path_fobjsQ ; 4;$..+7799CCC   JJt    r8targetcd}||kr|gS|}|}g}||D]}||t dt |dz D]L}||}||kr<||dzdD]} || ||ddccSMdS)zTBuild the relative sequence of files we need to traverse to get from us to 'target'.cttdt|D])}t||tr ||dcS*|S)Nr)reversedrangelenr/r0) inter_pathis r6 clip_pathz0CardFile.build_select_path_to..clip_paths^eAs:7788 * *jmW55*%abb>)))* r8rN)get_mfrLreverserHrQrR) r5rMrU cur_fqpath target_fqpathrScerTtete2s r6build_select_path_tozCardFile.build_select_path_tos*     V]]__ $ $8O3355 88::   5 5B   b ! ! !1c-00233 5 5"1%88,QqSTT2//"))#....$9Z^4444444  5tr8CardMFc|jdS|}|jr$|j|kr|j}|jr |j|ktt|S)z(Return the MF (root) of the file system.N)r)rr_)r5nodes r6rWzCardFile.get_mfsY ; 4k dkT11;Dk dkT11FD!!!r8aliasci}|r|||i|jr&|gksd|vr||j|i|jr&|gksd|vr||j|i|S)amReturn a dict of {'identifier': self} tuples. Args: alias : Add an alias with given name to 'self' flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing reference to 'self' for all identifiers. FIDSFNAMES)updater%r'r5rbflagsselss r6_get_self_selectableszCardFile._get_self_selectabless  ' KK & & & 8 *"% KK4( ) ) ) 9 +%2++U):): KKD) * * * r8ci}|jr |j|kr|S|r|||ji|jjr0|gksd|vr&||jj|ji|jjr0|gksd|vr&||jj|ji||jd||S)Nrdre)r)rfr%r'_get_parent_selectablesrgs r6rlz CardFile._get_parent_selectabless{ dkT11K  . KK , - - - ;? 8 v KK$+6 7 7 7 ;  9"E0A0A KK)4;7 8 8 8 DK77eDDEEE r8ci}|gksd|vr|d|}|gksd|vr)||d||gksd|vrh|}|rR|||||||S)aReturn a dict of {'identifier': File} that is selectable from the current file. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing all selectable items. Key is identifier (string), value a reference to a CardFile (or derived class) instance. SELFr!PARENTr r#)rh)rjrfrlrWget_app_selectables)r5rhrimfs r6get_selectableszCardFile.get_selectabless B;;&E//--c599D B;;(e++ KK44T5AA B B B B;;$%--B A B4454AABBB B222??@@@ r8c||}t|}||S)aAReturn a dict of {'identifier': File} that is selectable from the current file. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: list containing all selectable names. )rrlistkeyssort)r5rhrisel_keyss r6get_selectable_nameszCardFile.get_selectable_namess>##E** $$ r8data_hexcH|jr|j|SdS)zxDecode the response to a SELECT command. Args: data_hex: Hex string of the select response N)r)decode_select_response)r5rys r6r{zCardFile.decode_select_responses1 ; @;55h?? ? @ @r8cb|jr|jS|jr|jSdS)zGet the profile associated with this file. If this file does not have any profile assigned, try to find a file above (usually the MF) in the filesystem hierarchy that has a profile assigned N)r+r) get_profiler<s r6r}zCardFile.get_profile s; < <  ; -;**,, ,tr8servicesc,|jdSt|jtr |j|vSt|jtr|jD] }||vrdS dSt|jtr|jD] }||vrdS dSt d)z[Assuming the provided list of activated services, should this file exist and be activated?.NTFz0self.service must be either int or list or tuple)r-r/intrttupler1)r5r~ss r6should_exist_for_servicesz"CardFile.should_exist_for_servicess < 4 dlC ( ( ,<8+ + dlD ) ) \  ==44!5 dlE * * \ ! !H}} 55%4KLLLr8as_jsonc0dt|jzS)a Export file contents in the form of commandline script. This method is meant to be overloaded by a subclass in case any exportable contents are present. The generated script may contain multiple command lines separated by line breaks ("\n"), where the last commandline shall have no line break at the end (e.g. "update_record 1 112233\nupdate_record 1 445566"). Naturally this export method will always refer to the currently selected file of the presented lchan. z# %s has no exportable contentsstr selected_filerlchans r6exportzCardFile.export/s13u7J3K3KKKr8)NNNNNNN)T)__name__ __module__ __qualname____doc__RESERVED_NAMES RESERVED_FIDSrrCardFileServicer7r=boolrBrFrrErLr^rWrrjrlrrrxr{r}rr staticmethodrr8r6rr7s,++NHMX\W[6:!!C!c!!RU!!(+!=Em=T!"?3!!!!@ (3- @@D@C@@@@   S    4 +;:(4 CS:T<"*""""26R3DjDY&>B  Xc] PTUXZdUdPe    %'4Z+@2*,  S     @s @ @ @ @   M$s)MMMM*LLLL\LLLr8rc&eZdZdZedGddeZfdZfdZdZ dZ dd e d e fd Z dd ee d e fdZgfdeffd Zdeedee fdZdeedee fdZdedee fdZxZS)r*zWDF (Dedicated File) in the smart card filesystem. Those are basically sub-directories.zDF/ADF CommandsceZdZdS)CardDF.ShellCommandsN)rrrrr8r6 ShellCommandsr>s r8rc t|tsd|vrtdtjdi|i|_|g|_i|_dS)Nr%zfid is mandatory for all DFr) r/r0 TypeErrorsuperr7childrenrr4files_by_servicer5kwargs __class__s r6r7zCardDF.__init__Bsx$(( ?F"" =>>>""6""" #11334 "r8cJdtzS)NzDF(%s)rr=r5rs r6r=zCardDF.__str__L577??,,--r8c|jsdSt|jtr5|j|jg|dSt|jt r:|jD]0}|j|g|1dSt|jtr:|jD]0}|j|g|1dSt)z;Add a child (DF/EF) to the files_by_services of the parent.N) r-r/rr setdefaultrHrtrr1)r5childr-s r6_add_file_serviceszCardDF._add_file_servicesOs}  F emS ) )   ! , ,U]B ? ? F Fu M M M M M  t , ,  = L L%00"==DDUKKKK L L  u - -  = L L%00"==DDUKKKK L L r8c|jrdS|jD].}t|tr|rdS/dS)NT)r-rvaluesr/r* _has_service)r5cs r6rzCardDF._has_service^sd < 4%%''  A!V$$ >>## 44  r8Frignore_existingc:t|tstdt|jddst d|jz|jtjvrt d|jz|jtjvrt d|jz|j|j vr|rdSt d|jd || |j rt d |j d || |jr|rdSt d |jd |||j |j<||_ ||t|tr|j D]}||t|trT|j D]:}t|tr#|rt d ;dSdS) zAdd a child (DF/EF) to this DF. Args: child: The new DF/EF to be added ignore_existing: Ignore, if file with given FID already exists. Old one will be kept. zExpected a File instance)minlenmaxlenzFile name %s is not a valid fidzFile name %s is a reserved namezFile fid %s is a reserved fidNzFile with given fid z already exists in zFile with given sfid zFile with given name z1TODO: implement recursive service -> file mapping)r/rrrr%r1r'rrrlookup_file_by_sfidr&lookup_file_by_namer)rr*rr)r5rrrgcs r6r3zCardDF.add_filefsa %** 8677 7ei!444 N>%)LMM M :0 0 0>%*MNN N 9. . .< JKK K 9 % % *AFDDQSS S  # #EJ / / U*BG***ddSUU U  # #EJ / / U *BG***ddSUU U#( ei   &&& eV $ $ f^**,, f f''***a((fj//11ff%b&11f!00f&01d&e&e e f f f fr8rc<|D]}|||dS)zAdd a list of child (DF/EF) to this DF Args: children: List of new DF/EFs to be added ignore_existing: Ignore, if file[s] with given FID already exists. Old one[s] will be kept. N)r3)r5rrrs r6 add_fileszCardDF.add_filess4 2 2E MM% 1 1 1 1 2 2r8r?cJt|}|gksd|vr6|d|jD|gksd|vr6|d|jD|S)Return a dict of {'identifier': File} that is selectable from the current DF. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing all selectable items. Key is identifier (string), value a reference to a CardFile (or derived class) instance. rdc,i|]}|j |j|Srr%.0xs r6 z*CardDF.get_selectables..s#KKKaQUKKKKr8rec,i|]}|j |j|Srr'rs r6rz*CardDF.get_selectables..s#MMMqafMMMMr8)rrrrfrrr5rhrirs r6rrzCardDF.get_selectablessww&&u-- B;;&E// KKKK4=+?+?+A+AKKK L L L B;;(e++ KKMMDM,@,@,B,BMMM N N N r8r'cr|dS|jD]}|jr|j|kr|cSdS)z.Find a file with given name within current DF.N)rrr')r5r'rTs r6rzCardDF.lookup_file_by_namesL <4%%''  Av !&D..tr8r&c|dS|jD]+}|jtt |kr|cS,dS)z7Find a file with given short file ID within current DF.N)rrr&rr)r5r&rTs r6rzCardDF.lookup_file_by_sfidsU <4%%''  AvSYY''(tr8r%c2||jvr |j|SdS)z1Find a file with given file ID within current DF.N)r)r5r%s r6lookup_file_by_fidzCardDF.lookup_file_by_fids! $-  =% %tr8F)rrrrr r rr7r=rrrrr3rrdictrrrrrrr __classcell__rs@r6r*r*;saa,--       .- #####.....      &f&fh&f&f&f&f&fP22(8"42t2222%'4$ (8:L (8:Lchx.@r8r*cveZdZdZfdZdZd dZdZgfdeffd Z gfdefd Z d e e de fd ZxZS)r_z-MF (Master File) in the smart card filesystemc |dd|dd|dd||d<tjdi|i|_dS) Nr%r$r'r#r(zMaster File (directory root)r)r)rrr7 applicationsrs r6r7zCardMF.__init__s{%(((&$'''&"@AAAx""6"""r8cd|jzS)NzMF(%s)rr<s r6r=zCardMF.__str__s48$$r8appr0ct|tstd|j|jvrt d|jz||j|j<||_dS)zAdd an Application to the MFzExpected an ADF instancezAID %s already existsN)r/r0raidrr1r))r5rs r6add_application_dfzCardMF.add_application_dfsc#w'' 8677 7 7d' ' '4@AA A%(#'" r8cNt|jS)z#Get list of completions (AID names))rtrrr<s r6 get_app_nameszCardMF.get_app_namessD%,,..///r8r?ct|}||||S)r)rrrrfrprs r6rrzCardMF.get_selectablessAww&&u-- D,,U33444 r8c i}|gksd|vr6|d|jD|gksd|vr6|d|jD|S)zGet applications by AID + nameAIDSci|] }|j| Sr)rrs r6rz.CardMF.get_app_selectables..sFFFaFFFr8ANAMESc,i|]}|j |j|Srrrs r6rz.CardMF.get_app_selectables..s#IIIq!&IIIIr8)rfrr)r5rhris r6rpzCardMF.get_app_selectabless B;;&E// KKFF4+<+C+C+E+EFFF G G G B;;(e++ KKIID$5$<$<$>$>III K K K r8rycd|s|S|}|r||S|S)a\Decode the response to a SELECT command. This is the fall-back method which automatically defers to the standard decoding method defined by the card profile. When no profile is set, then no decoding is performed. Specific derived classes (usually ADF) can overload this method to install specific decoding. )r}r{)r5ryr+s r6r{zCardMF.decode_select_responsesC O""$$  11(;; ;Or8)rr0)rrrrr7r=rrrrrrprrobjectr{rrs@r6r_r_s77%%%000%'  4      )+tx}r8r_c\eZdZdZd dedeffd ZdZdefdZe d efd Z xZ S) r0z=ADF (Application Dedicated File) in the smart card filesystemFrhas_fsc tjdi|d|_||_||_|}|r||dSdS)Nr)rr7 applicationr2rrrWr)r5rrrrqrs r6r7zCardADF.__init__sw""6"""99;; [[]]  (  ! !$ ' ' ' ' ' ( (r8c2d|jr|jn|jzS)NzADF(%s)r'rr<s r6r=zCardADF.__str__s@DIIAAr8r>c0|jr |r|jS|jSr:rrAs r6rBzCardADF._path_elements" 9  9 8Or8rct|jtstd|jj||S)zb Export application specific parameters that are not part of the UICC filesystem. z.currently selected file is not of type CardADF)r/rr0rrrrs r6rzCardADF.export"sE %-w77 NLMM M".55guEEEr8r) rrrrrrr7r=rBrrrrs@r6r0r0 sGG((C(((((((BBB FFFF\FFFFFr8r0cReZdZdZdZededefdZd dZde fdZ d Z dS) JsonEditoraContext manager for editing a JSON-encoded EF value in an external editor. Writes the current JSON value (plus encode/decode examples as //-comments) to a temporary file, opens the user's editor, then reads the result back (stripping comment lines) and returns it as the context variable:: with JsonEditor(self._cmd, orig_json, ef) as edited_json: if edited_json != orig_json: ...write back... c>||_||_||_d|_dSr:)_cmd _orig_json_ef_file)r5cmd orig_jsonefs r6r7zJsonEditor.__init__7s" # r8textr?cddd|DS)z5Strip //-comment lines from text before JSON parsing. c3hK|]-}|d)|V.dS)z//N)lstrip startswith)rlines r6 z-JsonEditor._strip_comments..As>bb$4;;==C[C[\`CaCabbbbbbbr8)rD splitlines)rs r6_strip_commentszJsonEditor._strip_comments=s/yybb$//*;*;bbbbbbr8Ncg}dD]<}tt|j|d}|r||=|sdS|j}|g}|jr0|d|jd|jr|d|j| dd |d| d |D]}t|d kr5|d |d |d } } }| d| d|dn)|d |d } }| d|dtj | dtD]} | d| ddS)a6Append encode/decode test vectors as //-comment lines to an open file. The examples are taken from _test_de_encode and _test_decode class attributes (same source as the auto-generated filesystem documentation). The comment block is intentionally ignored on read-back by _strip_comments.)_test_de_encode _test_decodeN()z- z //  rz// Examples (ignored on save): rrVz // record z: z // file: rindentclsz// )getattrtyperextendrFr%rHupperr(writerDrRjsondumpsrr) r5 text_filevectorsattrvrpartstencoded record_nrdecodedrs r6_append_examples_as_commentsz'JsonEditor._append_examples_as_commentsCs 7 " "DTXd33A "q!!!  F X,,../ 6 0 LL.RV\\^^... / / / 7 ) LLbg ( ( (5#((5//555666:;;; 0 0A1vv{{./dAaD!A$G EY E E' E E EFFFF#$Q41 7G 7 7 7888 71+FFFQQSS 0 0d//// 0 0 0r8ctjdddd|_tj|j|jdt ||j|j |j |jj  t|jj d 5}tj ||cd d d S#1swxYwYnc#tj$rQ}|j d ||j d }|d vr |jcYd }~SYd }~nd }~wwxYw)a%Write JSON + examples to a temp file, run the editor, return parsed result. On JSONDecodeError the user is offered the option to re-open the file and fix the mistake interactively. The temp file is removed by __exit__() on success, or when the user declines to retry.pysim_z.jsonwF)prefixsuffixmodedeleterrTrNzInvalid JSON: z&Re-open file for editing? [y]es/[n]o: )yyes)tempfileNamedTemporaryFilerr dumprrrcloser run_editorr'openloadsrreadJSONDecodeErrorperror read_input)r5feanswers r6 __enter__zJsonEditor.__enter__as 069%III  $/4:a[IIII ))$*555  + I  1 1 1 +$*/3//F1:d&:&:16688&D&DEEFFFFFFFFFFFFFFFFF' + + +   !5!!5!5666--.VWW--?******.---- + +sCD 89C>1 D >DD DD E*AE%E*%E*cBtj|jjdSr:)osunlinkrr')r5argss r6__exit__zJsonEditor.__exit__ws $*/"""""r8)r?N) rrrrr7rrrrrr-r2rr8r6rr,s   ccccccc\c 0000<+6++++,#####r8rc@eZdZdZfdZfdZgfdeffd ZxZS)CardEFz,EF (Entry File) in the smart card filesystemc D||d<tjdi|dS)Nr%rrr7)r5r%rrs r6r7zCardEF.__init__~s/u ""6"""""r8cJdtzS)NzEF(%s)rrs r6r=zCardEF.__str__rr8r?cht|}|gksd|vr=|fdjjD|gksd|vr=|fdjjD|S)rrdc:i|]}|j |k|j|Srrrrr5s r6rz*CardEF.get_selectables..s0```aAE`VW[_V_V_V_V_V_r8rec:i|]}|j |k|j|Srrr:s r6rz*CardEF.get_selectables..s0bbbqQVbXY]aXaXaXaXaXar8)rrrrfr)rrrs` r6rrzCardEF.get_selectablessww&&u-- B;;&E// KK````4;+?+F+F+H+H``` a a a B;;(e++ KKbbbbDK,@,G,G,I,Ibbb c c c r8) rrrrr7r=rrrrrs@r6r4r4{s66#####.....%'4r8r4c *eZdZdZedGddeZ ddeded ed ed ed e f fd Z de de fdZ dede fdZddeedeefdZdde deede fdZdde deedefdZedefdZxZS) TransparentEFzTransparent EF (Entry File) in the smart card filesystem. A Transparent EF is a binary file with no formal structure. This is contrary to Record based EFs which have [fixed size] records that can be individually read/updated.zTransparent EF CommandscZeZdZdZejZedddedede j ed Z ejZ e d e d d e de de j e dZejZeddde j edZejZed e d d edede j edZejZedededde j edZdZdS)TransparentEF.ShellCommandsz,Shell commands specific for transparent EFs. --oneline store_true.No JSON pretty-printing, dump as a single lineactionhelpHEXSTR$Hex-string of encoded data to decoderrEc|jjj|j}|j||jdSzHDecode command-line provided hex-string as if it was read from the file.N)rrr decode_hexrF poutput_jsononeliner5optsdatas r6 do_decode_hexz)TransparentEF.ShellCommands.do_decode_hexs@9?0;;DKHHD I " "4 6 6 6 6 6r8z--offsetrzByte offset for start of readrdefaultrEz--lengthzNumber of bytes to readc|jj|j|j\}}|j|dS)z&Read binary data from a transparent EFN)rr read_binarylengthoffsetpoutputr5rOrP_sws r6do_read_binaryz*TransparentEF.ShellCommands.do_read_binarysA)/55dk4;OOKT3 I  d # # # # #r8c|jj\}}|j||jdS)z(Read + decode data from a transparent EFN)rrread_binary_decrLrMrYs r6do_read_binary_decodedz2TransparentEF.ShellCommands.do_read_binary_decodeds=)/99;;KT3 I " "4 6 6 6 6 6r8DATA Data bytes (hex format) to writec|jj|j|j\}}|r|j|dSdS)z'Update (Write) data of a transparent EFN)rr update_binaryr_rWrXrYs r6do_update_binaryz,TransparentEF.ShellCommands.do_update_binarysS)/77 4;OOKT3 ( !!$''''' ( (r8 --json-pathz1JSON path to modify specific element of file only$Abstract data (JSON format) to writerEcd|jrO|jj\}}t ||jt j|jnt j|j}|jj|\}}|r|j |dSdS)z0Encode + Update (Write) data of a transparent EFN) json_pathrrr]rr r%r_update_binary_decrLr5rO data_jsonrZrPs r6do_update_binary_decodedz4TransparentEF.ShellCommands.do_update_binary_decodeds~ 2#'9?#B#B#D#D Cy$.#z$)446666!Jty11 )/;;IFFKT3 - &&t,,,,, - -r8c|jj\}}|jjj}t |j||5}||kr|jdn>|jj|\}}|r|j|ddddS#1swxYwYdS)z=Edit the JSON representation of the EF contents in an editor.!Data not modified, skipping writeN)rrr]rrrXrirL)r5_optsrrZr edited_jsonrPs r6do_edit_binary_decodedz2TransparentEF.ShellCommands.do_edit_binary_decodeds#y>>@@ Y.BDIy"55 5)++I%%&IJJJJ"&)/"C"CK"P"PKT35 ..t444  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5s A B66B:=B:N)rrrrargparseArgumentParserdec_hex_parser add_argumentrcmd2with_argparserrQread_bin_parserrr[read_bin_dec_parserr^upd_bin_parserrcupd_bin_dec_parserrrlrqrr8r6rr?s::0022##K )Y $ [ [ [##H9Ci#jjj  ^ , , 7 7 - , 7 2(133$$ [!:Y % [ [ [$$ [/H % J J J  _ - - $ $ . - $ 6h577((\.^ ) ` ` `  0 1 1 7 7 2 1 7 1022## [!:Y $ [ [ [##FAc#ddd  ^ , , ( ( - , ( 5X466'' C-` ( b b b''5['\\\  / 0 0 - - 1 0 - 5 5 5 5 5r8rNrVNr%r&r'r(r)sizec tjd|||||d|d|_d|_||_|g|_dSas Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy size : tuple of (minimum_size, recommended_size) r%r&r'r(r)Nr)rr7 _construct_tlvr}rr4 r5r%r&r'r(r)r}rrs r6r7zTransparentEF.__init__sb [St$T&[[TZ[[[  #11334r8 raw_bin_datar?ct|dd}t|r ||St|dd}t|r|t|S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_bin() or _decode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data Returns: abstract_data; dict representing the decoded data _decode_binN _decode_hexraw) rcallablerrrrinspectisclassfrom_tlvto_dicthex)r5rmethodrs r6 decode_binzTransparentEF.decode_bins}d33 F   (6,'' '}d33 F   -6#l++,, , ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8 raw_hex_datact|dd}t|r ||St|}t|dd}t|r ||S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_bin() or _decode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data Returns: abstract_data; dict representing the decoded data rNrr rrr rrrrrrrrr5rrrrs r6rKzTransparentEF.decode_hexs}d33 F   (6,'' '<(( }d33 F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8 total_lenc||S|jdS|jd |jdS|jd |jdSdS)z'Get the size (total length) of the fileNrVr)r}r5rs r6 __get_sizezTransparentEF.__get_size3sT    9 4 9Q< #9Q<  9Q< #9Q< tr8 abstract_dataclt|dd}t|r ||||St|dd}t|r-t||||S|jr+t |j|d||iS|jr]tj|jr|n|j}| || Std|z)a Encode abstract representation into raw (binary) data. A derived class would typically provide an _encode_bin() or _encode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (file size) Returns: binary encoded data _encode_binNr _encode_hexr0%s encoder not yet implemented. Patches welcome.) rr_TransparentEF__get_sizer rrrrr from_dictto_tlvNotImplementedErrorr5rrrrs r6 encode_binzTransparentEF.encode_binFs1}d33 F   Q6-T__Y5O5OPPP P}d33 F   Vvvm9S9STTTUU U ? o"4?MKRVRaRabkRlRlCmnn n 9 &ty99H tyA KK & & &88:: ! > EGG Gr8c t|dd}t|r ||||St|dd}t|r/||||}t|S|jr8tt |j|d||iS|jrjtj|jr|n|j}| |t| Std|z)aEncode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_bin() or _encode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (file size) Returns: hex string encoded data rNrrrr) rrrrrrrrrrrr)r5rrrrrs r6 encode_hexzTransparentEF.encode_hexbsC}d33 F   Q6-T__Y5O5OPPP P}d33 F   %!6-T__Y=W=WXXXL|$$ $ ? rt TXTcTcdmTnTnGoppqq q 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8rc|dkr$td|zd}|r<|}|dtj|dt zz }n/|}|dt|dzz }|S)z Export the file contents of a TransparentEF. This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. transparentzTselected file has structure type '%s', expecting a file with structure 'transparent'zupdate_binary_decoded '%s' rrzupdate_binary %s ) selected_file_structurer1r]r r rrUrstrip)rr export_strresults r6rzTransparentEF.exports  ( ( * *m ; ;s"::<<=>> >  B**,,F 9DJvayVa>>> ? ?r8c|jj|j\}}|j||jdS)z0Read + decode a record from a record-oriented EFN)rrread_record_decrrLrMrYs r6do_read_record_decodedz/LinFixedEF.ShellCommands.do_read_record_decodedsA)/99$.IIKT3 I " "4 6 6 6 6 6r8c:|jj}tdd|zD]h}|jj|\}}t |dkrt |}nd}|jd||fzidS)z*Read all records from a record-oriented EFrVrrrN)rrselected_file_num_of_recrQrrRrrX)r5ro num_of_recrrPrZrs r6do_read_recordsz(LinFixedEF.ShellCommands.do_read_recordssAACCJq!j.11 ? ?"io99%@@ st99q== YYFF&F !!)ufo"=>>>>  ? ?r8c |jj}g}tdd|zD]9}|jj|\}}||:|j||jdS)z3Read + decode all records from a record-oriented EFrVN)rrrrQrrHrLrM)r5rOr data_listrrPrZs r6do_read_records_decodedz0LinFixedEF.ShellCommands.do_read_records_decodedsAACCJIq!j.11 ' '"io==eDD s  &&&& I " "9dl ; ; ; ; ;r8r_r`c|jj|j|j\}}|r|j|dSdS)z+Update (write) data to a record-oriented EFN)rr update_recordrr_rXrYs r6do_update_recordz)LinFixedEF.ShellCommands.do_update_recordsS)/77 RRKT3 ( !!$''''' ( (r8rdz3JSON path to modify specific element of record onlyrPrerfc||jrU|jj|j\}}t ||jt j|jnt j|j}|jj |j|\}}|r|j |dSdS)z4Encode + Update (write) data to a record-oriented EFN) rhrrrrrr r%rPupdate_record_decrXrjs r6do_update_record_decodedz1LinFixedEF.ShellCommands.do_update_record_decodeds~ 2#'9?#B#B4>#R#R Cy$.#z$)446666!Jty11 )/;; ++KT3 ( !!$''''' ( (r8zNumber of record to be editedc|jj|j\}}|jjj}t |j||5}||kr|jdnD|jj|j|\}}|r|j|ddddS#1swxYwYdS)z8Edit the JSON representation of one record in an editor.rnN) rrrrrrrXrrL)r5rOrrZrrprPs r6do_edit_record_decodedz/LinFixedEF.ShellCommands.do_edit_record_decodeds  $y>>t~NN Y.BDIy"55 5)++I%%&IJJJJ"&)/"C"C #5#5KT35 ..t444 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sA&CC CN)rrrrrrrsrtrurrvrwrQread_rec_parserrrread_rec_dec_parserrread_recs_parserrread_recs_dec_parserrupd_rec_parserrupd_rec_dec_parserrredit_rec_dec_parserrrr8r6rrs;;0022##K )Y $ [ [ [##H9Ci#jjj  ^ , , 7 7 - , 7 2(133$$ J8n % p p p$$ j/L % N N N  _ - - ? ? . - ?6h577((\.^ ) ` ` `(( j/L ) N N N  0 1 1 7 7 2 1 7 38244  - . . ? ? / . ? 7x688))+l/_ * a a a  1 2 2 < < 3 2 <1022## j/L $ N N N##FAc#ddd  ^ , , ( ( - , ( 5X466'' C-b ( d d d'' j/L ( N N N''5['\\\  / 0 0 ( ( 1 0 (6h577(( j/N ) P P P  0 1 1 5 5 2 1 5 5 5r8rNr|Fr%r&r'r(r)rec_lenleftpadc tjd|||||d|||_||_|g|_d|_d|_dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy rec_len : Tuple of (minimum_length, recommended_length) leftpad: On write, data must be padded from the left to fit physical record length rNr)rr7rrrr4rr) r5r%r&r'r(r)rrrrs r6r7zLinFixedEF.__init__sg [St$T&[[TZ[[[  #11334 r8rVrrr?ct|dd}t|r |||St|}t|dd}t|r |||S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data _decode_record_hexNr_decode_record_binrr)r5rrrrrs r6rzLinFixedEF.decode_record_hex(s3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8rct|dd}t|r |||St|}t|dd}t|r |||S|jrt |j|S|jr]t j|jr|n|j}||| Sd|iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data rNrrr) rrrrrrrrrr)r5rrrrrs r6decode_record_binzLinFixedEF.decode_record_binDs3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8rc||S|jdS|jd |jdS|jd |jdSdS)0Get the length (total length) of the file recordNrVrrrs r6 __get_rec_lenzLinFixedEF.__get_rec_len`sT    < 4 <? &<? " <? &<? "tr8rc t|dd}t|r!|||||St|dd}t|r0|||||}t|S|jr8tt |j|d||iS|jrjtj|jr|n|j}| |t| Std|z)aeEncode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data record_nr : record number (1 for first record, ...) total_len : expected total length of the encoded data (record length) Returns: hex string encoded data _encode_record_hexNrr_encode_record_binrr) rr_LinFixedEF__get_rec_lenrrrrrrrrr)r5rrrrrrs r6encode_record_hexzLinFixedEF.encode_record_hexssP3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   %!6-9RVRdRdenRoRopppL|$$ $ ? ut TXTfTfgpTqTqGrsstt t 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8c pt|dd}t|r!|||||St|dd}t|r.t|||||S|jr+t |j|d||iS|jr]tj|jr|n|j}| || Std|z)a]Encode abstract representation into raw (binary) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data record_nr : record number (1 for first record, ...) total_len : expected total length of the encoded data (record length) Returns: binary encoded data rNrrrr) rrrr rrrrrrrr)r5rrrrrs r6encode_record_binzLinFixedEF.encode_record_bins=3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   nvvmydN`N`ajNkNklllmm m ? p"4?MKPTPbPbclPmPmCnoo o 9 &ty99H tyA KK & & &88:: ! > EGG Gr8rcb|dkr<|dkr$td|zd}|}|rtd|dzD]u}|r?||}|d|t j|dtfzz }C||}|d |t|dfzz }vnd} |r?||}|d|t j|dtfzz }n2||}|d |t|dfzz }|#t$r}|j d krYd }~nYd }~nd }~wwxYw|dz}| S) z Export the file contents of a LinFixedEF (or a CyclicEF). This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. linear_fixedcycliczaselected file has structure type '%s', expecting a file with structure 'linear_fixed' or 'cyclic'rrVzupdate_record_decoded %d '%s' rrzupdate_record %d %s T9402N) rr1rrQrr r rrrr sw_actualr)rrrrrrr+s r6rzLinFixedEF.exports&  ( ( * *n < <A^A^A`A`dlAlAlA"::<<=>> > 3355  1j1n-- R RR"22155F#D4:V\]^V_epKqKqKqGr#rsJJ"..q11F#:aVAY=P#PQJJ  RA  V!&!6!6q!9!9"'HAtzZ`abZcitOuOuOuKv'vw !&!2!21!5!5"'>!SPQ^^AT'TU G ${f,,-,,,,E "!!!s;A3E00 F: FF)NNNNr|F)rVr:)rrrrr r rrrr*rrr7rrrrrrrrrrrrs@r6rrs?? 566y5y5y5y5y5 y5y576y5vRV]bCs3!&);?VZ&++c+c+$++++8%i%C%D%%%%8x} &GGtGGPXY\P]GilGGGG<GGtGGQYZ]Q^GjsGGGG:-"-"-"-"\-"-"-"-"-"r8rc BeZdZdZ d dededededed ef fd ZxZS) CyclicEFz3Cyclic EF (Entry File) in the smart card filesystemNr|r%r&r'r(r)rc Htjd||||||d|dS)N)r%r&r'r(r)rrr6) r5r%r&r'r(r)rrrs r6r7zCyclicEF.__init__s7lSt$T&Zalleklllllr8r) rrrrrr*rr7rrs@r6rrs==im!*mmCmsmm3m_emmmmmmmmmmmr8rceZdZdZ ddededededed eed effd Z d ed e fdZ de d e fdZ ddeed eefdZdde deed efdZdde deed e fdZde fdZd efdZxZS) TransRecEFaTransparent EF (Entry File) containing fixed-size records. These are the real odd-balls and mostly look like mistakes in the specification: Specified as 'transparent' EF, but actually containing several fixed-length records inside. We add a special class for those, so the user only has to provide encoder/decoder functions for a record, while this class takes care of split / merge of records. Nr|r%rr&r'r(r)r}c Vtjd||||||d|||_dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy rec_len : Length of the fixed-length records within transparent EF size : tuple of (minimum_size, recommended_size) )r%r&r'r(r)r}Nr)rr7r) r5r%rr&r'r(r)r}rrs r6r7zTransRecEF.__init__s> fSt$T&W[ff_efff r8rr?c,t|dz|krd|iSt|dd}t|r ||St |}t|dd}t|r ||S|jrt |j|S|jr]tj |jr|n|j}| || Sd|iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data Returns: abstract_data; dict representing the decoded data rrrNr) rR_TransRecEF__get_rec_lenrrr rrrrrrrrs r6rzTransRecEF.decode_record_hexs |   !D$6$6$8$8 8 8<( (3T:: F   (6,'' '<(( 3T:: F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8rc@t||krdt|iSt|dd}t |r ||St|}t|dd}t |r ||S|jrt |j|S|jr]tj |jr|n|j}| || Sd|iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data Returns: abstract_data; dict representing the decoded data rrNr) rRrrrrrrrrrrr)r5rrrrs r6rzTransRecEF.decode_record_bin#s |  t1133 3 33|,,- -3T:: F   (6,'' '<(( 3T:: F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8rc*||S|jr|jSdS)rNrrs r6rzTransRecEF.__get_rec_lenCs)    < < tr8rc t|dd}t|r ||||St|dd}t|r-t||||S|jrEtt t |j|d||iS|jrjtj |jr|n|j}| |t| Std|z)a%Encode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (record length) Returns: hex string encoded data rNrrrr) rrrrrrrrrrrrrrs r6rzTransRecEF.encode_record_hexPsb3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? b{?4?M4?@R@RS\@]@]3^$`$`aabb b 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8c t|dd}t|r ||||St|dd}t|r-t||||S|jr8t t |j|d||iS|jr]tj |jr|n|j}| || Std|z)aEncode abstract representation into raw (binary) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (record length) Returns: binary encoded data rNrrrr) rrrr rrrrrrrrrrs r6rzTransRecEF.encode_record_binmsM3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? ]t 0;D EGG Gr8cfdtdtjD}fd|DS)Nc4g|]}||jzSrr)rrTrr5s r6 z*TransRecEF._decode_bin..s?FFFq4</0FFFr8rc:g|]}|Sr)rr:s r6rz*TransRecEF._decode_bin..s':::a&&q)):::r8)rQrRr)r5rchunkss`` r6rzTransRecEF._decode_binsiFFFFF C $5$5t|DDFFF::::6::::r8c Nfd|D}d|S)Nc fg|]-}|dd.S)rNr)rget)rrrr5s r6rz*TransRecEF._encode_bin..s<nnn[\$(( ;PT8U8U(VVnnnr8r8)rD)r5rrrs` ` r6rzTransRecEF._encode_bins3nnnnn`mnnnxxr8rr:)rrrrrrrr*rr7rrrrrrrrbytesrrrs@r6rrs`d?H  C # S s Y\ !&) 8<       %c %d % % % %D%i%D%%%%@  x}     GGtG GY\GGGG:GGtG GYbGGGG:; ;;;;  e        r8rc eZdZdZedGddeZ ddeded ed ed ed e f fd Z e de fdZ xZS)BerTlvEFaVBER-TLV EF (Entry File) in the smart card filesystem. A BER-TLV EF is a binary file with a BER (Basic Encoding Rules) TLV structure NOTE: We currently don't really support those, this class is simply a wrapper around TransparentEF as a place-holder, so we can already define EFs of BER-TLV type without fully supporting them.zBER-TLV EF CommandsceZdZdZejZedede j edZ dZ ejZ e dede ded e j e d ZejZedede j ed Zd Zd S)BerTlvEF.ShellCommandsz(Shell commands specific for BER-TLV EFs.TAGz BER-TLV Tag of value to retrieverHc|jj|j\}}|j|dS)z&Retrieve (Read) data from a BER-TLV EFN)rr retrieve_datar rXrYs r6do_retrieve_dataz'BerTlvEF.ShellCommands.do_retrieve_datas=)/77AAKT3 I  d # # # # #r8cv|jj}|j|dS)z)List tags available in a given BER-TLV EFN)rr retrieve_tagsrX)r5rotagss r6do_retrieve_tagsz'BerTlvEF.ShellCommands.do_retrieve_tagss39?0022D I  d # # # # #r8zBER-TLV Tag of value to setrPr`c|jj|j|j\}}|r|j|dSdS)z0Set (Write) data for a given tag in a BER-TLV EFN)rrset_datar rPrXrYs r6 do_set_dataz"BerTlvEF.ShellCommands.do_set_datasS)/2248TYGGKT3 ( !!$''''' ( (r8c|jj|jd\}}|r|j|dSdS)z+Delete data for a given tag in a BER-TLV EFN)rrrr rXrYs r6do_delete_dataz%BerTlvEF.ShellCommands.do_delete_datasQ)/2248TBBKT3 ( !!$''''' ( (r8c|jj}|D]"}|jj|d#dS)z!Delete all data from a BER-TLV EFN)rrrr)r5rOrtags r6 do_delete_allz$BerTlvEF.ShellCommands.do_delete_allsM9?0022D 4 4 ((d3333 4 4r8N)rrrrrrrsretrieve_data_parserrurrvrwrrset_data_parserrrdel_data_parserrrrr8r6rr s{666x688)) 'I * K K K  1 2 2 $ $ 3 2 $  $ $ $ 2(133$$ 'D % F F F$$V)Bd$eee  _ - - ( ( . - ( 2(133$$ 'D % F F F  _ - - ( ( . - (  4 4 4 4 4r8rNr|r%r&r'r(r)r}c tjd|||||d|d|_||_|g|_dSr)rr7rr}rr4rs r6r7zBerTlvEF.__init__s[ [St$T&[[TZ[[[ #11334r8rc|dkr$td|z|rtdd}|}|gkr|dz }n]|dz }|D]U}||}t t |d\}}}} |d|t|fzz }V|S) z Export the file contents of a BerTlvEF. This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. ber_tlvzPselected file has structure type '%s', expecting a file with structure 'ber_tlv'z6BerTlvEF encoder not yet implemented. Patches welcome.rz# empty file, no tagsz delete_all rzset_data 0x%02x %s ) rr1rrrrr rr) rrrrrrrlval remainders r6rzBerTlvEF.exports  ( ( * *i 7 7o"::<<=>> >  `%&^__ _ ""$$ 2:: 1 1JJ . (J G G,,Q//+;Cq NN+K+K(ai5CHH EF !!!r8r)rrrrr r rrr*rr7rrrrrs@r6r r s++011-4-4-4-4-4 -4-421-4^im'55C5s5535_e5555555 """"\"""""r8r sw_dataswc|D]G\}}||vr |||fcS|D]\}}t||r||fccSHdS)zInterpret a given status word. Args: sw_data : Hierarchical dict of status word matches sw : status word to match (string of 4 hex digits) Returns: tuple of two strings (class_string, description) N)itemsr)r&r' class_strswdictpatterndescrs r6 interpret_swr.s%]]__** 6 <<vbz* * * *$llnn * *NGUG$$ *!5)))))) * * 4r8c\eZdZdZd deededefdZdZ dZ e d e fd Z dS) CardApplicationzqA card application is represented by an ADF (with contained hierarchy) and optionally some SW definitions.Nadfrr'c|r|}||_||_|pi|_|jr!|p |jj|_||j_dS||_dS)zc Args: adf : ADF name sw : Dict of status word conversions N)r2r'r1r'rr)r5r'r1rr's r6r7zCardApplication.__init__sg  ))++C ( 8 *dhlDH#'DH DHHHr8cd|jzS)NzAPP(%s)rr<s r6r=zCardApplication.__str__#sDI&&r8c,t|j|S)zInterpret a given status word within the application. Args: sw : Status word as string of 4 hex digits Returns: Tuple of two strings )r.r')r5r's r6r.zCardApplication.interpret_sw&sDGR(((r8rc0dt|jzS)z Export application specific parameters, in the form of commandline script. (see also comment in the export method of class "CardFile") z# %s has no exportable featuresrrs r6rzCardApplication.export1s 13u7J3K3KKKr8)NNN)rrrrrr0rrr7r=r.rrrrr8r6r0r0 s(7"3QU$''' ) ) )LLLL\LLLr8r0ceZdZdZgZeejd dZede de fdZ e de ddfdZ d S) CardModelzA specific card model, typically having some additional vendor-specific files. All you need to do is to define a sub-class with a list of ATRs or an overridden match method.rs RuntimeStatecdS)z/Add model specific files to given RuntimeState.Nr)rr8s r6rzCardModel.add_filesAsr8sccr?c"|}|jD] }||krtd|jdS!t |d}|jD]5}t |d}||krtd|jdS6dS)z&Test if given card matches this model.zDetected CardModel:ThbF)get_atr_atrsprintrr)rr;card_atratr card_atr_hbatr_hbs r6matchzCardModel.matchFs;;==9  Ch+S\:::tt#8,,T2 9  C!#&&t,F$$+S\:::tt%ur8ctD],}||r||-dS)zCheck if any of the CardModel sub-classes 'match' the currently inserted card (by ATR or overriding the 'match' method). If so, call their 'add_files' method.N)r7__subclasses__rEr)r;r8ms r6apply_matching_modelszCardModel.apply_matching_modelsWsK ))++  Awws||  B  r8N)r8r9)rrrrr? classmethodabcabstractmethodrrrrErrIrr8r6r7r7;s E>>>[>D[  ?    \   r8r7ceZdZdZdeeeeeeffdZdefdZ defdZ ddde fdZ d Z d Zd Zdd Zddde fd ZdS)Pathz%Representation of a file-system path.pct|tr|d}n6t|r't|dtr d|D}d|D|_dS)Nr"rcg|]}d|zS)z%04xrrs r6rz!Path.__init__..hs'''!'''r8c6g|]}|Sr)rrs r6rz!Path.__init__..js ***1QWWYY***r8)r/rsplitrRrrt)r5rOs r6r7z Path.__init__cst a   ( AA VV ( 1Q4-- (''Q'''A***** r8r?c6d|jS)Nr")rDrtr<s r6r=z Path.__str__lsxx """r8c&dt|zS)NzPath(%s))rr<s r6__repr__z Path.__repr__osSYY''r8otherc"|j|jkSr:rtr5rWs r6__eq__z Path.__eq__rsyEJ&&r8c|j|Sr:rY)r5rTs r6 __getitem__zPath.__getitem__usy|r8c*t|jSr:rRrtr<s r6__len__z Path.__len__xs49~~r8ct|tr |j|z}n0t|tr|j|jz}n |j|gz}t|Sr:)r/rtrN)r5ar#s r6__add__z Path.__add__{s[ a    A AA 4   AF"AA QCAAwwr8ct|jr+|jddvrt|jddS|S)z?Return a path relative to MF, i.e. without initial explicit MF.r)r#3F00rVN)rRrtrNr<s r6relative_to_mfzPath.relative_to_mfs? ty>> 'diln<< !"" && & r8ct|jt|jkrdS|jdt|j|jkrdSdS)z6Is this instance a parent of the given other instance?FNTr_rZs r6 is_parentzPath.is_parentsL ty>>S__ , ,5 :os49~~o &$) 3 34ur8N)r?rN)rrrrr rrrr7r=rVrr[r]r`rcrfrhrr8r6rNrNas//+%T#YS 9:++++#####(#(((('F't'''' v$r8rN)Artypingrrrrrrr rrrr rKrr/rvr r smartcard.utilr osmocom.utilsr rrrrrrr osmocom.tlvrosmocom.constructrrr pySim.utilsrrpySim.jsonpathrpySim.commandsrpySim.exceptionsrrrrrr*r_r0rr4r=rrrr rrr.r0ABCr7rNrr8r6rssz2FEEEEEEEEEEEEEEEEE  22222222""""""eeeeeeeeeeeeeeeeeeee((((((KKKKKKKKKK........))))))******)))))) T#Yc3h78 S(3-  ALALALALALALALALHEEEEEXEEEPFFFFFVFFFRFFFFFfFFF@L#L#L#L#L#L#L#L#^X:x"x"x"x"x"Fx"x"x"vI"I"I"I"I"I"I"I"X mmmmmzmmmj j j j j j j j Za"a"a"a"a"va"a"a"H$C(*L*L*L*L*L*L*L*L\# # # # # # # # L//////////r8