.+i~) BdZddlmZmZmZddlmZddlmZm Z ddl m Z ddl Z ddl Z ddlZe jdZgZGdd ZGd d e jZGd d eZefdefdZefdeedededeeeffdZefdedededefdZdS)aObtaining card parameters (mostly key data) from external source. This module contains a base class and a concrete implementation of obtaining card key material (or other card-individual parameters) from an external data source. This is used e.g. to keep PIN/PUK data in some file on disk, avoiding the need of manually entering the related card-individual data on every operation with pySim-shell. )ListDictOptional)AES)h2bb2h) PySimLoggerNCARDKEYceZdZdZgdgdgdgdgddZdZed ed efd Zed ed efdZ d efdZ de de d e fdZ de de d e fdZ dS)CardKeyFieldCryptora A Card key field encryption class that may be used by Card key provider implementations to add support for a column-based encryption to protect sensitive material (cryptographic key material, ADM keys, etc.). The sensitive material is encrypted using a "key-encryption key", occasionally also known as "transport key" before it is stored into a file or database (see also GSMA FS.28). The "transport key" is then used to decrypt the key material on demand. )UICC_SCP02_KIC1UICC_SCP02_KID1UICC_SCP02_KIK1)UICC_SCP03_KIC1UICC_SCP03_KID1UICC_SCP03_KIK1)SCP03_ENC_ISDRSCP03_MAC_ISDRSCP03_DEK_ISDR)rSCP03_MAC_ISDASCP03_DEK_ISDA)SCP03_ENC_ECASDSCP03_MAC_ECASDSCP03_DEK_ECASD) UICC_SCP02 UICC_SCP03 SCP03_ISDR SCP03_ISDA SCP03_ECASDs################dreturnc>d|DS)Nc>i|]\}}||Supper).0kvs E/home/jenkins/workspace/simtester-sanitize/pySim/card_key_provider.py z.Ds&555CAaAGGIIa555items)r s r*__dict_keys_to_upperz(CardKeyFieldCryptor.__dict_keys_to_upperBs5517799555 5r,transport_keys crypt_groupscri}|D]\}}||vr||D]}|||<|||< |S)zPApply a single transport key to multiple fields/columns, if the name is a group.r-)r0r1new_dictnamekeyfields r*__process_transport_keysz,CardKeyFieldCryptor.__process_transport_keysFsi'--// % %ID#|##)$/**E&)HUOO*"%r,c||||j|_|jD]%\}}t d|d|&dS)ab Create new field encryptor/decryptor object and set transport keys, usually one for each column. In some cases it is also possible to use a single key for multiple columns (see also __CRYPT_GROUPS) Args: transport_keys : a dict indexed by field name, whose values are hex-encoded AES keys for the respective field (column) of the CSV. This is done so that different fields (columns) can use different transport keys, which is strongly recommended by GSMA FS.28 zEncrypting/decrypting field z using AES key N),_CardKeyFieldCryptor__process_transport_keys(_CardKeyFieldCryptor__dict_keys_to_upper"_CardKeyFieldCryptor__CRYPT_GROUPSr0r.logdebug)selfr0r4r5s r*__init__zCardKeyFieldCryptor.__init__Rs#;;Dr@rAciphers r* decrypt_fieldz!CardKeyFieldCryptor.decrypt_fieldb{!!T%888 T01A1A1C1CDEEs|UYU^__6>>#m"4"455666r, plaintext_valc8||jvr|Stjt |j|tj|j}t|t |S)a Encrypt a single field. The encryption is only applied if we have a transport key is known under the provided field name, otherwise the field is treated as non sensitive and passed through as it is. Args: field_name : name of the field to decrypt (used to identify which key to use) encrypted_val : encrypted field value Returns: plaintext field value ) r&r0rrCrrDrErencrypt)r>r@rJrGs r* encrypt_fieldz!CardKeyFieldCryptor.encrypt_fieldsrIr,N)__name__ __module__ __qualname____doc__r;rE staticmethoddictr:r9r?strrHrMr$r,r*r r ,s-TSSSSSPPPPPPTTT N D66666\6  T   \ [t[[[[ 77C7C7777"77C7C777777r,r c feZdZdZejdeedededeeeffdZ dZ dS) CardKeyProviderz7Base class, not containing any concrete implementation.fieldsr5valuer!cdS)a Get multiple card-individual fields for identified card. This method should not fail with an exception in case the entry, columns or even the key column itsself is not found. Args: fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained key : look-up key to identify card data, such as 'ICCID' value : value for look-up key to identify card data Returns: dictionary of {field : value, ...} strings for each requested field from 'fields'. In case nothing is fond None shall be returned. Nr$)r>rWr5rXs r*getzCardKeyProvider.getsr,c*t|jS)N)typerN)r>s r*__str__zCardKeyProvider.__str__sDzz""r,N) rNrOrPrQabcabstractmethodrrTrrZr]r$r,r*rVrVssAA  $s)  #  c  d38n      #####r,rVc VeZdZdZdedefdZdeedededeeeffd Z d S) CardKeyProviderCsvzSCard key provider implementation that allows to query against a specified CSV file. csv_filenamer0ct|d|_|jstd|z||_t ||_dS)z Args: csv_filename : file name (path) of CSV file containing card-individual key/data transport_keys : (see class CardKeyFieldCryptor) rzCould not open CSV file '%s'N)opencsv_file RuntimeErrorrbr crypt)r>rbr0s r*r?zCardKeyProviderCsv.__init__sO \3// } N= LMM M((88 r,rWr5rXr!c |jdtj|j}|st d|jzd|jD|_||jvrdSi}|D]h}|||krZ|D]W}||vr7|||j |||i=t d|jd|di|ikrdS|S)Nrz+Could not open DictReader for CSV-File '%s'c6g|]}|Sr$r%)r'r6s r* z*CardKeyProviderCsv.get..s BBB5BBBr,z CSV-File 'z' lacks column '') rfseekcsv DictReaderrgrb fieldnamesupdaterhrH)r>rWr5rXcr return_dictrowfs r*rZzCardKeyProviderCsv.gets  1 ^DM * * bLtO``aa aBBBMBBB bm # #4  g gC3x5  ggACxx#**Atz/G/G3q6/R/R+STTTT*lPTPaPaPacdcdcd+efff "  4r,N) rNrOrPrQrTrSr?rrrZr$r,r*rarasx]] 9S 9$ 9 9 9 9$s)#cd38nr,raprovidercxt|tstd||dS)zRegister a new card key provider. Args: provider : the to-be-registered provider provider_list : override the list of providers from the global default z$provider is not a card data providerN) isinstancerV ValueErrorappend)rv provider_lists r*card_key_provider_registerr|s@ h 0 0A?@@@"""""r,rWr5rXr!c |}d|D}|D]}t|tstdtd|d|dt |d||||}|r.tdt |z|cStd|d|d t |d) aQuery all registered card data providers for card-individual [key] data. Args: fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained key : look-up key to identify card data, such as 'ICCID' value : value for look-up key to identify card data provider_list : override the list of providers from the global default Returns: dictionary of {field, value} strings for each requested field from 'fields' c6g|]}|Sr$r%)r'rus r*rkz)card_key_provider_get..s ( ( (Aaggii ( ( (r,z@Provider list contains element which is not a card data providerz!Searching for card key data (key=z, value=z , provider=)zFound card data: %sz"Unable to find card key data (key=z , fields=)r&rxrVryr<r=rTrZ)rWr5rXr{presults r*card_key_provider_getrs ))++C ( ( ( ( (F !_-- a_`` ` SVSVSVX]X]X]_bcd_e_e_e_efgggvsE**   II+s6{{; < < <MMM  *UXUXUXZ_Z_Z_adekalalalalm n nnr,r6c|g}t|||t}||S)aQuery all registered card data providers for a single field. Args: field : name valid field such as 'ADM1', 'PIN1', ... which is to be obtained key : look-up key to identify card data, such as 'ICCID' value : value for look-up key to identify card data provider_list : override the list of providers from the global default Returns: dictionary of {field, value} strings for the requested field )rcard_key_providersrZr&)r6r5rXr{rWrs r*card_key_provider_get_fieldrs9WF "637I J JF ::ekkmm $ $$r,)rQtypingrrrCryptodome.Cipherr osmocom.utilsrr pySim.logr r^rnloggingrZr<rr ABCrVrar|listrTrrr$r,r*rs  :('''''''''!!!!!!""""""""!!!!!! koi  V7V7V7V7V7V7V7V7p#####cg###*""""""""LI[ # # # # # #Rdoo$s)o#ocohlmprumuhvoooo2Qc%%s%%S%gj%%%%%%r,