
    dio                         d Z ddlmZmZ ddlmZmZmZmZ ddl	m
Z
 ddlT ddlT ddlmZ  ej        e          Zdedefd	Z G d
 d          Z G d d          ZdS )zHRepresentation of the runtime state of an application like pySim-shell.
    )OptionalTuple)h2bi2his_hexHexstr)bertlv_parse_one)*)PySimLoggerclareturnc                 \    | dz	  dv r| dz  S | dz  dv rd| dz  z   S t          d| z            )z5Resolve the logical channel number from the CLA byte.   )r   
            )@         z/Could not determine logical channel for CLA=%2X)
ValueError)r   s    ;/home/jenkins/workspace/simtester-sanitize/pySim/runtime.pylchan_nr_from_clar      sO     ax?""Tz
Tz\!!C$J
FL
M
MM    c                   b    e Zd ZdZddZd Zdd	efd
Zded	dfdZ	defdZ
d	ed         fdZdS )RuntimeStatez5Represent the runtime state of a session with a card.cardCardBaseprofileCardProfilec                    t          |          | _        || _        || _        i | _        t          d|           | j        d<   i | _        d| _        | j                            | j        j	        | j        j
                   | j        d                             d           | j        j        D ]p} |            }|                    | j                  rJt                              d| j        d|d           |j        D ]}| j                            |           q| j        d                             d           |                                 }|D ](}|j        r| j                            |j                   )| j        j        D ]}| j                            |           d	| _        |                                  d
S )zo
        Args:
            card : pysim.cards.Card instance
            profile : CardProfile instance
        )r   r   F)r   sel_ctrlMFz	Detected z	 Add-on ""TN)CardMFmfr   r   lchanRuntimeLchanidentityadm_verifiedset_apdu_parameterr   r"   selectaddonsprobeloginfofiles_in_mfadd_file_match_applicationsadfadd_application_dfconserve_writereset)selfr   r   	addon_clsaddonfappsas           r   __init__zRuntimeState.__init__-   s    )))	
$Q--
1 ! 		$$ 4<+@ 	% 	B 	B 	B 	
1T""", 	( 	(IIKKE{{49%% (eeeLMMM* ( (AG$$Q'''' 	
1T""" '')) 	2 	2Au 2**15111) 	  	 AGQ" 	

r   c           	         | j         j        }|sg S | j                                        }g }|rg }t                              d           |D ]`}|D ][}|j        |v rPt                              d|j        d|d           |                    |           |                    |           \at          |          t          |          z
  }|D ]}t                              d|z              nt          
                    d           t          t          |          t          |          z
  t                    D ]}	 | j                            |j                  \  }}	|| _        |	dk    r?t                              d|j        d|j                   |                    |           r# t          t           f$ r Y w xY w|S )	zEmatch the applications from the profile with applications on the cardzAIDs on card: : z	 (EF.DIR)z unknown: %s (EF.DIR)zEF.DIR seems to be empty!)key9000)r   applicationsr   	read_aidsr/   r0   aidnameappendsetwarningsortedstrselect_adf_by_aidselected_adfSwMatchErrorProtocolError)
r8   apps_profile	aids_card
apps_taken
aids_takenr=   r;   aids_unknown_datasws
             r   r3   z RuntimeState._match_applications^   s   |0  	I I''))	
 	5JHH_%%% - -% - -Auzzqvvvqqq!ABBB"))!,,,"))!,,,	-
 y>>C
OO;L! 6 601455556 KK3444 L))C
OO;EEE 	 	A !I77>>	r$%!<<HHH!&&&!%%8999%%a((( -0   s   ?A.F..GGNr   c                    t          | j                                                  D ](}d| j        |         j        _        |dk    r | j        |= )d| _        | j                                        }|r| j        d         |_        | j        d                             d|           d| j        d         _	        || j
        d<   |S )zPerform physical card reset and obtain ATR.
        Args:
            cmd_app : Command Application State (for unregistering old file commands)
        Nr   Fr#   ATR)listr'   keyssccscpr*   r   r7   r,   rN   r)   )r8   cmd_applchan_nratrs       r   r7   zRuntimeState.reset   s     TZ__..// 	% 	%H+/DJx $(1}}
8$$!ioo 	* JqMGM
1T7+++%)
1""e
r   r_   r(   c                     || j                                         v rt          d|z            t          ||           | j         |<   | j         |         S )zAdd a logical channel to the runtime state.  You shouldn't call this
        directly but always go through RuntimeLchan.add_lchan().z'Cannot create already-existing lchan %d)r'   r[   r   r(   r8   r_   s     r   	add_lchanzRuntimeState.add_lchan   sR     tz((((FQRRR+Hd;;
8z(##r   c                 P    || j                                         v r
| j         |= dS dS )NTF)r'   r[   rb   s     r   	del_lchanzRuntimeState.del_lchan   s-    tz((((
8$45r   c                 t    t          |          }|| j                                        v r| j        |         S d S N)r   r'   r[   )r8   r   r_   s      r   get_lchan_by_clazRuntimeState.get_lchan_by_cla   s8    $S))tz((((:h''4r   )r   r   r   r    rg   )__name__
__module____qualname____doc__r>   r3   r   r7   intrc   re   r   rh    r   r   r   r   *   s        ??/ / / /b, , ,\ V    ,$# $. $ $ $ $#    x'?      r   r   c                   X   e Zd ZdZdedefdZdedd fdZdefdZ	de
fdZdefd	Zdefd
Zdee         fdZdee         fdZdee         fdZdee         fdZdee         fdZdefdZdee         fdZdedefdZdefdZd6defdZd7dee         fdZd6defdZd6defdZd Z defdZ!defdZ"d8d!ed"efd#Z#de$eef         fd$Z%d% Z&d& Z'd9d'ed"efd(Z(d)efd*Z)d9d+efd,Z*d9d+ede$eef         fd-Z+d+ed'efd.Z,d+ed)efd/Z-d9d0efd1Z.d2 Z/d0ed'efd3Z0d6d4Z1d6d5Z2dS ):r(   z=Represent the runtime state of a logical channel with a card.r_   rsc                     || _         || _        | j        j        j                            |          | _        | j        j        | _        d | _        d | _	        d | _
        d S rg   )r_   rp   r   _scc
fork_lchanr\   r&   selected_filerN   selected_file_fcpselected_file_fcp_hex)r8   r_   rp   s      r   r>   zRuntimeLchan.__init__   sX     7<$//99 "WZ !%%)"""r   r   c                     | j                             |          }| j        dk    r%|                                 |_        | j        |_        |S )zAdd a new logical channel from the current logical channel. Just affects
        internal state, doesn't actually open a channel with the UICC.r   )rp   rc   r_   get_cwdrt   rN   )r8   r_   	new_lchans      r   rc   zRuntimeLchan.add_lchan   sG     G%%h//	=A&*llnnI#%)%6I"r   c                 (    | j         d         d         S )Nfile_descriptorfile_descriptor_byte)ru   r8   s    r   selected_file_descriptor_bytez*RuntimeLchan.selected_file_descriptor_byte   s    %&789OPPr   c                 6    |                                  d         S )N	shareabler~   r}   s    r   selected_file_shareablez$RuntimeLchan.selected_file_shareable       1133K@@r   c                 6    |                                  d         S )N	structurer   r}   s    r   selected_file_structurez$RuntimeLchan.selected_file_structure   r   r   c                 6    |                                  d         S )N	file_typer   r}   s    r   selected_file_typezRuntimeLchan.selected_file_type   r   r   c                 B    | j         d                             d          S )Nr{   
num_of_recru   getr}   s    r   selected_file_num_of_recz%RuntimeLchan.selected_file_num_of_rec       %&78<<\JJJr   c                 B    | j         d                             d          S )Nr{   
record_lenr   r}   s    r   selected_file_record_lenz%RuntimeLchan.selected_file_record_len   r   r   c                 6    | j                             d          S )N	file_sizer   r}   s    r   selected_file_sizezRuntimeLchan.selected_file_size   s    %))+666r   c                 B    | j         d                             d          S )Nproprietary_informationreserved_file_sizer   r}   s    r    selected_file_reserved_file_sizez-RuntimeLchan.selected_file_reserved_file_size   s     %&?@DDEYZZZr   c                 B    | j         d                             d          S )Nr   maximum_file_sizer   r}   s    r   selected_file_maximum_file_sizez,RuntimeLchan.selected_file_maximum_file_size   s     %&?@DDEXYYYr   c                 \    t          | j        t                    r| j        S | j        j        S )z\Obtain the current working directory.

        Returns:
            CardDF instance
        )
isinstancert   CardDFparentr}   s    r   rx   zRuntimeLchan.get_cwd   s.     d(&11 	-%%%,,r   c                 |    | j         }|j        |k    r)t          |t                    r|S |j        }|j        |k    )dS )zoObtain the currently selected application DF (if any).

        Returns:
            CardADF() instance or NoneN)rt   r   r   CardADF)r8   nodes     r   get_application_dfzRuntimeLchan.get_application_df   sM     !kT!!$(( ;D kT!! tr   rG   c                     d|v r'|                     d          }|d         dk    rd|d<   n|g}|                                 }|D ]2}|                                }d}|D ]}||k    r
||         } n| dS 3|S )zObtain the file object from the file system tree by its name without actually selecting the file.

        Returns:
            CardFile() instance or None/r    r#   N)splitrx   get_selectables)r8   rG   pathlistfilepselectables
selectables          r   get_file_by_namezRuntimeLchan.get_file_by_name  s     $;;zz#H{b  "vH
 ||~~ 	 	A..00KD)  
??&z2DE #
 |tt  r   rW   c                     d}|                                  }|r.|j        }|r%t          |d          r|                    |          }|p| j        j                            |          S )zInterpret a given status word relative to the currently selected application
        or the underlying card profile.

        Args:
            sw : Status word as string of 4 hex digits

        Returns:
            Tuple of two strings
        Ninterpret_sw)r   applicationhasattrr   rp   r   )r8   rW   resr4   apps        r   r   zRuntimeLchan.interpret_sw(  st     %%'' 	+/C  +wsN33 +&&r**6dgo222666r   Nfidc           	         t          |dd          st          d|z            |                     |           	 | j                            |          \  }}nn# t
          $ ra}|                     |           |                     |j                  }|s|t          |j        d|d         d|d                   |d}~ww xY w| j
                            |          }|d         d	         d
         dk    r6t          |ddt          |                                          z   d          }n|d         d	         d         dk    r6t          |ddt          |                                          z   d          }n5t!          |ddt          |                                          z   d          }| j
                            |g           |                     |||           dS )zqBlindly try to select a file and automatically add a matching file
           object if the file actually exists.r   zNCannot select unknown file by name %s, only hexadecimal 4 digit FID is allowedrA   r   z -    Nr{   r|   r   dfzDF.z)dedicated file, manually added at runtime)r   sfidrG   descr   transparentzEF.z*elementary file, manually added at runtime)r   r   unregister_cmdsr\   select_filerO   _select_postr   	sw_actualRuntimeErrorrt   decode_select_responser   rL   upperTransparentEF
LinFixedEF	add_files)	r8   r   r^   data_swswmkselect_respr;   s	            r   
probe_filezRuntimeLchan.probe_file=  s'    c1a   	h`cffh h h 	W%%%	U (..s33KT33 	U 	U 	Ug&&&!!#-00A 	qtttQqTTJKKQTT	U (??EE()*@A+NRVVV3TC8H8H0HGI I IAA ,-.DEkRVccc!c53s88>>CSCS;S'SU U U 3TC@P@P8P$PR R R 	$$aS)))'1d+++++s   A 
C"AB>>Cr   c                     |rZ|| _         t          |t                    r|| _        |r'|| _        | j                             |          | _        nd | _        d | _        |                     |           d S rg   )rt   r   r   rN   rv   r   ru   register_cmds)r8   r^   r   select_resp_datas       r   r   zRuntimeLchan._select_postf  s      		.!%D$(( )$(! .-=*)-);)R)RSc)d)d&&-1*)-& 	7#####r   c                 t   t          |t                    s| j        r| j        j        dk    r| j        j                                                                        D ]Q}t          |d         t                    r4|d         j        dk    r#|                     |d         j	        |            nR| j
                            |          }|st          d| j
        d|          |                     |           | j
        }| j        }|D ]}	 t          |t                    r/| j        j                            |j        | j                  \  }}n"| j                            |j                  \  }}|}l# t*          $ r}	|                     |||           |	d}	~	ww xY w|                     |||           dS )zSelect a file (EF, DF, ADF, MF, ...).

        Args:
            file : CardFile [or derived class] instance
            cmd_app : Command Application State (for unregistering old file commands)
        Fr   TzCannot determine path from z to )r\   N)r   r   rN   has_fsrp   r&   r   itemsr,   rG   rt   build_select_path_tor   r   rv   r   rM   rF   r\   r   r   rO   r   )
r8   r   r^   r   
inter_pathrt   r   r;   r   r   s
             r   r   zRuntimeLchan.select_filew  s    $(( 	T-> 	4CTC[_dCdCd #gj88::@@BB  
jmW55 *Q-:NRV:V:VKK
1 2G<<<E '<<TBB
 	c,HZHZHZ\`\`abbb 	W%%% *) 	 	A a)) >"&',"@"@DH"@"U"UKT33"&("6"6qu"="=KT3 !   !!'=$???	 	'1d+++++s   A(E66
F FFc                 J   | j         }d|v rs|                    d          }|d         dk    rd|d<   	 |D ]}|                     ||           | j        S # t          $ r}|                     ||           |d}~ww xY w| j                                         }t          |          r|                                }	 ||v r|                     ||         |           n| 	                    ||           n*# t          $ r}|                     ||           |d}~ww xY w| j        S )zSelect a file (EF, DF, ADF, MF, ...).

        Args:
            name : Name of file to select
            cmd_app : Command Application State (for unregistering old file commands)
        r   r   r   r#   N)
rt   r   r,   ru   	Exceptionr   r   r   lowerr   )r8   rG   r^   prev_sel_filer   r   eselss           r   r,   zRuntimeLchan.select  sb    * $;;zz#H{b  "! , ,AKK7++++--     888 !1133$<< 	 ::<<D	t||  dW5555g... 	 	 	]G444G	 %%s/   !A 
A<A77A<<7C4 4
D>DDc                 n    | j                                         \  }}| j                            |          S )z5Request STATUS (current selected file FCP) from card.)r\   statusrt   r   )r8   r   r   s      r   r   zRuntimeLchan.status  s.    hoo''s!88>>>r   c                     t          |          r|                                }| j                                        }||         S )z9Get the related CardFile object for a specified filename.)r   r   rt   r   )r8   rG   r   s      r   get_file_for_filenamez"RuntimeLchan.get_file_for_filename  s;    $<< 	 ::<<D!1133Dzr   c                     t          |          r|                                }| j                                        }||         }| j                            |j                  \  }}||fS )z(Request ACTIVATE FILE of specified file.)r   r   rt   r   r\   activate_filer   )r8   rG   r   r;   r   rW   s         r   r   zRuntimeLchan.activate_file  s^    $<< 	 ::<<D!1133J8))!%00bRxr   r   lengthoffsetc                     t          | j        t                    s)t          d| j        d| j        j        j                  | j                            | j        j        ||          S )a  Read [part of] a transparent EF binary data.

        Args:
            length : Amount of data to read (None: as much as possible)
            offset : Offset into the file from which to read 'length' bytes
        Returns:
            binary data read from the file
        #Only works with TransparentEF, but  is )	r   rt   r   	TypeError	__class____mro__r\   read_binaryr   )r8   r   r   s      r   r   zRuntimeLchan.read_binary  sq     $,m<< 	t)TM_M_M_MQM_MiMqMqs t t tx##D$6$:FFKKKr   c                 l    |                                  \  }}| j                            |          }||fS )a+  Read [part of] a transparent EF binary data and decode it.

        Args:
            length : Amount of data to read (None: as much as possible)
            offset : Offset into the file from which to read 'length' bytes
        Returns:
            abstract decode data read from the file
        )r   rt   
decode_hex)r8   r   rW   dec_datas       r   read_binary_deczRuntimeLchan.read_binary_dec  s9     %%''
r%0066"~r   c                 2   | j         }|sdS |                    di                               di                               d          }|sdS |dk    r|                    d          S |dk    r)|                    di                               d          S dS )	z Determine the writable size (file or record) using the cached FCP parameters of the currently selected
            file. Return None in case the writeable size cannot be determined (no FCP available, FCP lacks size
            information).
        Nr{   r|   r   r   r   linear_fixedr   r   )r8   fcpr   s      r   __get_writeable_sizez!RuntimeLchan.__get_writeable_size
  s    
 $ 	4GG-r22667MrRRVVWbcc	 	4%%77;'''.((77,b1155lCCC4r   c                 F   |                                  }|sdS t          | j        t                    rd}nt          | j        t                    rd}nd}||k    rt          d|||||z
  fz            ||k     r't                              d|||||z
  |fz             dS dS )zb Guard against unsuccessful writes caused by attempts to write data that exceeds the file limits. Nr   recordobjectz1Data length (%u) exceeds %s size (%u) by %u byteszXData length (%u) less than %s size (%u), leaving %u unwritten bytes at the end of the %s)!_RuntimeLchan__get_writeable_sizer   rt   r   r   r   r/   rJ   )r8   data_lenwriteable_sizewriteable_names       r   __check_writeable_sizez#RuntimeLchan.__check_writeable_size  s     2244 	Fd(-88 	&#NN*J77 	&%NN%Nn$$O%~~xR`G`ab c c c&&KKr!>>>T\C\^lmn o o o o o '&r   data_hexc                 <   t          | j        t                    s)t          d| j        d| j        j        j                  |                     t          |          dz  |z              | j        	                    | j        j
        ||| j        j                  S )zUpdate transparent EF binary data.

        Args:
            data_hex : hex string of data to be written
            offset : Offset into the file from which to write 'data_hex'
        r   r      conserve)r   rt   r   r   r   r   #_RuntimeLchan__check_writeable_sizelenr\   update_binaryr   rp   r6   )r8   r   r   s      r   r  zRuntimeLchan.update_binary3  s     $,m<< 	t)TM_M_M_MQM_MiMqMqs t t t##CMMQ$6$?@@@x%%d&8&<hY]Y`Yo%pppr   r   c                     | j                             ||                                           }|                     |          S )zUpdate transparent EF from abstract data. Encodes the data to binary and
        then updates the EF with it.

        Args:
            data : abstract data which is to be encoded and written
        )rt   
encode_hexr   r  )r8   r   r   s      r   update_binary_deczRuntimeLchan.update_binary_dec@  s<     %00t7N7N7P7PQQ!!(+++r   rec_nrc                     t          | j        t                    s)t          d| j        d| j        j        j                  | j                            | j        j        |          S )zRead a record as binary data.

        Args:
            rec_nr : Record number to read
        Returns:
            hex string of binary data contained in record
        %Only works with Linear Fixed EF, but r   )	r   rt   r   r   r   r   r\   read_recordr   )r8   r  s     r   r  zRuntimeLchan.read_recordJ  sq     $,j99 	v)tOaOaOaOSOaOkOsOsu v v v x##D$6$:FCCCr   c                 l    |                      |          \  }}| j                            ||          |fS )zRead a record and decode it to abstract data.

        Args:
            rec_nr : Record number to read
        Returns:
            abstract data contained in record
        )r  rt   decode_record_hex)r8   r  r   rW   s       r   read_record_deczRuntimeLchan.read_record_decX  s9     %%f--
r"44T6BBBGGr   c                 L   t          | j        t                    s)t          d| j        d| j        j        j                  |                     t          |          dz             | j        	                    | j        j
        ||| j        j        | j        j                  S )zUpdate a record with given binary data

        Args:
            rec_nr : Record number to read
            data_hex : Hex string binary data to be written
        r  r   r   )r   leftpad)r   rt   r   r   r   r   r   r   r\   update_recordr   rp   r6   r  )r8   r  r   s      r   r  zRuntimeLchan.update_recordc  s     $,j99 	v)tOaOaOaOSOaOkOsOsu v v v##CMMQ$6777x%%d&8&<fhW+&. & 0 0 	0r   c                     | j                             |||                                           }|                     ||          S )zUpdate a record with given abstract data.  Will encode abstract to binary data
        and then write it to the given record on the card.

        Args:
            rec_nr : Record number to read
            data_hex : Abstract data to be written
        )rt   encode_record_hexr   r  )r8   r  r   r   s       r   update_record_deczRuntimeLchan.update_record_decr  s@     %77fdFcFcFeFeff!!&(333r   tagc                     t          | j        t                    st          d          | j                            | j        j        |          S )zRead a DO/TLV as binary data.

        Args:
            tag : Tag of TLV/DO to read
        Returns:
            hex string of full BER-TLV DO including Tag and Length
        zOnly works with BER-TLV EF)r   rt   BerTlvEFr   r\   retrieve_datar   )r8   r  s     r   r  zRuntimeLchan.retrieve_data}  sF     $,h77 	:8999x%%d&8&<cBBBr   c                 8   t          | j        t                    s)t          d| j        d| j        j        j                  | j                            | j        j        d          \  }}t          t          |                    \  }}}}t          |          S )zrRetrieve tags available on BER-TLV EF.

        Returns:
            list of integer tags contained in EF
         Only works with BER-TLV EF, but r   \   )r   rt   r  r   r   r   r\   r  r   r	   r   rZ   )r8   r   r   _tag_lengthvalue
_remainders          r   retrieve_tagszRuntimeLchan.retrieve_tags  s     $,h77 	q)$J\J\J\JNJ\JfJnJnp q q qH**4+=+A4HH	c+;CII+F+F(gujE{{r   c                     t          | j        t                    s)t          d| j        d| j        j        j                  | j                            | j        j        ||| j	        j
                  S )zUpdate a TLV/DO with given binary data

        Args:
            tag : Tag of TLV/DO to be written
            data_hex : Hex string binary data to be written (value portion)
        r  r   r   )r   rt   r  r   r   r   r\   set_datar   rp   r6   )r8   r  r   s      r   r  zRuntimeLchan.set_data  s}     $,h77 	q)$J\J\J\JNJ\JfJnJnp q q qx  !3!7hQUQXQg hhhr   c                 r    |r0| j         j        r&| j         j        D ]}|                    |           dS dS dS )zHRegister command set that is associated with the currently selected fileN)rt   shell_commandsregister_command_setr8   r^   cs      r   r   zRuntimeLchan.register_cmds  sa     	0t)8 	0'6 0 0,,Q////	0 	0 	0 	00 0r   c                 r    |r0| j         j        r&| j         j        D ]}|                    |           dS dS dS )zJUnregister command set that is associated with the currently selected fileN)rt   r!  unregister_command_setr#  s      r   r   zRuntimeLchan.unregister_cmds  sa     	2t)8 	2'6 2 2..q1111	2 	2 	2 	22 2r   rg   )NN)Nr   )r   )3ri   rj   rk   rl   rm   r   r>   rc   dictr~   boolr   rL   r   r   r   r   r   r   r   r   r   rx   r   r   CardFiler   r   r   r   r   r,   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r   r   rn   r   r   r(   r(      s       GG	* 	*, 	* 	* 	* 	*# .    Qt Q Q Q QA A A A AA A A A AAC A A A AK(3- K K K KK(3- K K K K7HSM 7 7 7 7[(3- [ [ [ [Z# Z Z Z Z	- 	- 	- 	- 	-HW$5    "S "X " " " "H7s 7 7 7 7*', ',c ', ', ', ',R$ $(); $ $ $ $"7, 7, 7, 7, 7, 7,r(& (&3 (& (& (& (&T? ? ?
#    #    L L# Lc L L L LtSy!1      (o o o*q qc q3 q q q q,d , , , ,D D# D D D D	H 	Hc 	H%c	2B 	H 	H 	H 	H0C 03 0 0 0 0	4 	44 	4 	4 	4 	4C C C C C C  
iC 
i3 
i 
i 
i 
i0 0 0 02 2 2 2 2 2r   r(   N)rl   typingr   r   osmocom.utilsr   r   r   r   osmocom.tlvr	   pySim.exceptionspySim.filesystem	pySim.logr   r   ri   r/   rm   r   r   r(   rn   r   r   <module>r0     s/   $ # " " " " " " " 2 2 2 2 2 2 2 2 2 2 2 2 ( ( ( ( ( (         ! ! ! ! ! !koh	N3 	N3 	N 	N 	N 	NL L L L L L L L^t2 t2 t2 t2 t2 t2 t2 t2 t2 t2r   