)g dZddlmZmZmZmZmZmZmZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZmZddlmZddlmZmZmZmZmZmZmZmZddlmZddlmZm Z m!Z!dd l"m#Z#dd l$m%Z%dd l&m'Z'dd l(m)Z)ee*ee*ee*d ffZ+ee*ee*fZ,GddZ-Gdde-Z.Gdde.Z/Gdde.Z0Gdde-Z1Gdde1Z2Gdde1Z3Gdde3Z4Gdde2Z5Gd d!e1Z6d"e7d#e8fd$Z9Gd%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)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$r4s r5__str__zCardFile.__str__]s 9 9 8Or7 prefer_namereturnc0|r|jr|jS|jSr9r:r4r=s r5 _path_elementzCardFile._path_elementcs"  49 9 8Or7TcRd||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_pathr@s r5fully_qualified_path_strz!CardFile.fully_qualified_path_stris$ xx11+>>???r7c|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(rDrAappend)r4r=retelems r5rDzCardFile.fully_qualified_pathqsh ; 4;$..+22;??CCC!!+..   JJt    r7c|jr%|j|kr|j}ng}|r|||S)zLReturn fully qualified path to file as list of CardFile instance references.)r(fully_qualified_path_fobjrG)r4rHs r5rKz"CardFile.fully_qualified_path_fobjsQ ; 4;$..+7799CCC   JJt    r7targetcd}||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.r/) inter_pathis r5 clip_pathz0CardFile.build_select_path_to..clip_paths^eAs:7788 * *jmW55*%abb>)))* r7rN)get_mfrKreverserGrPrQ) r4rLrT cur_fqpath target_fqpathrRcerStete2s r5build_select_path_tozCardFile.build_select_path_tos*     V]]__ $ $8O3355 88::   5 5B   b ! ! !1c-00233 5 5"1%88,QqSTT2//"))#....$9Z^4444444  5tr7CardMFc|jdS|}|jr$|j|kr|j}|jr |j|ktt|S)z(Return the MF (root) of the file system.N)r(rr^)r4nodes r5rVzCardFile.get_mfsY ; 4k dkT11;Dk dkT11FD!!!r7aliasci}|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&r4raflagsselss r5_get_self_selectableszCardFile._get_self_selectabless  ' KK & & & 8 *"% KK4( ) ) ) 9 +%2++U):): KKD) * * * r7ci}|jr |j|kr|S|r|||ji|jjr0|gksd|vr&||jj|ji|jjr0|gksd|vr&||jj|ji||jd||S)Nrcrd)r(rer$r&_get_parent_selectablesrfs r5rkz CardFile._get_parent_selectabless{ dkT11K  . KK , - - - ;? 8 v KK$+6 7 7 7 ;  9"E0A0A KK)4;7 8 8 8 DK77eDDEEE r7ci}|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 PARENTrr")rg)rirerkrVget_app_selectables)r4rgrhmfs r5get_selectableszCardFile.get_selectabless B;;&E//--c599D B;;(e++ KK44T5AA B B B B;;$%--B A B4454AABBB B222??@@@ r7c||}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. )rqlistkeyssort)r4rgrhsel_keyss r5get_selectable_nameszCardFile.get_selectable_namess>##E** $$ r7data_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)r4rxs r5rzzCardFile.decode_select_responses1 ; @;55h?? ? @ @r7cb|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 hirarchy that has a profile assigned N)r*r( get_profiler;s r5r|zCardFile.get_profile s; < <  ; -;**,, ,tr7servicesc,|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.intrstupler0)r4r}ss r5should_exist_for_servicesz"CardFile.should_exist_for_servicess < 4 dlC ( ( ,<8+ + dlD ) ) \  ==44!5 dlE * * \ ! !H}} 55%4KLLLr7as_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 (" "), where the last commandline shall have no line break at the end (e.g. "update_record 1 112233 update_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 r5exportzCardFile.export.s13u7J3K3KKKr7)NNNNNNN)T)__name__ __module__ __qualname____doc__RESERVED_NAMES RESERVED_FIDSrrCardFileServicer6r<boolrArErrDrKr]rVrrirkrqrwrzr|rr staticmethodrr7r5rr6s,++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\LLLr7rc&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)rrrrr7r5 ShellCommandsr=s r7rc t|tsd|vrtdtjdi|i|_|g|_i|_dS)Nr$zfid is mandatory for all DFr) r.r/ TypeErrorsuperr6childrenrr3files_by_servicer4kwargs __class__s r5r6zCardDF.__init__Asx$(( ?F"" =>>>""6""" #11334 "r7cJdtzS)NzDF(%s)rr<r4rs r5r<zCardDF.__str__K577??,,--r7c|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 setdefaultrGrsrr0)r4childr,s r5_add_file_serviceszCardDF._add_file_servicesNs}  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 r7c|jrdS|jD].}t|tr|rdS/dS)NT)r,rvaluesr.r) _has_service)r4cs r5rzCardDF._has_service]sd < 4%%''  A!V$$ >>## 44  r7Frignore_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$r0r&rrrlookup_file_by_sfidr%lookup_file_by_namer(rr)rr)r4rrrgcs r5r2zCardDF.add_fileesa %** 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 fr7rc<|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)r2)r4rrrs r5 add_fileszCardDF.add_filess4 2 2E MM% 1 1 1 1 2 2r7r>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. rcc,i|]}|j |j|Srr$.0xs r5 z*CardDF.get_selectables..s#KKKaQUKKKKr7rdc,i|]}|j |j|Srr&rs r5rz*CardDF.get_selectables..s#MMMqafMMMMr7)rrqrerrr4rgrhrs r5rqzCardDF.get_selectablessww&&u-- B;;&E// KKKK4=+?+?+A+AKKK L L L B;;(e++ KKMMDM,@,@,B,BMMM N N N r7r&cr|dS|jD]}|jr|j|kr|cSdS)z.Find a file with given name within current DF.N)rrr&)r4r&rSs r5rzCardDF.lookup_file_by_namesL <4%%''  Av !&D..tr7r%c|dS|jD]+}|jtt |kr|cS,dS)z7Find a file with given short file ID within current DF.N)rrr%rr)r4r%rSs r5rzCardDF.lookup_file_by_sfidsU <4%%''  AvSYY''(tr7r$c2||jvr |j|SdS)z1Find a file with given file ID within current DF.N)r)r4r$s r5lookup_file_by_fidzCardDF.lookup_file_by_fids! $-  =% %tr7F)rrrrr r rr6r<rrrrr2rrdictrqrrrrr __classcell__rs@r5r)r):saa,--       .- #####.....      &f&fh&f&f&f&f&fP22(8"42t2222%'4$ (8:L (8:Lchx.@r7r)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)rrr6 applicationsrs r5r6zCardMF.__init__s{%(((&$'''&"@AAAx""6"""r7cd|jzS)NzMF(%s)rr;s r5r<zCardMF.__str__s48$$r7appr/ct|tstd|j|jvrt d|jz||j|j<||_dS)zAdd an Application to the MFzExpected an ADF instancezAID %s already existsN)r.r/raidrr0r()r4rs r5add_application_dfzCardMF.add_application_dfsc#w'' 8677 7 7d' ' '4@AA A%(#'" r7cNt|jS)z#Get list of completions (AID names))rsrrr;s r5 get_app_nameszCardMF.get_app_namessD%,,..///r7r>ct|}||||S)r)rrqrerors r5rqzCardMF.get_selectablessAww&&u-- D,,U33444 r7c i}|gksd|vr6|d|jD|gksd|vr6|d|jD|S)zGet applications by AID + nameAIDSci|] }|j| Sr)rrs r5rz.CardMF.get_app_selectables..sFFFaFFFr7ANAMESc,i|]}|j |j|Srrrs r5rz.CardMF.get_app_selectables..s#IIIq!&IIIIr7)rerr)r4rgrhs r5rozCardMF.get_app_selectabless B;;&E// KKFF4+<+C+C+E+EFFF G G G B;;(e++ KKIID$5$<$<$>$>III K K K r7rxcd|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|rz)r4rxr*s r5rzzCardMF.decode_select_responsesC O""$$  11(;; ;Or7)rr/)rrrrr6r<rrrrqrorrobjectrzrrs@r5r^r^s77%%%000%'  4      )+tx}r7r^c\eZdZdZd dedeffd ZdZdefdZe d efd Z xZ S) r/z=ADF (Application Dedicated File) in the smart card filesystemFrhas_fsc tjdi|d|_||_||_|}|r||dSdS)Nr)rr6 applicationr1rrrVr)r4rrrrprs r5r6zCardADF.__init__sw""6"""99;; [[]]  (  ! !$ ' ' ' ' ' ( (r7c2d|jr|jn|jzS)NzADF(%s)r&rr;s r5r<zCardADF.__str__s@DIIAAr7r=c0|jr |r|jS|jSr9rr@s r5rAzCardADF._path_elements" 9  9 8Or7rct|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.rr/rrrrs r5rzCardADF.export!sE %-w77 NLMM M".55guEEEr7r) rrrrrrr6r<rArrrrs@r5r/r/ sGG((C(((((((BBB FFFF\FFFFFr7r/c@eZdZdZfdZfdZgfdeffd ZxZS)CardEFz,EF (Entry File) in the smart card filesystemc D||d<tjdi|dS)Nr$rrr6)r4r$rrs r5r6zCardEF.__init__.s/u ""6"""""r7cJdtzS)NzEF(%s)rrs r5r<zCardEF.__str__2rr7r>cht|}|gksd|vr=|fdjjD|gksd|vr=|fdjjD|S)rrcc:i|]}|j |k|j|Srrrrr4s r5rz*CardEF.get_selectables..Bs0```aAE`VW[_V_V_V_V_V_r7rdc:i|]}|j |k|j|Srrrs r5rz*CardEF.get_selectables..Ds0bbbqQVbXY]aXaXaXaXaXar7)rrqrer(rrrs` r5rqzCardEF.get_selectables5sww&&u-- B;;&E// KK````4;+?+F+F+H+H``` a a a B;;(e++ KKbbbbDK,@,G,G,I,Ibbb c c c r7) rrrrr6r<rrqrrs@r5rr+s66#####.....%'4r7rc *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 decodetyperc|jjj|j}|j||jdSzHDecode command-line provided hex-string as if it was read from the file.N)_cmdrr decode_hexr poutput_jsononeliner4optsdatas r5 do_decode_hexz)TransparentEF.ShellCommands.do_decode_hexWs@9?0;;DKHHD I " "4 6 6 6 6 6r7z--offsetrzByte offset for start of readrdefaultrz--lengthzNumber of bytes to readc|jj|j|j\}}|j|dS)z&Read binary data from a transparent EFN)rr read_binarylengthoffsetpoutputr4rr_sws r5do_read_binaryz*TransparentEF.ShellCommands.do_read_binarycsA)/55dk4;OOKT3 I  d # # # # #r7c|jj\}}|j||jdS)z(Read + decode data from a transparent EFN)rrread_binary_decrrr s r5do_read_binary_decodedz2TransparentEF.ShellCommands.do_read_binary_decodedms=)/99;;KT3 I " "4 6 6 6 6 6r7DATA Data bytes (hex format) to writec|jj|j|j\}}|r|j|dSdS)z'Update (Write) data of a transparent EFN)rr update_binaryrr r r s r5do_update_binaryz,TransparentEF.ShellCommands.do_update_binaryxsS)/77 4;OOKT3 ( !!$''''' ( (r7 --json-pathz1JSON path to modify specific element of file only$Abstract data (JSON format) to writercd|jrO|jj\}}t ||jt j|jnt j|j}|jj|\}}|r|j |dSdS)z0Encode + Update (Write) data of a transparent EFN) json_pathrrrrjsonloadsrupdate_binary_decrr4r data_jsonr rs r5do_update_binary_decodedz4TransparentEF.ShellCommands.do_update_binary_decodeds~ 2#'9?#B#B#D#D Cy$.#z$)446666!Jty11 )/;;IFFKT3 - &&t,,,,, - -r7c|jj\}}tjd5}d|z}t |d5}t j||ddddn #1swxYwY|j|t |d5}t j |}dddn #1swxYwY||kr|j d n>|jj |\}}|r|j |ddddS#1swxYwYdS) z=Edit the JSON representation of the EF contents in an editor.pysim_prefix%s/filewrindentNr!Data not modified, skipping write) rrrtempfileTemporaryDirectoryopenrdump run_editorloadr rr) r4_opts orig_jsonr dirnamefilename text_file edited_jsonrs r5do_edit_binary_decodedz2TransparentEF.ShellCommands.do_edit_binary_decodeds#y>>@@ Y,H=== 5$w.(C((>IIi1====>>>>>>>>>>>>>>> $$X...(C((7I"&)I"6"6K777777777777777)++I%%&IJJJJ"&)/"C"CK"P"PKT35 ..t444 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZD> A1% D>1A5 5D>8A5 9-D>&C; D>C D>C A"D>>EEN)rrrrargparseArgumentParserdec_hex_parser add_argumentrcmd2with_argparserrread_bin_parserrrread_bin_dec_parserrupd_bin_parserrupd_bin_dec_parserrr!r8rr7r5rrNs::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 5r7rNrUNr$r%r&r'r(sizec tjd|||||d|d|_d|_||_|g|_dSar Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, lik 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)rr6 _construct_tlvrDrr3 r4r$r%r&r'r(rDrrs r5r6zTransparentEF.__init__sb [St$T&[[TZ[[[  #11334r7 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) getattrcallablerrHrrIinspectisclassfrom_tlvto_dicthex)r4rKmethodts r5 decode_binzTransparentEF.decode_bins}d33 F   (6,'' '}d33 F   -6#l++,, , ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r7 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 rNNrMrO rPrQr rHrrIrRrSrTrUrVr4rZrWrKrXs r5rzTransparentEF.decode_hexs}d33 F   (6,'' '<(( }d33 F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r7 total_lenc||S|jdS|jd |jdS|jd |jdSdS)z'Get the size (total length) of the fileNrUr)rDr4r^s r5 __get_sizezTransparentEF.__get_sizesT    9 4 9Q< #9Q<  9Q< #9Q< tr7 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_hexr^0%s encoder not yet implemented. Patches welcome.) rPrQ_TransparentEF__get_sizer rHrrIrRrS from_dictto_tlvNotImplementedErrorr4rbr^rWrXs r5 encode_binzTransparentEF.encode_bins1}d33 F   Q6-T__Y5O5OPPP P}d33 F   Vvvm9S9STTTUU U ? o"4?MKRVRaRabkRlRlCmnn n 9 &ty99H tyA KK & & &88:: ! > EGG Gr7c 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 rfNrerdr^rg) rPrQrhrrHrrIrRrSrirjrk)r4rbr^rWrKrXs r5 encode_hexzTransparentEF.encode_hexsC}d33 F   Q6-T__Y5O5OPPP P}d33 F   %!6-T__Y=W=WXXXL|$$ $ ? rt TXTcTcdmTnTnGoppqq q 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr7rc|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' rclszupdate_binary %s ) selected_file_structurer0rrdumpsrrrstrip)rr export_strresults r5rzTransparentEF.export6s  ( ( * *m ; ;s"::<<=>> >  B**,,F 9DJvayVa>>> ? ?r7c|jj|j\}}|j||jdS)z0Read + decode a record from a record-oriented EFN)rrread_record_decrrrr s r5do_read_record_decodedz/LinFixedEF.ShellCommands.do_read_record_decodedvsA)/99$.IIKT3 I " "4 6 6 6 6 6r7c:|jj}tdd|zD]h}|jj|\}}t |dkrt |}nd}|jd||fzidS)z*Read all records from a record-oriented EFrUrrrN)rrselected_file_num_of_recrPrrQrr )r4r2 num_of_recrrr rs r5do_read_recordsz(LinFixedEF.ShellCommands.do_read_records~sAACCJq!j.11 ? ?"io99%@@ st99q== YYFF&F !!)ufo"=>>>>  ? ?r7c |jj}g}tdd|zD]9}|jj|\}}||:|j||jdS)z3Read + decode all records from a record-oriented EFrUN)rrrrPrrGrr)r4rr data_listrrr s r5do_read_records_decodedz0LinFixedEF.ShellCommands.do_read_records_decodedsAACCJIq!j.11 ' '"io==eDD s  &&&& I " "9dl ; ; ; ; ;r7rrc|jj|j|j\}}|r|j|dSdS)z+Update (write) data to a record-oriented EFN)rr update_recordrrr r s r5do_update_recordz)LinFixedEF.ShellCommands.do_update_recordsS)/77 RRKT3 ( !!$''''' ( (r7rz3JSON path to modify specific element of record onlyrrrc||jrU|jj|j\}}t ||jt j|jnt j|j}|jj |j|\}}|r|j |dSdS)z4Encode + Update (write) data to a record-oriented EFN) rrrrrrrrrupdate_record_decr rs r5do_update_record_decodedz1LinFixedEF.ShellCommands.do_update_record_decodeds~ 2#'9?#B#B4>#R#R Cy$.#z$)446666!Jty11 )/;; ++KT3 ( !!$''''' ( (r7zNumber of record to be editedc|jj|j\}}t jd5}d|z}t |d5}tj||ddddn #1swxYwY|j |t |d5}tj |}dddn #1swxYwY||kr|j d nD|jj |j|\}}|r|j |ddddS#1swxYwYdS) z8Edit the JSON representation of one record in an editor.r#r$r&r'rr(Nr*r+)rrrrr,r-r.rr/r0r1r rr) r4rr3r r4r5r6r7rs r5do_edit_record_decodedz/LinFixedEF.ShellCommands.do_edit_record_decodeds  $y>>t~NN Y,H=== 5$w.(C((>IIi1====>>>>>>>>>>>>>>> $$X...(C((7I"&)I"6"6K777777777777777)++I%%&IJJJJ"&)/"C"C #5#5KT35 ..t444 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZE A7+ E 7A; ;E >A; ?-E ,C  E  C E C A(E  EEN)rrrrr9r:r;r<rr=r>rread_rec_parserrrread_rec_dec_parserrread_recs_parserrread_recs_dec_parserrupd_rec_parserrupd_rec_dec_parserrredit_rec_dec_parserrrr7r5rrPs;;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 5r7rNrCFr$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, lik 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 pysical record length rGNr)rr6rrrr3rHrI) r4r$r%r&r'r(rrrrs r5r6zLinFixedEF.__init__sg [St$T&[[TZ[[[  #11334 r7rUrZ record_nrr>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_binrOr\)r4rZrrWrKrXs r5rzLinFixedEF.decode_record_hexs3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r7rKct|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 rNrrrO rPrQrrHrrIrRrSrTrU)r4rKrrWrZrXs r5decode_record_binzLinFixedEF.decode_record_bins3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r7r^c||S|jdS|jd |jdS|jd |jdSdS)0Get the length (total length) of the file recordNrUrrr`s r5 __get_rec_lenzLinFixedEF.__get_rec_lensT    < 4 <? &<? " <? &<? "tr7rbc 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_binr^rg) rPrQ_LinFixedEF__get_rec_lenrrHrrIrRrSrirjrk)r4rbrr^rWrKrXs r5encode_record_hexzLinFixedEF.encode_record_hex1sP3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   %!6-9RVRdRdenRoRopppL|$$ $ ? ut TXTfTfgpTqTqGrsstt t 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr7c 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 rNrrr^rg) rPrQrr rHrrIrRrSrirjrk)r4rbrr^rWrXs r5encode_record_binzLinFixedEF.encode_record_binOs=3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   nvvmydN`N`ajNkNklllmm m ? p"4?MKPTPbPbclPmPmCnoo o 9 &ty99H tyA KK & & &88:: ! > EGG Gr7rcb|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'rrrUzupdate_record_decoded %d '%s' rrszupdate_record %d %s T9402N) rur0rrPrrrvrrrr sw_actualrw)rrrxrr*ryes r5rzLinFixedEF.exportls&  ( ( * *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)NNNNrCF)rUr9)rrrrr r rrrr)r{rr6rrrr|rrrrrrrrs@r5r~r~Js?? 566@5@5@5@5@5 @5@576@5DRV]bCs3!&);?VZ&++c+c+$++++8%i%C%D%%%%8x} &GGtGGPXY\P]GilGGGG<GGtGGQYZ]Q^GjsGGGG:-"-"-"-"\-"-"-"-"-"r7r~c BeZdZdZ d dededededed ef fd ZxZS) CyclicEFz3Cyclic EF (Entry File) in the smart card filesystemNrCr$r%r&r'r(rc Htjd||||||d|dS)N)r$r%r&r'r(rrr) r4r$r%r&r'r(rrrs r5r6zCyclicEF.__init__s7lSt$T&Zalleklllllr7rz) rrrrrr)r{r6rrs@r5rrs==im!*mmCmsmm3m_emmmmmmmmmmmr7rceZdZdZ 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. NrCr$rr%r&r'r(rDc 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(rDNr)rr6r) r4r$rr%r&r'r(rDrrs r5r6zTransRecEF.__init__s> fSt$T&W[ff_efff r7rZr>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 Returns: abstract_data; dict representing the decoded data rNrrO) rPrQr rHrrIrRrSrTrUr]s r5rzTransRecEF.decode_record_hex3T:: F   (6,'' '<(( 3T:: F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r7rKct|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 Returns: abstract_data; dict representing the decoded data rNrrOr)r4rKrWrZrXs r5rzTransRecEF.decode_record_binrr7r^c*||S|jr|jSdS)rNrr`s r5rzTransRecEF.__get_rec_lens)    < < tr7rbc 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 rNrerr^rg) rPrQ_TransRecEF__get_rec_lenrrHrrrIrRrSrirjrkrls r5rzTransRecEF.encode_record_hexsb3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? b{?4?M4?@R@RS\@]@]3^$`$`aabb b 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr7c 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 rNrerr^rg) rPrQrr rHrrrIrRrSrirjrkrls r5rzTransRecEF.encode_record_binsM3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? ]t 0;D EGG Gr7cfdtdtjD}fd|DS)Nc4g|]}||jzSrr)rrSrKr4s r5 z*TransRecEF._decode_bin..=s?FFFq4</0FFFr7rc:g|]}|Sr)rrs r5rz*TransRecEF._decode_bin..?s':::a&&q)):::r7)rPrQr)r4rKchunkss`` r5rMzTransRecEF._decode_bin<siFFFFF C $5$5t|DDFFF::::6::::r7c Nfd|D}d|S)Nc fg|]-}|dd.S)r^Nre)rget)rrrr4s r5rz*TransRecEF._encode_bin..Bs<nnn[\$(( ;PT8U8U(VVnnnr7r7)rC)r4rbrrs` ` r5rdzTransRecEF._encode_binAs3nnnnn`mnnnxxr7rzr9)rrrrrrrr)r{r6rrr|rrrrrMbytesrdrrs@r5rrs`d?H  C # S s Y\ !&) 8<      %c%d%%%%6%i%D%%%%6  x}     GGtG GY\GGGG:GGtG GYbGGGG:; ;;;;  e        r7rc 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 retrieverc|jj|j\}}|j|dS)z&Retrieve (Read) data from a BER-TLV EFN)rr retrieve_datarr r s r5do_retrieve_dataz'BerTlvEF.ShellCommands.do_retrieve_dataWs=)/77AAKT3 I  d # # # # #r7cv|jj}|j|dS)z)List tags available in a given BER-TLV EFN)rr retrieve_tagsr )r4r2tagss r5do_retrieve_tagsz'BerTlvEF.ShellCommands.do_retrieve_tags]s39?0022D I  d # # # # #r7zBER-TLV Tag of value to setrrc|jj|j|j\}}|r|j|dSdS)z0Set (Write) data for a given tag in a BER-TLV EFN)rrset_datarrr r s r5 do_set_dataz"BerTlvEF.ShellCommands.do_set_datagsS)/2248TYGGKT3 ( !!$''''' ( (r7c|jj|jd\}}|r|j|dSdS)z+Delete data for a given tag in a BER-TLV EFN)rrrrr r s r5do_delete_dataz%BerTlvEF.ShellCommands.do_delete_datarsQ)/2248TBBKT3 ( !!$''''' ( (r7c|jj}|D]"}|jj|d#dS)z!Delete all data from a BER-TLV EFN)rrrr)r4rrtags r5 do_delete_allz$BerTlvEF.ShellCommands.do_delete_allysM9?0022D 4 4 ((d3333 4 4r7N)rrrrr9r:retrieve_data_parserr<rr=r>rrset_data_parserrrdel_data_parserrrrr7r5rrOs{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 4r7rNrCr$r%r&r'r(rDc tjd|||||d|d|_||_|g|_dSrF)rr6rHrDrr3rJs r5r6zBerTlvEF.__init__s[ [St$T&[[TZ[[[ #11334r7rc|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.rrz# empty file, no tagsz delete_all rzset_data 0x%02x %s ) rur0rkrrrr rrw) rrrxrrXryrlvalremainers r5rzBerTlvEF.exports  ( ( * *i 7 7o"::<<=>> >  `%&^__ _ ""$$ 2:: 1 1JJ . (J G G,,Q//*:3vay>>*J*J'ah5CHH EF !!!r7rz)rrrrr r rrr)r{r6rrrrrs@r5rrGs++011-4-4-4-4-4 -4-421-4^im'55C5s5535_e5555555 """"\"""""r7rsw_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)rr class_strswdictpatterndescrs r5 interpret_swrs%]]__** 6 <<vbz* * * *$llnn * *NGUG$$ *!5)))))) * * 4r7c\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.Nadfrrc|r|}||_||_|pi|_|jr!|p |jj|_||j_dS||_dS)zc Args: adf : ADF name sw : Dict of status word conversions N)r1r&rrrr)r4r&rrrs r5r6zCardApplication.__init__sg  ))++C ( 8 *dhlDH#'DH DHHHr7cd|jzS)NzAPP(%s)rr;s r5r<zCardApplication.__str__sDI&&r7c,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 )rr)r4rs r5rzCardApplication.interpret_swsDGR(((r7rc0dt|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 r5rzCardApplication.exports 13u7J3K3KKKr7)NNN)rrrrrr/rrr6r<rrrrrr7r5rrs(7"3QU$''' ) ) )LLLL\LLLr7rceZdZdZgZeejd 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)rtrs r5rzCardModel.add_filessr7sccr>c|}|jD]/}t|}||krtd|jdS0dS)z&Test if given card matches this model.zDetected CardModel:TF)get_atr_atrsr printr)rtr card_atratratr_bins r5matchzCardModel.matchs^;;==9  CcllG(""+S\:::tt#ur7ctD],}||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)r__subclasses__rr)r rms r5apply_matching_modelszCardModel.apply_matching_modelssK ))++  Awws||  B  r7N)rr)rrrrr  classmethodabcabstractmethodrrrrrrrr7r5rrs E>>>[>D[ ?    \   r7rceZdZdZdeeeeeeffdZdefdZ 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 r5rz!Path.__init__..s'''!'''r7c6g|]}|Sr)upperrs r5rz!Path.__init__..s ***1QWWYY***r7)r.rsplitrQrrs)r4rs r5r6z Path.__init__st a   ( AA VV ( 1Q4-- (''Q'''A***** r7r>c6d|jS)Nr!)rCrsr;s r5r<z Path.__str__sxx """r7c&dt|zS)NzPath(%s))rr;s r5__repr__z Path.__repr__sSYY''r7otherc"|j|jkSr9rsr4r%s r5__eq__z Path.__eq__syEJ&&r7c|j|Sr9r')r4rSs r5 __getitem__zPath.__getitem__!sy|r7c*t|jSr9rQrsr;s r5__len__z Path.__len__$s49~~r7ct|tr |j|z}n0t|tr|j|jz}n |j|gz}t|Sr9)r.rsr)r4ars r5__add__z Path.__add__'s[ a    A AA 4   AF"AA QCAAwwr7ct|jr+|jddvrt|jddS|S)z?Return a path relative to MF, i.e. without initial explicit MF.r)r"3F00rUN)rQrsrr;s r5relative_to_mfzPath.relative_to_mf0s? ty>> 'diln<< !"" && & r7ct|jt|jkrdS|jdt|j|jkrdSdS)z6Is this instance a parent of the given other instance?FNTr-r(s r5 is_parentzPath.is_parent6sL ty>>S__ , ,5 :os49~~o &$) 3 34ur7N)r>r)rrrrr rrrr6r<r$rr)r+r.r1r4r6rr7r5rr s//+%T#YS 9:++++#####(#(((('F't'''' v$r7r)>rtypingrrrrrrr r9r,rrrRr=r r smartcard.utilr osmocom.utilsr rrrrrrr osmocom.tlvrosmocom.constructrrr pySim.utilsrpySim.jsonpathrpySim.commandsrpySim.exceptionsrrrr{rr)r^r/rrr~rrrrrrrABCrrrr7r5rAs:2FEEEEEEEEEEEEEEEEE  22222222""""""eeeeeeeeeeeeeeeeeeee((((((KKKKKKKKKK ))))))******)))))) T#Yc3h78 S(3-  ALALALALALALALALHEEEEEXEEEPFFFFFVFFFRFFFFFfFFF@X:"""""F"""DP"P"P"P"P"P"P"P"f mmmmmzmmm^ ^ ^ ^ ^ ^ ^ ^ Ba"a"a"a"a"va"a"a"H$C(*L*L*L*L*L*L*L*L\        @//////////r7