
    i                       d Z ddlmZmZmZmZmZmZmZ ddl	Z	ddl
Z
ddlZddlZddlZddlZddlmZmZ ddlmZ ddlmZmZmZmZmZmZmZmZ ddlmZ ddlmZm Z m!Z! dd	l"m#Z#m$Z$ dd
l%m&Z& ddl'm(Z( ddl)m*Z* ee+ee+         ee+df         f         Z,ee+ee+         f         Z- G d d          Z. G d de.          Z/ G d de/          Z0 G d de/          Z1 G d de.          Z2 G d de2          Z3 G d de2          Z4 G d de4          Z5 G d de3          Z6 G d  d!e2          Z7d"e8d#e9fd$Z: G d% d&          Z; G d' d(ej<                  Z= G d) d*          Z>dS )+a  Representation 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.
    )castOptionalIterableListDictTupleUnionN)
CommandSetwith_default_category)toBytes)h2bb2his_hexauto_int
auto_uint8auto_uint16	is_hexstrJsonEncoder)bertlv_parse_one)filter_dictparse_constructbuild_construct)sw_matchdecomposeATR)js_path_modify)SimCardCommands)SwMatchError.c                      e Zd ZdZg dZdgZ	 	 	 d'dedededed	ed
         ded         dee         fdZ	d Z
dedee         fdZd(dedefdZd(dedee         fdZded          fdZdd deed                   fdZded         fdZdg fdedeed f         fdZdg fdee         deed f         fdZg fdeed f         fdZg fdee         fdZd efd!Zd" Zd#ee         fd$Zed%efd&            ZdS ))CardFilezBase class for all objects in the smart card filesystem.
    Serve as a common ancestor to all other file types; rarely used directly.
    ).../MF3f00NfidsfidnamedescparentCardDFprofileCardProfileservicec                 T   t          | t                    s|t          d          |r|                                }|| _        || _        || _        || _        || _        | j        r,| j        | k    r!| j        r| j        	                    |            || _
        || _        g | _        dS )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
        Nzfid is mandatory)
isinstanceCardADF
ValueErrorlowerr%   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__zCardFile.__init__=   s     $(( 	1S[/000 	))++C			; 	'4;$..48.K  &&&     c                 ,    | j         r| j         S | j        S Nr'   r%   r5   s    r6   __str__zCardFile.__str__]   s    9 	98Or8   prefer_namereturnc                 0    |r| j         r| j         S | j        S r:   r;   r5   r>   s     r6   _path_elementzCardFile._path_elementc   s"     	49 	98Or8   Tc                 R    d                     |                     |                    S )zReturn fully qualified path to file as string.

        Args:
            prefer_name : Preferably build path of names; fall-back to FIDs as required
        r"   )joinfully_qualified_pathrA   s     r6   fully_qualified_path_strz!CardFile.fully_qualified_path_stri   s$     xx11+>>???r8   c                     | j         r&| j         | k    r| j                             |          }ng }|                     |          }|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)   rE   rB   append)r5   r>   retelems       r6   rE   zCardFile.fully_qualified_pathq   sh     ; 	4;$..+22;??CCC!!+.. 	JJt
r8   c                     | j         r%| j         | k    r| j                                         }ng }| r|                    |            |S )zLReturn fully qualified path to file as list of CardFile instance references.)r)   fully_qualified_path_fobjrH   )r5   rI   s     r6   rL   z"CardFile.fully_qualified_path_fobj   sQ    ; 	4;$..+7799CCC 	JJt
r8   targetc                    d }||                                 k    r|gS |                                 }|                                }g }|                                 |D ]}|                    |           t	          dt          |          dz
            D ]L}||         }||k    r<||dz   d         D ]}	|                    |	            ||dd                   c c S MdS )zTBuild the relative sequence of files we need to traverse to get from us to 'target'.c                     t          t          dt          |                               D ])}t          | |         t                    r| |d          c S *| S )Nr   )reversedrangelenr/   r0   )
inter_pathis     r6   	clip_pathz0CardFile.build_select_path_to.<locals>.clip_path   s^    eAs:7788 * *jmW55 *%abb>)))*r8   r      N)get_mfrL   reverserH   rQ   rR   )
r5   rM   rU   
cur_fqpathtarget_fqpathrS   cerT   tete2s
             r6   build_select_path_tozCardFile.build_select_path_to   s*   	 	 	 V]]__$$8O3355
88::
 	5 	5Bb!!!1c-00233 5 5"1%88,QqSTT2 / /"))#....$9Z^4444444	 5 tr8   CardMFc                     | j         dS | }|j         r$|j         |k    r|j         }|j         r|j         |k    t          t          |          S )z(Return the MF (root) of the file system.N)r)   r   r_   )r5   nodes     r6   rW   zCardFile.get_mf   sY    ;4k 	dkT11;D k 	dkT11FD!!!r8   aliasc                     i }|r|                     || i           | j        r&|g k    sd|v r|                     | j        | i           | j        r&|g k    sd|v r|                     | j        | i           |S )am  Return 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.
        FIDSFNAMES)updater%   r'   r5   rb   flagsselss       r6   _get_self_selectableszCardFile._get_self_selectables   s      	'KK&&&8 	*"%KK4()))9 	+%2++U):):KKD)***r8   c                    i }| j         r| j         | k    r|S |r|                    || j         i           | j         j        r0|g k    sd|v r&|                    | j         j        | j         i           | j         j        r0|g k    sd|v r&|                    | j         j        | j         i           |                    | j                             d |                     |S )Nrd   re   )r)   rf   r%   r'   _get_parent_selectablesrg   s       r6   rl   z CardFile._get_parent_selectables   s    { 	dkT11K 	.KK,---;? 	8vKK$+6777; 	9"E0A0AKK)4;7888DK77eDDEEEr8   c                    i }|g k    sd|v r|                      d|          }|g k    sd|v r)|                    |                     d|                     |g k    sd|v rh|                                 }|rR|                    |                     |                     |                    |                    |                     |S )a  Return 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   )rj   rf   rl   rW   get_app_selectables)r5   rh   ri   mfs       r6   get_selectableszCardFile.get_selectables   s     B;;&E//--c599DB;;(e++KK44T5AABBBB;;$%--B AB4454AABBBB222??@@@r8   c                     |                      |          }t          |                                          }|                                 |S )aA  Return 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.
        )rr   listkeyssort)r5   rh   ri   sel_keyss       r6   get_selectable_nameszCardFile.get_selectable_names   s>     ##E**		$$r8   data_hexc                 H    | j         r| j                             |          S dS )zxDecode the response to a SELECT command.

        Args:
            data_hex: Hex string of the select response
        N)r)   decode_select_response)r5   ry   s     r6   r{   zCardFile.decode_select_response   s1     ; 	@;55h???	@ 	@r8   c                 b    | j         r| j         S | j        r| j                                        S dS )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    r6   r}   zCardFile.get_profile
  s;     < 	 < ; 	-;**,,,tr8   servicesc                 ,   | j         dS t          | j         t                    r	| j         |v S t          | j         t                    r| j         D ]	}||v r dS 
dS t          | j         t                    r| j         D ]	}||vr dS 
dS t          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/   intrt   tupler1   )r5   r~   ss      r6   should_exist_for_servicesz"CardFile.should_exist_for_services  s    <4dlC(( 	,<8++dlD)) 	\    ==44 !5dlE** 	\ ! !H}} 55 %4KLLLr8   as_jsonc                 0    dt          |j                  z  S )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 contentsstrselected_filer   lchans     r6   exportzCardFile.export.  s     13u7J3K3KKKr8   )NNNNNNN)T)__name__
__module____qualname____doc__RESERVED_NAMESRESERVED_FIDSr   r   CardFileServicer7   r=   boolrB   rF   r   rE   rL   r^   rW   r   rj   rl   rr   rx   r{   r}   r   r   staticmethodr    r8   r6   r   r   6   s         ,++NHMX\W[6:! !C !c ! !RU !!(+!=Em=T!"?3! ! ! !@   (3-    @ @D @C @ @ @ @  S	    4
+;    : (4
CS:T    <"* " " " " 26R  3 DjDY    & >B  Xc] PTUXZdUdPe     %'  4Z+@    2 *,  S	    @s @ @ @ @  M$s) M M M M* L L L L \L L Lr8   r   c                   &    e Zd ZdZ ed           G d de                      Z fdZ fdZd Z	d Z
dd
edefdZddee         defdZg fdef fdZdee         dee         fdZdee         dee         fdZdedee         fdZ xZS )r*   zWDF (Dedicated File) in the smart card filesystem.  Those are basically sub-directories.zDF/ADF Commandsc                       e Zd ZdS )CardDF.ShellCommandsN)r   r   r   r   r8   r6   ShellCommandsr   =  s        r8   r   c                     t          | t                    sd|vrt          d           t                      j        di | i | _        |                                 g| _        i | _        d S )Nr%   zfid is mandatory for all DFr   )	r/   r0   	TypeErrorsuperr7   childrenr   r4   files_by_servicer5   kwargs	__class__s     r6   r7   zCardDF.__init__A  sx    $(( 	?F"" =>>>""6"""#11334 "r8   c                 J    dt                                                      z  S )NzDF(%s)r   r=   r5   r   s    r6   r=   zCardDF.__str__K      577??,,--r8   c                    |j         sdS t          |j         t                    r5| j                            |j         g                               |           dS t          |j         t                    r:|j         D ]0}| j                            |g                               |           1dS t          |j         t                    r:|j         D ]0}| j                            |g                               |           1dS t          )z;Add a child (DF/EF) to the files_by_services of the parent.N)	r-   r/   r   r   
setdefaultrH   rt   r   r1   )r5   childr-   s      r6   _add_file_serviceszCardDF._add_file_servicesN  s   } 	FemS)) 		!,,U]B??FFuMMMMMt,, 	 = L L%00"==DDUKKKKL Lu-- 	 = L L%00"==DDUKKKKL L r8   c                     | j         rdS | j                                        D ].}t          |t                    r|                                r dS /d S )NT)r-   r   valuesr/   r*   _has_service)r5   cs     r6   r   zCardDF._has_service]  sd    < 	4%%'' 	  	 A!V$$  >>##  44	  	 r8   Fr   ignore_existingc                 :   t          |t                    st          d          t          |j        dd          st          d|j        z            |j        t          j        v rt          d|j        z            |j        t          j        v rt          d|j        z            |j        | j	        v r|rdS t          d|j        d	|           | 
                    |j                  rt          d
|j        d	|           |                     |j                  r|rdS t          d|j        d	|           || j	        |j        <   | |_        |                     |           t          |t                    r|j	                                        D ]}|                     |           t          |t                    rT|j	                                        D ]:}t          |t                    r#|                                rt          d          ;dS dS )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.
        zExpected a File instance   )minlenmaxlenzFile name %s is not a valid fidzFile name %s is a reserved namezFile fid %s is a reserved fidNzFile with given fid z already exists in zFile with given sfid zFile with given name z1TODO: implement recursive service -> file mapping)r/   r   r   r   r%   r1   r'   r   r   r   lookup_file_by_sfidr&   lookup_file_by_namer)   r   r*   r   r   )r5   r   r   r   gcs        r6   r3   zCardDF.add_filee  sa    %** 	86777ei!444 	N>%)LMMM:000>%*MNNN9...<	JKKK9%% *AFDDQS S S##EJ// 	U*BG***ddSU U U##EJ// 	U *BG***ddSU U U#(ei &&&eV$$ 	f^**,, f f''***a(( fj//11 f f%b&11 f!00 f&01d&e&e e	f 	ff fr8   r   c                 <    |D ]}|                      ||           dS )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   )r5   r   r   r   s       r6   	add_fileszCardDF.add_files  s4      	2 	2EMM%1111	2 	2r8   r?   c                 J   t                                          |          }|g k    sd|v r6|                    d | j                                        D                        |g k    sd|v r6|                    d | j                                        D                        |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.
        rd   c                 ,    i | ]}|j         	|j         |S r   r%   .0xs     r6   
<dictcomp>z*CardDF.get_selectables.<locals>.<dictcomp>  s#    KKKaQUKKKKr8   re   c                 ,    i | ]}|j         	|j         |S r   r'   r   s     r6   r   z*CardDF.get_selectables.<locals>.<dictcomp>  s#    MMMqafMMMMr8   )r   rr   rf   r   r   r5   rh   ri   r   s      r6   rr   zCardDF.get_selectables  s     ww&&u--B;;&E//KKKK4=+?+?+A+AKKKLLLB;;(e++KKMMDM,@,@,B,BMMMNNNr8   r'   c                 r    |dS | j                                         D ]}|j        r|j        |k    r|c S dS )z.Find a file with given name within current DF.N)r   r   r'   )r5   r'   rT   s      r6   r   zCardDF.lookup_file_by_name  sL    <4%%'' 	 	Av !&D..tr8   r&   c                     |dS | j                                         D ]+}|j        t          t	          |                    k    r|c S ,dS )z7Find a file with given short file ID within current DF.N)r   r   r&   r   r   )r5   r&   rT   s      r6   r   zCardDF.lookup_file_by_sfid  sU    <4%%'' 	 	AvSYY'' (tr8   r%   c                 2    || j         v r| j         |         S dS )z1Find a file with given file ID within current DF.N)r   )r5   r%   s     r6   lookup_file_by_fidzCardDF.lookup_file_by_fid  s!    $-=%%tr8   F)r   r   r   r   r   r
   r   r7   r=   r   r   r   r   r3   r   r   dictrr   r   r   r   r   r   __classcell__r   s   @r6   r*   r*   :  s       aa,--    
   .-# # # # #. . . . .       &f &fh &f &f &f &f &fP2 2(8"4 2t 2 2 2 2 %'  4      $ (8:L     (8:L    c hx.@        r8   r*   c                   v     e Zd ZdZ fdZd ZddZd Zg fdef fd	Z	g fdefd
Z
dee         defdZ xZS )r_   z-MF (Master File) in the smart card filesystemc                     |                     dd           |                     dd           |                     dd           | |d<    t                      j        di | i | _        d S )	Nr%   r$   r'   r#   r(   zMaster File (directory root)r)   r   )r   r   r7   applicationsr   s     r6   r7   zCardMF.__init__  s{    %(((&$'''&"@AAAx""6"""r8   c                     d| j         z  S )NzMF(%s)r   r<   s    r6   r=   zCardMF.__str__  s    48$$r8   appr0   c                     t          |t                    st          d          |j        | j        v rt          d|j        z            || j        |j        <   | |_        dS )zAdd an Application to the MFzExpected an ADF instancezAID %s already existsN)r/   r0   r   aidr   r1   r)   )r5   r   s     r6   add_application_dfzCardMF.add_application_df  sc    #w'' 	867777d'''4@AAA%(#'"


r8   c                 N    t          | j                                                  S )z#Get list of completions (AID names))rt   r   r   r<   s    r6   get_app_nameszCardMF.get_app_names  s    D%,,..///r8   r?   c                     t                                          |          }|                    |                     |                     |S )r   )r   rr   rf   rp   r   s      r6   rr   zCardMF.get_selectables  sA     ww&&u--D,,U33444r8   c                 
   i }|g k    sd|v r6|                     d | j                                        D                        |g k    sd|v r6|                     d | j                                        D                        |S )zGet applications by AID + nameAIDSc                     i | ]
}|j         |S r   )r   r   s     r6   r   z.CardMF.get_app_selectables.<locals>.<dictcomp>  s    FFFaFFFr8   ANAMESc                 ,    i | ]}|j         	|j         |S r   r   r   s     r6   r   z.CardMF.get_app_selectables.<locals>.<dictcomp>  s#    IIIq!&IIIIr8   )rf   r   r   )r5   rh   ri   s      r6   rp   zCardMF.get_app_selectables  s    B;;&E//KKFF4+<+C+C+E+EFFFGGGB;;(e++KKIID$5$<$<$>$>IIIK K Kr8   ry   c                 d    |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{   )r5   ry   r+   s      r6   r{   zCardMF.decode_select_response  sC      	O""$$ 	11(;;;Or8   )r   r0   )r   r   r   r   r7   r=   r   r   r   rr   rp   r   r   objectr{   r   r   s   @r6   r_   r_     s        77    % % %   0 0 0 %'  4       )+  t    x}         r8   r_   c                   \     e Zd ZdZddedef fdZd ZdefdZe	d	efd
            Z
 xZS )r0   z=ADF (Application Dedicated File) in the smart card filesystemFr   has_fsc                      t                      j        di | d | _        |                                | _        || _        |                                 }|r|                    |            d S d S )Nr   )r   r7   applicationr2   r   r   rW   r   )r5   r   r   r   rq   r   s        r6   r7   zCardADF.__init__  sw    ""6"""99;;[[]] 	(!!$'''''	( 	(r8   c                 2    d| j         r| j         n| j        z  S )NzADF(%s)r'   r   r<   s    r6   r=   zCardADF.__str__  s    @DIIAAr8   r>   c                 0    | j         r	|r| j         S | j        S r:   r   rA   s     r6   rB   zCardADF._path_element  s"    9 	 	98Or8   r   c                     t          |j        t                    st          d          |j        j                            | |          S )zb
        Export application specific parameters that are not part of the UICC filesystem.
        z.currently selected file is not of type CardADF)r/   r   r0   r   r   r   r   s     r6   r   zCardADF.export!  sE    
 %-w77 	NLMMM".55guEEEr8   r   )r   r   r   r   r   r   r7   r=   rB   r   r   r   r   s   @r6   r0   r0     s        GG( (C ( ( ( ( ( ( (B B B     F F F F \F F F F Fr8   r0   c                   @     e Zd ZdZ fdZ fdZg fdef fdZ xZS )CardEFz,EF (Entry File) in the smart card filesystemc                D    ||d<    t                      j        di | d S )Nr%   r   r   r7   )r5   r%   r   r   s      r6   r7   zCardEF.__init__.  s/    u""6"""""r8   c                 J    dt                                                      z  S )NzEF(%s)r   r   s    r6   r=   zCardEF.__str__2  r   r8   r?   c                 h    t                                          |          }|g k    sd|v r=|                     fd j        j                                        D                        |g k    sd|v r=|                     fd j        j                                        D                        |S )r   rd   c                 :    i | ]}|j         	|k    |j         |S r   r   r   r   r5   s     r6   r   z*CardEF.get_selectables.<locals>.<dictcomp>B  s0    ```aAE`VW[_V_V_V_V_V_r8   re   c                 :    i | ]}|j         	|k    |j         |S r   r   r   s     r6   r   z*CardEF.get_selectables.<locals>.<dictcomp>D  s0    bbbqQVbXY]aXaXaXaXaXar8   )r   rr   rf   r)   r   r   r   s   `  r6   rr   zCardEF.get_selectables5  s     ww&&u--B;;&E//KK````4;+?+F+F+H+H```aaaB;;(e++KKbbbbDK,@,G,G,I,Ibbbcccr8   )	r   r   r   r   r7   r=   r   rr   r   r   s   @r6   r   r   +  s        66# # # # #. . . . . %'  4          r8   r   c                   *    e Zd ZdZ ed           G d de                      Z	 	 ddeded	ed
edede	f fdZ
dedefdZdedefdZddee         dee         fdZddedee         defdZddedee         defdZedefd            Z xZS )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.zTransparent EF Commandsc                   Z   e Zd ZdZ ej                    Ze                    ddd           e                    ded            e	j
        e          d	             Z ej                    Ze                    d
edd           e                    ded            e	j
        e          d             Z ej                    Ze                    ddd            e	j
        e          d             Z ej                    Ze                    d
edd           e                    ded            e	j
        e          d             Z ej                    Ze                    ded           e                    dd            e	j
        e          d             Zd ZdS )TransparentEF.ShellCommandsz,Shell commands specific for transparent EFs.	--oneline
store_true.No JSON pretty-printing, dump as a single lineactionhelpHEXSTR$Hex-string of encoded data to decodetyper   c                     | j         j        j                            |j                  }| j                             ||j                   dS zHDecode command-line provided hex-string as if it was read from the file.N)_cmdr   r   
decode_hexr   poutput_jsononeliner5   optsdatas      r6   do_decode_hexz)TransparentEF.ShellCommands.do_decode_hexW  s@     9?0;;DKHHDI""466666r8   z--offsetr   zByte offset for start of readr   defaultr   z--lengthzNumber of bytes to readc                     | j         j                            |j        |j                  \  }}| j                             |           dS )z&Read binary data from a transparent EFN)r   r   read_binarylengthoffsetpoutputr5   r  r  _sws       r6   do_read_binaryz*TransparentEF.ShellCommands.do_read_binaryc  sA     )/55dk4;OOKT3Id#####r8   c                     | j         j                                        \  }}| j                             ||j                   dS )z(Read + decode data from a transparent EFN)r   r   read_binary_decr   r  r  s       r6   do_read_binary_decodedz2TransparentEF.ShellCommands.do_read_binary_decodedm  s=     )/99;;KT3I""466666r8   DATA Data bytes (hex format) to writec                     | j         j                            |j        |j                  \  }}|r| j                             |           dS dS )z'Update (Write) data of a transparent EFN)r   r   update_binaryr  r  r  r  s       r6   do_update_binaryz,TransparentEF.ShellCommands.do_update_binaryx  sS     )/77	4;OOKT3 (	!!$'''''( (r8   --json-pathz1JSON path to modify specific element of file only$Abstract data (JSON format) to writer   c                 d   |j         rO| j        j                                        \  }}t	          ||j         t          j        |j                             nt          j        |j                  }| j        j                            |          \  }}|r| j        	                    |           dS dS )z0Encode + Update (Write) data of a transparent EFN)
	json_pathr   r   r  r   jsonloadsr  update_binary_decr   r5   r  	data_jsonr  r  s        r6   do_update_binary_decodedz4TransparentEF.ShellCommands.do_update_binary_decoded  s     ~ 2#'9?#B#B#D#D Cy$.#z$)446 6 6 6 !Jty11	)/;;IFFKT3 -	&&t,,,,,- -r8   c                    | j         j                                        \  }}t          j        d          5 }d|z  }t          |d          5 }t          j        ||dt                     ddd           n# 1 swxY w Y   | j         	                    |           t          |d          5 }t          j
        |          }ddd           n# 1 swxY w Y   ||k    r| j                             d	           n>| j         j                            |          \  }}|r| j                             |           ddd           dS # 1 swxY w Y   dS )
z=Edit the JSON representation of the EF contents in an editor.pysim_prefix%s/filewr   indentclsNr!Data not modified, skipping write)r   r   r  tempfileTemporaryDirectoryopenr  dumpr   
run_editorloadr  r  r   )	r5   _opts	orig_jsonr  dirnamefilename	text_fileedited_jsonr  s	            r6   do_edit_binary_decodedz2TransparentEF.ShellCommands.do_edit_binary_decoded  s   #y>>@@Y,H=== 5$w.(C(( OIIi1+NNNNO O O O O O O O O O O O O O O 	$$X...(C(( 7I"&)I"6"6K7 7 7 7 7 7 7 7 7 7 7 7 7 7 7)++I%%&IJJJJ"&)/"C"CK"P"PKT3 5	..t4445 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZ   EA7+E7A;	;E>A;	?-E,CEC	EC	A"EEEN)r   r   r   r   argparseArgumentParserdec_hex_parseradd_argumentr   cmd2with_argparserr  read_bin_parserr   r  read_bin_dec_parserr  upd_bin_parserr  upd_bin_dec_parserr   r"  r:  r   r8   r6   r   r   N  s       ::0022##K)Y 	$ 	[ 	[ 	[##H9Ci#jjj		^	,	,	7 	7 
-	,	7
 2(133$$[!:Y 	% 	[ 	[ 	[$$[/H 	% 	J 	J 	J 
	_	-	-	$ 	$ 
.	-	$
 6h577((\.^ 	) 	` 	` 	` 
	0	1	1	7 	7 
2	1	7
 1022##[!:Y 	$ 	[ 	[ 	[##FAc#ddd		^	,	,	( 	( 
-	,	( 5X466''C-` 	( 	b 	b 	b''5['\\\		/	0	0
	- 
	- 
1	0
	-	5 	5 	5 	5 	5r8   r   NrV   Nr%   r&   r'   r(   r)   sizec           	           t                      j        d|||||d| d| _        d| _        || _        |                                 g| _        dS as  
        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   )r   r7   
_construct_tlvrF  r   r4   	r5   r%   r&   r'   r(   r)   rF  r   r   s	           r6   r7   zTransparentEF.__init__  sb     	[St$T&[[TZ[[[		#11334r8   raw_bin_datar?   c                    t          | dd          }t          |          r ||          S t          | dd          }t          |          r |t          |                    S | j        rt	          | j        |          S | j        r]t          j        | j                  r|                                 n| j        }|                    |           |	                                S d|
                                iS )a  Decode 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_hexraw)getattrcallabler   rJ  r   rK  inspectisclassfrom_tlvto_dicthex)r5   rM  methodts       r6   
decode_binzTransparentEF.decode_bin  s     }d33F 	(6,'''}d33F 	-6#l++,,,? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|''))**r8   raw_hex_datac                    t          | dd          }t          |          r ||          S t          |          }t          | dd          }t          |          r ||          S | j        rt	          | j        |          S | j        r]t          j        | j                  r|                                 n| j        }|                    |           |	                                S d|
                                iS )a  Decode 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
        rP  NrO  rQ  rR  rS  r   rJ  r   rK  rT  rU  rV  rW  rX  r5   r\  rY  rM  rZ  s        r6   r   zTransparentEF.decode_hex  s     }d33F 	(6,'''<((}d33F 	(6,'''? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|''))**r8   	total_lenc                     ||S | j         dS | j         d         | j         d         S | j         d         | j         d         S dS )z'Get the size (total length) of the fileNrV   r   )rF  r5   r`  s     r6   
__get_sizezTransparentEF.__get_size  sT      94 9Q<#9Q<9Q<#9Q<tr8   abstract_datac                 l   t          | dd          }t          |          r  |||                     |                    S t          | dd          }t          |          r-t           |||                     |                              S | j        r+t          | j        |d|                     |          i          S | j        r]t          j        | j                  r|                                 n| j        }|	                    |           |
                                S t          d| 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_binNr`  _encode_hexr`  0%s encoder not yet implemented. Patches welcome.)rR  rS  _TransparentEF__get_sizer   rJ  r   rK  rT  rU  	from_dictto_tlvNotImplementedErrorr5   rd  r`  rY  rZ  s        r6   
encode_binzTransparentEF.encode_bin  s1    }d33F 	Q6-T__Y5O5OPPPP}d33F 	Vvvm9S9STTTUUU? 	o"4?MKRVRaRabkRlRlCmnnn9 	&ty99H		tyAKK&&&88::!>EG G 	Gr8   c           
         t          | dd          }t          |          r  |||                     |                    S t          | dd          }t          |          r/ |||                     |                    }t          |          S | j        r8t          t          | j        |d|                     |          i                    S | j        rjt          j        | j                  r|                                 n| j        }|	                    |           t          |
                                          S t          d| z            )a  Encode 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
        rh  Nrg  rf  r`  ri  )rR  rS  rj  r   rJ  r   rK  rT  rU  rk  rl  rm  )r5   rd  r`  rY  rM  rZ  s         r6   
encode_hexzTransparentEF.encode_hex  sC    }d33F 	Q6-T__Y5O5OPPPP}d33F 	%!6-T__Y=W=WXXXL|$$$? 	rtTXTcTcdmTnTnGoppqqq9 	#&ty99H		tyAKK&&&qxxzz??"!>EG G 	Gr8   r   c                    |                                 dk    r$t          d|                                 z            d}| r<|                                }|dt          j        |d         t
                    z  z  }n/|                                }|dt          |d                   z  z  }|                                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' zupdate_binary_decoded '%s'
r   r+  zupdate_binary %s
)	selected_file_structurer1   r  r  dumpsr   r	  r   strip)r   r   
export_strresults       r6   r   zTransparentEF.export6  s     ((**m;;s"::<<= > > >
 	B**,,F9DJvayVa<b<b<bbcJJ&&((F/#fQi..@AJ!!!r8   NNNNrE  r:   )r   r   r   r   r   r
   r   r   r*   Sizer7   	bytearrayr   r[  r   r   r   rj  ro  rq  r   r   r   r   r   s   @r6   r   r   H  s       _ _
 455S5 S5 S5 S5 S5
 S5 S5 65S5j im'5 5C 5s 5 53 5_e 55 5 5 5 5 5"+y +T + + + +4+s +t + + + +6 HSM Xc]    &G G G# GR[ G G G G8G G G# GRU G G G G: " " " " \" " " " "r8   r   c                   L    e Zd ZdZ ed           G d de                      Z	 	 dded	ed
ededee	         de
def fdZddededefdZdededefdZd dee         dee         fdZd dededee         defdZd dededee         defdZedefd            Z xZS )!
LinFixedEFzLinear Fixed EF (Entry File) in the smart card filesystem.

    Linear Fixed EFs are record oriented files.  They consist of a number of fixed-size
    records.  The records can be individually read/updated.zLinear Fixed EF Commandsc                      e Zd ZdZ ej                    Ze                    ddd           e                    ded            e	j
        e          d	             Z ej                    Ze                    d
edd           e                    ded            e	j
        e          d             Z ej                    Ze                    ddd           e                    ded            e	j
        e          d             Z ej                    Z e	j
        e          d             Z ej                    Ze                    ddd            e	j
        e          d             Z ej                    Ze                    ded           e                    ded            e	j
        e          d             Z ej                    Ze                    ded           e                    ded           e                    dd            e	j
        e          d             Z ej                    Ze                    ded            e	j
        e          d             ZdS ) LinFixedEF.ShellCommandsz-Shell commands specific for Linear Fixed EFs.r   r   r   r   r   r   r   c                     | j         j        j                            |j                  }| j                             ||j                   dS r   )r   r   r   decode_record_hexr   r   r  r  s      r6   r  z&LinFixedEF.ShellCommands.do_decode_hexX  s@     9?0BB4;OODI""466666r8   z--countrV   z4Number of records to be read, beginning at record_nrr  	RECORD_NRzNumber of record to be readc                    t          |j                  D ]r}|j        |z   }| j        j                            |          \  }}t          |          dk    rt          |          }nd}| j                            d||fz             sdS )z6Read one or multiple records from a record-oriented EFr   (empty)%03d %sN)	rQ   countr  r   r   read_recordrR   r   r  )r5   r  r,  recnrr  r  recstrs          r6   do_read_recordz'LinFixedEF.ShellCommands.do_read_recordd  s     4:&& ? ?*"io99%@@st99q== YYFF&F	!!)ufo"=>>>>? ?r8   c                     | j         j                            |j                  \  }}| j                             ||j                   dS )z0Read + decode a record from a record-oriented EFN)r   r   read_record_decr  r   r  r  s       r6   do_read_record_decodedz/LinFixedEF.ShellCommands.do_read_record_decodedv  sA     )/99$.IIKT3I""466666r8   c                 :   | j         j                                        }t          dd|z             D ]h}| j         j                            |          \  }}t          |          dk    rt          |          }nd}| j                             d||fz             idS )z*Read all records from a record-oriented EFrV   r   r  r  N)r   r   selected_file_num_of_recrQ   r  rR   r   r  )r5   r4  
num_of_recr  r  r  r  s          r6   do_read_recordsz(LinFixedEF.ShellCommands.do_read_records~  s     AACCJq!j.11 ? ?"io99%@@st99q== YYFF&F	!!)ufo"=>>>>? ?r8   c                     | j         j                                        }g }t          dd|z             D ]9}| j         j                            |          \  }}|                    |           :| j                             ||j                   dS )z3Read + decode all records from a record-oriented EFrV   N)r   r   r  rQ   r  rH   r   r  )r5   r  r  	data_listr  r  r  s          r6   do_read_records_decodedz0LinFixedEF.ShellCommands.do_read_records_decoded  s     AACCJIq!j.11 ' '"io==eDDs  &&&&I""9dl;;;;;r8   r  r  c                     | j         j                            |j        |j                  \  }}|r| j                             |           dS dS )z+Update (write) data to a record-oriented EFN)r   r   update_recordr  r  r  r  s       r6   do_update_recordz)LinFixedEF.ShellCommands.do_update_record  sS     )/77	RRKT3 (	!!$'''''( (r8   r  z3JSON path to modify specific element of record onlyr  r  r  c                 |   |j         rU| j        j                            |j                  \  }}t          ||j         t          j        |j                             nt          j        |j                  }| j        j        	                    |j        |          \  }}|r| j        
                    |           dS dS )z4Encode + Update (write) data to a record-oriented EFN)r  r   r   r  r  r   r  r  r  update_record_decr  r   s        r6   do_update_record_decodedz1LinFixedEF.ShellCommands.do_update_record_decoded  s     ~ 2#'9?#B#B4>#R#R Cy$.#z$)446 6 6 6 !Jty11	)/;;	+ +KT3 (	!!$'''''( (r8   zNumber of record to be editedc                    | j         j                            |j                  \  }}t	          j        d          5 }d|z  }t          |d          5 }t          j        ||dt                     ddd           n# 1 swxY w Y   | j         
                    |           t          |d          5 }t          j        |          }ddd           n# 1 swxY w Y   ||k    r| j                             d	           nD| j         j                            |j        |          \  }}|r| j                             |           ddd           dS # 1 swxY w Y   dS )
z8Edit the JSON representation of one record in an editor.r$  r%  r'  r(  r   r)  Nr,  r-  )r   r   r  r  r.  r/  r0  r  r1  r   r2  r3  r  r  r   )	r5   r  r5  r  r6  r7  r8  r9  r  s	            r6   do_edit_record_decodedz/LinFixedEF.ShellCommands.do_edit_record_decoded  s     $y>>t~NNY,H=== 5$w.(C(( OIIi1+NNNNO O O O O O O O O O O O O O O 	$$X...(C(( 7I"&)I"6"6K7 7 7 7 7 7 7 7 7 7 7 7 7 7 7)++I%%&IJJJJ"&)/"C"C#5 #5KT3 5	..t4445 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZ   EA=1E=B	EB	-E2CEC	EC	A(EEEN)r   r   r   r   r;  r<  r=  r>  r   r?  r@  r  read_rec_parserr   r  read_rec_dec_parserr  read_recs_parserr  read_recs_dec_parserr  upd_rec_parserr  upd_rec_dec_parserr   r  edit_rec_dec_parserr  r   r8   r6   r   r  P  s       ;;0022##K)Y 	$ 	[ 	[ 	[##H9Ci#jjj		^	,	,	7 	7 
-	,	7
 2(133$$J8n 	% 	p 	p 	p$$j/L 	% 	N 	N 	N 
	_	-	-		? 		? 
.	-		? 6h577((\.^ 	) 	` 	` 	`((j/L 	) 	N 	N 	N 
	0	1	1	7 	7 
2	1	7
 38244		-	.	.		? 		? 
/	.		?  7x688))+l/_ 	* 	a 	a 	a 
	1	2	2	< 	< 
3	2	< 1022##j/L 	$ 	N 	N 	N##FAc#ddd		^	,	,	( 	( 
-	,	( 5X466''C-b 	( 	d 	d 	d''j/L 	( 	N 	N 	N''5['\\\		/	0	0	( 	( 
1	0	( 6h577((j/N 	) 	P 	P 	P 
	0	1	1	5 	5 
2	1	5 	5 	5r8   r   NrE  Fr%   r&   r'   r(   r)   rec_lenleftpadc           	           t                      j        d|||||d| || _        || _        |                                 g| _        d| _        d| _        dS )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
        rI  Nr   )r   r7   r  r  r   r4   rJ  rK  )
r5   r%   r&   r'   r(   r)   r  r  r   r   s
            r6   r7   zLinFixedEF.__init__  sg     	[St$T&[[TZ[[[#11334			r8   rV   r\  	record_nrr?   c                     t          | dd          }t          |          r |||          S t          |          }t          | dd          }t          |          r |||          S | j        rt	          | j        |          S | j        r]t          j        | j                  r|                                 n| j        }|                    |           |	                                S d|
                                iS )a  Decode 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_hexNr  _decode_record_binrQ  r^  )r5   r\  r  rY  rM  rZ  s         r6   r  zLinFixedEF.decode_record_hex  s    3T::F 	=6,)<<<<<((3T::F 	=6,)<<<<? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|''))**r8   rM  c                    t          | dd          }t          |          r |||          S t          |          }t          | dd          }t          |          r |||          S | j        rt	          | j        |          S | j        r]t          j        | j                  r|                                 n| j        }|                    |           |	                                S d|iS )a  Decode 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
        r  Nr  r  rQ  )
rR  rS  r   rJ  r   rK  rT  rU  rV  rW  )r5   rM  r  rY  r\  rZ  s         r6   decode_record_binzLinFixedEF.decode_record_bin  s     3T::F 	=6,)<<<<<((3T::F 	=6,)<<<<? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|$$r8   r`  c                     ||S | j         dS | j         d         | j         d         S | j         d         | j         d         S dS )0Get the length (total length) of the file recordNrV   r   r  rb  s     r6   __get_rec_lenzLinFixedEF.__get_rec_len  sT      <4 <?&<?"<?&<?"tr8   rd  c           
         t          | dd          }t          |          r! ||||                     |                    S t          | dd          }t          |          r0 ||||                     |                    }t          |          S | j        r8t          t          | j        |d|                     |          i                    S | j        rjt          j        | j                  r|                                 n| j        }|	                    |           t          |
                                          S t          d| z            )ae  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
            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_hexNr  r`  _encode_record_binr`  ri  )rR  rS  _LinFixedEF__get_rec_lenr   rJ  r   rK  rT  rU  rk  rl  rm  )r5   rd  r  r`  rY  rM  rZ  s          r6   encode_record_hexzLinFixedEF.encode_record_hex1  sP    3T::F 	i6-9$J\J\]fJgJghhhh3T::F 	%!6-9RVRdRdenRoRopppL|$$$? 	utTXTfTfgpTqTqGrssttt9 	#&ty99H		tyAKK&&&qxxzz??"!>EG G 	Gr8   c           	      p   t          | dd          }t          |          r! ||||                     |                    S t          | dd          }t          |          r.t           ||||                     |                              S | j        r+t          | j        |d|                     |          i          S | j        r]t          j        | j                  r|                                 n| j        }|	                    |           |
                                S t          d| 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
        r  Nr  r  r`  ri  )rR  rS  r  r   rJ  r   rK  rT  rU  rk  rl  rm  )r5   rd  r  r`  rY  rZ  s         r6   encode_record_binzLinFixedEF.encode_record_binO  s=    3T::F 	i6-9$J\J\]fJgJghhhh3T::F 	nvvmydN`N`ajNkNklllmmm? 	p"4?MKPTPbPbclPmPmCnooo9 	&ty99H		tyAKK&&&88::!>EG G 	Gr8   r   c                 b   |                                 dk    r<|                                 dk    r$t          d|                                 z            d}|                                }|rt          d|dz             D ]u}| r?|                    |          }|d|t          j        |d         t                    fz  z  }C|                    |          }|d	|t          |d                   fz  z  }vnd}	 	 | r?|                    |          }|d|t          j        |d         t                    fz  z  }n2|                    |          }|d	|t          |d                   fz  z  }|# t          $ r}|j        dk    rY d}~nY d}~nd}~ww xY w|dz   }|                                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_fixedcycliczaselected file has structure type '%s', expecting a file with structure 'linear_fixed' or 'cyclic'rt  rV   zupdate_record_decoded %d '%s'
r   ru  zupdate_record %d %s
T9402N)rv  r1   r  rQ   r  r  rw  r   r  r   r   	sw_actualrx  )r   r   ry  r  r,  rz  es          r6   r   zLinFixedEF.exportl  s&    ((**n<<A^A^A`A`dlAlAl  A"::<<= > > > 
 3355
 	1j1n-- R R R"22155F#D4:V\]^V_epKqKqKqGr#rsJJ"..q11F#:aVAY=P#PQJJR A V!&!6!6q!9!9"'HAtzZ`abZcitOuOuOuKv'vw

!&!2!21!5!5"'>!SPQ^^AT'TU
 G $   {f,, -,,,, E" !!!s   ;A3E0 0
F:FF)NNNNrE  F)rV   r:   )r   r   r   r   r   r
   r   r   r   r*   r|  r   r7   r   r   r  r}  r  r  r  r  r   r   r   r   s   @r6   r  r  J  s       ? ?
 566@5 @5 @5 @5 @5
 @5 @5 76@5D RV]b C s  3 !&);?VZ     &+ +c +c +$ + + + +8%i %C %D % % % %8 x}     &G Gt G GPXY\P] Gil G G G G<G Gt G GQYZ]Q^ Gjs G G G G: -" -" -" -" \-" -" -" -" -"r8   r  c                   B     e Zd ZdZ	 	 ddededededed	ef fd
Z xZS )CyclicEFz3Cyclic EF (Entry File) in the smart card filesystemNrE  r%   r&   r'   r(   r)   r  c           
      H     t                      j        d||||||d| d S )N)r%   r&   r'   r(   r)   r  r   r   )	r5   r%   r&   r'   r(   r)   r  r   r   s	           r6   r7   zCyclicEF.__init__  s7    lSt$T&Zalleklllllr8   r{  )	r   r   r   r   r   r*   r|  r7   r   r   s   @r6   r  r    s        == im!*m mC ms m m3 m_e mm m m m m m m m m mr8   r  c                        e Zd ZdZ	 	 ddededededed	ee         d
ef fdZ	dede
fdZdede
fdZddee         dee         fdZdde
dee         defdZdde
dee         defdZdefdZdefdZ xZS )
TransRecEFa  Transparent 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.
    NrE  r%   r  r&   r'   r(   r)   rF  c           
      V     t                      j        d||||||d| || _        dS )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)   rF  Nr   )r   r7   r  )
r5   r%   r  r&   r'   r(   r)   rF  r   r   s
            r6   r7   zTransRecEF.__init__  s>     	fSt$T&W[ff_efffr8   r\  r?   c                 ,   t          |          dz  |                                 k     rd|iS t          | dd          }t          |          r ||          S t	          |          }t          | dd          }t          |          r ||          S | j        rt          | j        |          S | j        r]t          j	        | j                  r|                                 n| j        }|
                    |           |                                S d|iS )a  Decode 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
           rQ  r  Nr  )rR   _TransRecEF__get_rec_lenrR  rS  r   rJ  r   rK  rT  rU  rV  rW  r_  s        r6   r  zTransRecEF.decode_record_hex  s     |!D$6$6$8$888<((3T::F 	(6,'''<((3T::F 	(6,'''? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|$$r8   rM  c                 @   t          |          |                                 k     rdt          |          iS t          | dd          }t	          |          r ||          S t          |          }t          | dd          }t	          |          r ||          S | j        rt          | j        |          S | j        r]t          j	        | j                  r|                                 n| j        }|
                    |           |                                S d|iS )a  Decode 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
        rQ  r  Nr  )rR   r  r   rR  rS  rJ  r   rK  rT  rU  rV  rW  )r5   rM  rY  r\  rZ  s        r6   r  zTransRecEF.decode_record_bin  s    |t1133333|,,--3T::F 	(6,'''<((3T::F 	(6,'''? 	B"4?LAAA9 	&ty99H		tyAJJ|$$$99;;|$$r8   r`  c                 *    ||S | j         r| j         S dS )r  Nr  rb  s     r6   r  zTransRecEF.__get_rec_len  s)       < 	 <tr8   rd  c                    t          | dd          }t          |          r  |||                     |                    S t          | dd          }t          |          r-t           |||                     |                              S | j        rEt          t          t          | j        |d|                     |          i                              S | j        rjt          j	        | j                  r|                                 n| j        }|
                    |           t          |                                          S t          d| 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
        r  Nrg  r  r`  ri  )rR  rS  r  r   rJ  r   r   rK  rT  rU  rk  rl  rm  rn  s        r6   r  zTransRecEF.encode_record_hex  sb    3T::F 	T6-T5G5G	5R5RSSSS3T::F 	Yvvm9K9KI9V9VWWWXXX? 	b{?4?M4?@R@RS\@]@]3^$` $` a a b b b9 	#&ty99H		tyAKK&&&qxxzz??"!>EG G 	Gr8   c           
         t          | dd          }t          |          r  |||                     |                    S t          | dd          }t          |          r-t           |||                     |                              S | j        r8t          t          | j        |d|                     |          i                    S | j        r]t          j	        | j                  r|                                 n| j        }|
                    |           |                                S t          d| 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
            total_len : expected total length of the encoded data (record length)
        Returns:
            binary encoded data
        r  Nrg  r  r`  ri  )rR  rS  r  r   rJ  r   r   rK  rT  rU  rk  rl  rm  rn  s        r6   r  zTransRecEF.encode_record_bin+  sM    3T::F 	T6-T5G5G	5R5RSSSS3T::F 	Yvvm9K9KI9V9VWWWXXX? 	]t0;D<N<Ny<Y<Y/Z \  \ ] ] ]9 	&ty99H		tyAKK&&&88::!>EG G 	Gr8   c                       fdt          dt                     j                  D             } fd|D             S )Nc                 4    g | ]}||j         z            S r   r  )r   rT   rM  r5   s     r6   
<listcomp>z*TransRecEF._decode_bin.<locals>.<listcomp>I  s?     F F F q4</0 F F Fr8   r   c                 :    g | ]}                     |          S r   )r  r   s     r6   r  z*TransRecEF._decode_bin.<locals>.<listcomp>K  s'    :::a&&q)):::r8   )rQ   rR   r  )r5   rM  chunkss   `` r6   rO  zTransRecEF._decode_binH  si    F F F F F C$5$5t|DDF F F::::6::::r8   c                 N      fd|D             }d                     |          S )Nc           	      f    g | ]-}                     |                    d d                    .S )r`  Nrg  )r  get)r   r   r   r5   s     r6   r  z*TransRecEF._encode_bin.<locals>.<listcomp>N  s<    nnn[\$((

;PT8U8U(VVnnnr8   r8   )rD   )r5   rd  r   r  s   ` ` r6   rf  zTransRecEF._encode_binM  s3    nnnnn`mnnnxxr8   r{  r:   )r   r   r   r   r   r   r   r*   r|  r7   r   r  r}  r  r  r  r  rO  bytesrf  r   r   s   @r6   r  r    s         `d?H C # S s Y\ !&)8<      %c  %d  %  %  %  %D%i %D % % % %@ x}     G Gt G GY\ G G G G:G Gt G GYb G G G G:;	 ; ; ; ;
 e                r8   r  c                        e Zd ZdZ ed           G d de                      Z	 	 ddeded	ed
edede	f fdZ
edefd            Z xZS )BerTlvEFaV  BER-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.zBER-TLV EF Commandsc                      e Zd ZdZ ej                    Ze                    ded            e	j
        e          d             Zd Z ej                    Ze                    ded           e                    ded	            e	j
        e          d
             Z ej                    Ze                    ded            e	j
        e          d             Zd ZdS )BerTlvEF.ShellCommandsz(Shell commands specific for BER-TLV EFs.TAGz BER-TLV Tag of value to retriever   c                     | j         j                            |j                  \  }}| j                             |           dS )z&Retrieve (Read) data from a BER-TLV EFN)r   r   retrieve_datar  r  r  s       r6   do_retrieve_dataz'BerTlvEF.ShellCommands.do_retrieve_datac  s=     )/77AAKT3Id#####r8   c                 v    | j         j                                        }| j                             |           dS )z)List tags available in a given BER-TLV EFN)r   r   retrieve_tagsr  )r5   r4  tagss      r6   do_retrieve_tagsz'BerTlvEF.ShellCommands.do_retrieve_tagsi  s3    9?0022DId#####r8   zBER-TLV Tag of value to setr  r  c                     | j         j                            |j        |j                  \  }}|r| j                             |           dS dS )z0Set (Write) data for a given tag in a BER-TLV EFN)r   r   set_datar  r  r  r  s       r6   do_set_dataz"BerTlvEF.ShellCommands.do_set_datas  sS     )/2248TYGGKT3 (	!!$'''''( (r8   c                     | j         j                            |j        d          \  }}|r| j                             |           dS dS )z+Delete data for a given tag in a BER-TLV EFN)r   r   r  r  r  r  s       r6   do_delete_dataz%BerTlvEF.ShellCommands.do_delete_data~  sQ     )/2248TBBKT3 (	!!$'''''( (r8   c                     | j         j                                        }|D ]"}| j         j                            |d           #dS )z!Delete all data from a BER-TLV EFN)r   r   r  r  )r5   r  r  tags       r6   do_delete_allz$BerTlvEF.ShellCommands.do_delete_all  sM    9?0022D 4 4	((d33334 4r8   N)r   r   r   r   r;  r<  retrieve_data_parserr>  r   r?  r@  r  r  set_data_parserr   r  del_data_parserr  r  r   r8   r6   r   r  [  s{       666x688))'I 	* 	K 	K 	K 
	1	2	2	$ 	$ 
3	2	$
	$ 	$ 	$
 2(133$$'D 	% 	F 	F 	F$$V)Bd$eee		_	-	-	( 	( 
.	-	( 2(133$$'D 	% 	F 	F 	F 
	_	-	-	( 	( 
.	-	(	4 	4 	4 	4 	4r8   r   NrE  r%   r&   r'   r(   r)   rF  c           	           t                      j        d|||||d| d| _        || _        |                                 g| _        dS rH  )r   r7   rJ  rF  r   r4   rL  s	           r6   r7   zBerTlvEF.__init__  s[     	[St$T&[[TZ[[[	#11334r8   r   c                    |                                 dk    r$t          d|                                 z            | rt          d          d}|                                }|g k    r|dz  }n]|dz  }|D ]U}|                    |          }t          t          |d                             \  }}}}	|d|t          |          fz  z  }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.rt  z# empty file, no tagszdelete_all
r   zset_data 0x%02x %s
)	rv  r1   rm  r  r  r   r   r   rx  )
r   r   ry  r  rZ  rz  r  lval	remainders
             r6   r   zBerTlvEF.export  s    ((**i77o"::<<= > > >  	`%&^___
""$$2::11JJ.(J G G,,Q//+;Cq	NN+K+K(ai5CHHEF

!!!r8   r{  )r   r   r   r   r   r
   r   r   r*   r|  r7   r   r   r   r   r   s   @r6   r  r  S  s        + + 011-4 -4 -4 -4 -4
 -4 -4 21-4^ im'5 5C 5s 5 53 5_e 55 5 5 5 5 5  " " " " \" " " " "r8   r  sw_dataswc                     |                                  D ]G\  }}||v r|||         fc S |                                 D ]\  }}t          ||          r||fc c S HdS )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_strswdictpatterndescrs         r6   interpret_swr    s     %]]__ * *	6<<vbz****$llnn 	* 	*NGUG$$ *!5))))))*	* 4r8   c                   \    e Zd ZdZddee         dedefdZd Z	d Z
ed	efd
            ZdS )CardApplicationzqA card application is represented by an ADF (with contained hierarchy) and optionally
       some SW definitions.Nadfr   r  c                     |r|                                 }|| _        || _        |pi | _        | j        r!|p| j        j        | _        | | j        _        dS || _        dS )zc
        Args:
            adf : ADF name
            sw : Dict of status word conversions
        N)r2   r'   r   r  r   r   )r5   r'   r   r   r  s        r6   r7   zCardApplication.__init__  sg      	))++C	(8 	*dhlDH#'DH   DHHHr8   c                     d| j         z  S )NzAPP(%s)r   r<   s    r6   r=   zCardApplication.__str__  s    DI&&r8   c                 ,    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  )r5   r  s     r6   r  zCardApplication.interpret_sw  s     DGR(((r8   r   c                 0    dt          |j                  z  S )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 featuresr   r   s     r6   r   zCardApplication.export  s     13u7J3K3KKKr8   )NNN)r   r   r   r   r   r0   r   r   r7   r=   r  r   r   r   r   r8   r6   r  r    s          (7"3  QU    $' ' '	) 	) 	) L L L L \L L Lr8   r  c                       e Zd ZdZg Zeej        d
d                        Zede	de
fd            Zede	ddfd            Z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RuntimeStatec                     dS )z/Add model specific files to given RuntimeState.Nr   )r+  r  s     r6   r   zCardModel.add_files  s      r8   sccr?   c                 "   |                                 }| j        D ] }||k    rt          d| j                    dS !t	          |          d         }| j        D ]5}t	          |          d         }||k    rt          d| j                    dS 6dS )z&Test if given card matches this model.zDetected CardModel:ThbF)get_atr_atrsprintr   r   )r+  r
  card_atratrcard_atr_hbatr_hbs         r6   matchzCardModel.match  s     ;;==9 	 	Ch+S\:::tt  #8,,T29 	 	C!#&&t,F$$+S\:::tt % ur8   c                     t                                           D ],}|                    |           r|                    |           -dS )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__r  r   )r
  r  ms      r6   apply_matching_modelszCardModel.apply_matching_models  sK    
 ))++ 	  	 Awws||  B	  	 r8   N)r  r  )r   r   r   r   r  classmethodabcabstractmethodr   r   r   r  r   r  r   r8   r6   r  r    s          E> > >  [>  D    [   ?         \     r8   r  c                       e Zd ZdZdeeee         ee         f         fdZdefdZ	defdZ
dd defdZd	 Zd
 Zd ZddZdd defdZdS )Pathz%Representation of a file-system path.pc                     t          |t                    r|                    d          }n6t          |          r't          |d         t                    rd |D             }d |D             | _        d S )Nr"   r   c                     g | ]}d |z  S )z%04xr   r   s     r6   r  z!Path.__init__.<locals>.<listcomp>&  s    '''!'''r8   c                 6    g | ]}|                                 S r   )upperr   s     r6   r  z!Path.__init__.<locals>.<listcomp>(  s     ***1QWWYY***r8   )r/   r   splitrR   r   rt   )r5   r  s     r6   r7   zPath.__init__!  st    a 	(AAVV 	(
1Q4-- 	(''Q'''A*****			r8   r?   c                 6    d                     | j                  S )Nr"   )rD   rt   r<   s    r6   r=   zPath.__str__*  s    xx	"""r8   c                 &    dt          |           z  S )NzPath(%s))r   r<   s    r6   __repr__zPath.__repr__-  s    SYY''r8   otherc                 "    | j         |j         k    S r:   rt   r5   r'  s     r6   __eq__zPath.__eq__0  s    yEJ&&r8   c                     | j         |         S r:   r)  )r5   rT   s     r6   __getitem__zPath.__getitem__3  s    y|r8   c                 *    t          | j                  S r:   rR   rt   r<   s    r6   __len__zPath.__len__6  s    49~~r8   c                     t          |t                    r| j        |z   }n0t          |t                    r| j        |j        z   }n| j        |gz   }t          |          S r:   )r/   rt   r  )r5   ar  s      r6   __add__zPath.__add__9  s[    a 	 	AAA4   	 	AF"AA	QCAAwwr8   c                     t          | j                  r+| j        d         dv rt          | j        dd                   S | S )z?Return a path relative to MF, i.e. without initial explicit MF.r   )r#   3F00rV   N)rR   rt   r  r<   s    r6   relative_to_mfzPath.relative_to_mfB  s?    ty>> 	'diln<<	!""&&&r8   c                     t          | j                  t          |j                  k    rdS |j        dt          | j                           | j        k    rdS dS )z6Is this instance a parent of the given other instance?FNTr/  r*  s     r6   	is_parentzPath.is_parentH  sL    ty>>S__,,5:os49~~o&$)334ur8   N)r?   r  )r   r   r   r   r	   r   r   r   r7   r=   r&  r   r+  r-  r0  r3  r6  r8  r   r8   r6   r  r    s       //+%T#YS	 9: + + + +# # # # #(# ( ( ( ('F 't ' ' ' '         v $      r8   r  )?r   typingr   r   r   r   r   r   r	   r;  r.  r  r  rT  r?  r
   r   smartcard.utilr   osmocom.utilsr   r   r   r   r   r   r   r   osmocom.tlvr   osmocom.constructr   r   r   pySim.utilsr   r   pySim.jsonpathr   pySim.commandsr   pySim.exceptionsr   r   r   r|  r   r*   r_   r0   r   r   r  r  r  r  r   r   r  r  ABCr  r  r   r8   r6   <module>rC     s@   2 F E E E E E E E E E E E E E E E E E    



   2 2 2 2 2 2 2 2 " " " " " " e e e e e e e e e e e e e e e e e e e e ( ( ( ( ( ( K K K K K K K K K K . . . . . . . . ) ) ) ) ) ) * * * * * * ) ) ) ) ) )
 T#Yc3h78S(3- AL AL AL AL AL AL AL ALHE E E E EX E E EPF F F F FV F F FRF F F F Ff F F F@    X   :" " " " "F " " "DP" P" P" P" P" P" P" P"f
m m m m mz m m mj  j  j  j  j  j  j  j Za" a" a" a" a"v a" a" a"H$ C    (*L *L *L *L *L *L *L *L\#  #  #  #  #  #  #  # L/ / / / / / / / / /r8   