g~ dZddlZddlZddlZddlZddlZddlmZddlm Z m Z m Z m Z m Z mZmZddlTddlmZmZedeZedeZe eefZd efd Zd ed e efd Zd ed efdZded efdZdeeefd efdZdeded efdZded e fdZ!ded efdZ"ded efdZ#ded efdZ$ded efdZ%ded e efdZ&ded e ee ffdZ'ded e fd Z(d!ed"ed efd#Z)d efd$Z*d%efd&Z+d ed e efd'Z,dRd ed)e-d e efd*Z.d+ed,ed-ed efd.Z/dSd+ed,ed-ed efd0Z0dTd efd1Z1d2Z2d3ed4ed e-fd5Z3 dUd:ed;edZ4d?Z5dVdAZ6dBe7d efdCZ8GdDdEej9Z:GdFdGe:Z;GdHdIZ<GdJdKe<Z=GdLdMZ>GdNdOZ?GdPdQZ@dS)Wz pySim: various utilities N)BytesIO)OptionalListDictAnyTupleNewTypeUnion)*)bertlv_encode_tagbertlv_encode_lenSwHexstr SwMatchstrimsic tt|dz}t|dz}d|ztd|dzdzt|dfzz}|S)z7Converts a string IMSI into the encoded value of the EF%02xz%01x%s) half_round_uplen swap_nibblesrpad)rloeeis ;/home/jenkins/workspace/simtester-sanitize/./pySim/utils.pyenc_imsir4sb D A   A TQB !l8a1}d4nn.M#MNN NB Iefreturncvt|dkrdSt|ddddz}|dz }t|ddd}t|dkrdSt|ddz dz}|s|dz }|t|dz krdS|dd}|S) z6Converts an EF value to the IMSI string representationNrrfr)rintrrstrip)r rswappedrrs rdec_imsir*=s 2ww{{t BqsGR1A AA2abb6""))#..G 7||at gaj//Q ! #B  aCCLL1 t 122;D KrcFt|dS)Nr&)rstrip)r s r dec_iccidr-Ps    ! !# & &&riccidc<tt|dS)N)rrr.s r enc_iccidr2Ts UB ( ((rct|}t|dkrtdt|dkrtdt|dkr|tt|z }t|dkrt |t|dkr@ t |n/#t$r"|tt|z }YnwxYw|S)Nz,ICCID input value must be at least 18 digitsr0z+ICCID input value must be at most 20 digits)strr ValueErrorcalculate_luhn verify_luhnr1s rsanitize_iccidr:Ws JJE 5zzBGHHH 5zzBFGGG 5zzR ^E**+++ 5zzR E 5zzR 0      0 0 0 S..// /EEE 0 Ls<C )C87C8mccmncc|}|}t|dkrd}n4t|dkr d|zdz}nt|dkr|dz }t|dkrd}n1t|dkrd|z}nt|dkrd|z}|d|dz|d|dzz|d|dzzS)z,Converts integer MCC/MNC into 3 bytes for EFrFFFr0Fr$00)r,rr;r<s renc_plmnrCps ))++C ))++C 3xx1}} SQCi#o SQ s  3xx1}} SQSj SQCi FSVOAQ 0CFSVO DDr threehexbytescvddd}t|t||d<t||d<|S)Nr?rBr;r<dec_mcc_from_plmn_strdec_mnc_from_plmn_str)rDress rdec_plmnrJsDc " "C-(((&}55CJ&}55CJ Jrplmnct|}|ddz}|ddzdz }|ddz}|dkr|dkr|dkrdSt|||S)Nrrr#r)h2i derive_mccrKiadigit1digit2digit3s rdec_mcc_from_plmnrVsi TB UT\Fedlq F UT\F }}36S==u fff - --rc|d}|d}|d}||z|z}|dS)Nrrrr@upperr,rKrSrTrUrIs rrGrGG !WF !WF !WF 6/F "C 99;;  S ! !!rct|}|ddz}|ddzdz }|ddzdz }|dkr|dkr|dkrdSt|||S)Nr$rrMr#rrN)rO derive_mncrQs rdec_mnc_from_plmnr^sn TB UT\Fedlq Fedlq F }}36S==u fff - --rc|d}|d}|d}||z|z}|dS)Nr#r$r@rXrZs rrHrHr[r twohexbytescddddddddddd dd d dg}t|}|d d z|dz}t}|D]+}|d|dzzr||d,|dz}|dvr+|d|dn7|dkr|dn|dkr|d|dz}|dvr+|d|dn=|dzdkr|dn|dzdkr|dtt |S)NrUTRAN)bitname zNG-RANz GSM COMPACTr`z cdma2000 HRPDr#zcdma2000 1xRTTrrrdrep)i@riz E-UTRAN WB-S1z E-UTRAN NB-S1iPi`)rjGSMz EC-GSM-IoT)rOsetaddsortedlist)raact_listrRu16tsela eutran_bitsgsm_bitss rdec_actrysG$$H%%M**O,,,-- H [  B qEQJ"Q% D %%C  1%= !  GGAfI   -K&&&                      f}H###    &   &    $s))  r fivehexbytescddgd}d}d}|d|}||||z}t||d<t||d<t||d<|S)Nr?r;r<actrgr#r;r<r})rGrHry)rzrI plmn_chars act_charsplmn_stract_strs rdec_xplmn_w_actrsuc" - -CJIKZK(H:j9&<<=G&x00CJ&x00CJ!!CJ Jrcrddgd}d}|d|}t||d<t||d<|S)Nrr|rgr;r<rF)rDrIr~rs r dec_xplmnrsKAb ) )CJ[j[)H&x00CJ&x00CJ Jrki_hexop_hexcddlm}ddlm}t t |}t t |}|||j}||}t|||S)zD Run the milenage algorithm to calculate OPC from Ki and OP r)AES)strxor) Cryptodome.CipherrCryptodome.Util.strxorrbytesh2bnewMODE_ECBencryptb2h)rrrrki_bytesop_bytesaes opc_bytess rderive_milenage_opcrs&%%%%%------S[[!!HS[[!!H ''(CL ) )C H%%I vvi** + ++rc tttt|}dt |dddd|dddDzdzz }|dkrdn|S)z= Calculate Luhn checksum used in e.g. ICCID and IMEI NcNg|]"}tt|dzd#S)r$r)sumdivmod).0ds r z"calculate_luhn.. s>*/*/*/ +.fQUB.?.?*@*@*/*/*/rr)rrmapr'r6r)ccnum check_digits rr8r8s s3B  ! !Cs3rv2v;*/*/$'"I*/*/*//002455Kr!!11{2rdigitsct|dd}t||dkr(tdt|d|ddS)zBVerify the Luhn check digit; raises ValueError if it is incorrect.Nz%Luhn check digit mismatch: should be z but is )r8r6r7)rcds rr9r9sc ss $ $B 2ww&*jPSTVPWPWPWPWY_`bYcYcdeeercH|dSt|dkr |ddSdS)zU Derive the MCC (Mobile Country Code) from the first three digits of an IMSI Nrr)rs r mcc_from_imsirs/ |t 4yy1}}BQBxtrFlongc`|dSt|dkr|r |ddS|ddSdS)zS Derive the MNC (Mobile Country Code) from the 4th to 6th digit of an IMSI Nrrgr`r)rrs r mnc_from_imsir"sF |t 4yy1}}  !9 !9 trrSrTrUcXd}|dkr||dzz }|dkr||dzz }|dkr||z }|S)ze Derive decimal representation of the MCC (Mobile Country Code) from three given digits. rrdr)rSrTrUr;s rrPrP2sN C ~~ v| ~~ v{ ~~ v  Jrrcjd}|dkrt|||S|dkr||dzz }|dkr||z }|S)zy Derive decimal representation of the MNC (Mobile Network Code) from two or (optionally) three given digits. rrr)rP)rSrTrUr<s rr]r]DsT C~~&&&111 ~~ v{ ~~ v  Jrc`|Rt|dkr0dd|D}t|d}ntd|Wt|dkr5|} t |}n1#t$r}td|d}~wwxYwtd|S) a The ADM pin can be supplied either in its hexadecimal form or as ascii string. This function checks the supplied opts parameter and returns the pin_adm as hex encoded string, regardless in which form it was originally supplied by the user Nrhc2g|]}dt|zS)r)ordrxs rrz$sanitize_pin_adm..bs#BBBQvQ0BBBrr%z&PIN-ADM needs to be <=8 digits (ascii)z1PIN-ADM needs to be hex encoded using this optionz3PIN-ADM needs to be exactly 16 digits (hex encoded))rjoinrr7r)pin_adm pin_adm_hex try_encodeexcs rsanitize_pin_admrXs w<<1  ggBB'BBBCCG7B''GGEFF F {  r ! !!G _ \\  _ _ _ !TUU[^^ _RSS S Ns-A== BBBct|dkrdS|d} ddl}||}|jdkrdS|jdkrdSn:#t $r-d}|D] }ddl}|d |sd }n!|rYdSYnwxYwd}|D] }ddl}|d |sd }n!|rdSdS) z Validates the given address and returns it's type (FQDN or IPv4 or IPv6) Return: 0x00 (FQDN), 0x01 (IPv4), 0x02 (IPv6), None (Bad address argument given) TODO: Handle IPv6 rN.r#rrgr$Tz ^[0-9_]+$Fz ^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)?$)rsplit ipaddress ip_addressversion Exceptionrematch)addr addr_listripa invalid_ipv4ir fqdn_flags r get_addr_typervsG 4yyA~~t 3I""4(( ;!  4 [A  4       A III88K++ $    44   I  xx:A>> I E  t 4s$A  A 1BBswpatternc|}d}tddD]1}||dkr|dz}||dkr|dz}&|||z}2||kS)z%Match given SW against given pattern.rrr#?r)lowerrange)rrsw_lower sw_maskedrs rsw_matchrs|xxzzHI 1a[[00 1:  !CII QZ3  !CII!HQK/II  rOr$rTwidthhspacelspace align_leftc|dSt|dkrdSt|t}t||z}||z}t|dz |zdz}g} tt|D]V} || d|} |rd} nd} | |zt| z} d|z| z} | | t | zWd | S) aZPretty print a list of strings into a tabulated form. Args: width : total width in characters per line space : horizontal space between cells lspace : number of spaces before row align_lef : Align text to the left side Returns: multi-line string containing formatted table Nrr)keyrz%%-%dsz%%%ds  )rmaxiterrappendtupler)str_listrrrr longest_strcellwithcolsrowstabler str_list_rowformat_str_cellformat_str_rows rtabulate_str_listrs r 8}}rhC(((K;&(H H D MMA $ & *D E %++  ;;4(  &&OO%O)H4L8I8II,.8 ^eL&9&99:::: 99U  rc`|ddkrk|d}|dkr ||dz }n ||dz}|dzt|dz z }|dkr|S|d||zS|ddkrt|dzr|S|d}|dzr|S|dkr||dz |}n||dz|dz}|dzt|dz z }|dkr|S|d||dzzS|S)apExpand a given hexstring to a specified length by replacing "." or ".." with a filler that is derived from the neighboring nibbles respective bytes. Usually this will be the nibble respective byte before "." or "..", execpt when the string begins with "." or "..", then the nibble respective byte after "." or ".." is used.". In case the string cannot be expanded for some reason, the input string is returned unmodified. Args: hexstring : hexstring to expand length : desired length of the resulting hexstring. Returns: expanded hexstring rrrr$z..r#)countindexrreplace) hexstringlengthposfillermissings r expand_hexrsm sq  ooc"" 77sQw'FFsQw'F1*I 23 a<<   fw&6777   ! # # y>>A   ood## 7   77sQws{+FFsQws1u}-F1*I 23 a<<   vA'>??? rPct||dz krt|dz}d|z}dt|dz zdz}|||zz }|d|zz }|S)z0Generate a string that contains a boxed heading.r##z # %-zs # )rr6)headingrrIfstrs rboxed_heading_strrsm 7||eaiG q  +C c%!)nn $w .D47 C3;C Jrapduc Ht|dkr d}d}d}d|||fSt|dkrd}|d}|dkrd}d}d|||fSt|dkr|d}|dkrd}|d|dz}t|d|zkrd}d|||fSt|d|zdzkr|d|z}|dkrd}d|||fStd t|||t|dd fztd t|z) a*Parse a given command APDU and return case (see also ISO/IEC 7816-3, Table 12 and Figure 26), lc, le and the data field. Args: apdu : hexstring that contains the command APDU Returns: tuple containing case, lc and le values of the APDU (case, lc, le, data) r#rrrr`r$rzRinvalid APDU (%s), Lc=0x%02x (%d) does not match the length (%d) of the data fieldNzinvalid APDU (%s), too short!)rr7r)rlcledatas rparse_command_apdursm 4yyA~~  2r4  Ta  !W 77B2r4  TQ !W 77BAbdF| t99B  Br2t$ $ YY!b&1* $ $a"fBQwwr2t$ $q #D 2r3tABBx==ABCC C83t99DEEErceZdZdZddedeedeefdZdZdefd Z dd Z dd Z defdZ de fdZejdefdZejdefdZdedefdZdefdZdedee effdZdefdZdS) DataObjecta_A DataObject (DO) in the sense of ISO 7816-4. Contrary to 'normal' TLVs where one simply has any number of different TLVs that may occur in any order at any point, ISO 7816 has the habit of specifying TLV data but with very spcific ordering, or specific choices of tags at specific points in a stream. This class tries to represent this.NredesctagcL||_||_||_d|_d|_dS)z Args: name: A brief, all-lowercase, underscore separated string identifier desc: A human-readable description of what this DO represents tag : The tag associated with this DO N)rerrdecodedencoded)selfrerrs r__init__zDataObject.__init__Rs+    rc|jSNrer s r__str__zDataObject.__str___ yrr!c&|jd|jdS)N()) __class__rers r__repr__zDataObject.__repr__bs>>>499955rDataObjectChoicec`t|trtd||gSt)z7OR-ing DataObjects together renders a DataObjectChoice.Nmembers) isinstancerr TypeErrorr others r__or__zDataObject.__or__es0 eZ ( ( #D4-@@@ @OrDataObjectCollectionc`t|trtd||gSt)zCompute the tag (sometimes the tag encodes part of the value).rrs r _compute_tagzDataObject._compute_tagus xrc|j|jiS)z,Return a dict in form "name: decoded_value" )rer rs rto_dictzDataObject.to_dictys 4<((rdocdS)zParse the value part of the DO into the internal state of this instance. Args: do : binary encoded bytes Nr)r r*s r from_byteszDataObject.from_bytes}rcdS)zEncode the internal state of this instance into the TLV value part. Returns: binary bytes encoding the internal state Nrrs rto_byteszDataObject.to_bytesr-rc|d|jkrtd||jfz|d}|dd|z}|||d|zdS)aSParse binary TLV representation into internal state. The resulting decoded representation is _not_ returned, but just internalized in the object instance! Args: do : input bytes containing TLV-encoded representation Returns: bytes remaining at end of 'do' after parsing one TLV/DO. rz%s: Can only decode tag 0x%02xrr$N)rr7r,)r r*rvals rfrom_tlvzDataObject.from_tlvsw a5DH  ="DH-.// /A1V8n !F())}rc|}t|tt |z|zS)zpEncode internal representation to binary TLV. Returns: bytes encoded in TLV format. )r/r r'r r)r r1s rto_tlvzDataObject.to_tlvsE mmoo !2!2!4!4558I#c((8S8SSVYYYrbinaryc|d}||jkrtd||||jfz||}||fS)zDecode a single DOs from the input data. Args: binary : binary bytes of encoded data Returns: tuple of (decoded_result, binary_remainder) rz-%s: Unknown Tag 0x%02x in %s; expected 0x%02x)rr7r2r))r r5r remainders rdecodezDataObject.decodesdQi $(??L"C:;<< <MM&))   **rc*|Sr)r4rs rencodezDataObject.encodes{{}}rNNr!rr!r")__name__ __module__ __qualname____doc__r6rr'r rrr!r$r'dictr)abcabstractmethodrr,r/r2r4rr8r:rrrrrLsQQ  S  8C=    6#6666c)))))  U      %    5U"ZZZZZ +U +uT5['9 + + + +rrcJeZdZdZd dededeffd ZdefdZd efd Z xZ S) TL0_DataObjectz2Data Object that has Tag, Len=0 and no Value part.Nrerrc\t|||||_dSr)superr r1)r rerrr1rs rr zTL0_DataObject.__init__s* tS)))rr5cRt|dkrt|j|_dSNr)rr7r1r )r r5s rr,zTL0_DataObject.from_bytess& v;;!   x rr!cdS)Nrrrs rr/zTL0_DataObject.to_bytesssrr) r>r?r@rAr6r'r rr,r/ __classcell__)rs@rrFrFs<<S#     %rrFc|eZdZdZd dedeefdZdefdZdefdZdd Z d e de e e ffd Z de fd ZdS)r"zA DataObjectCollection consits of multiple Data Objects identified by their tags. A given encoded DO may contain any of them in any order, and may contain multiple instances of each DO.Nrerc||_||_|pg|_i|_i|_d|D|_d|D|_dS)Nci|] }|j| Srr&rms r z1DataObjectCollection.__init__..s999Aqua999rci|] }|j| SrrrPs rrRz1DataObjectCollection.__init__..s;;;a;;;r)rerrmembers_by_tagmembers_by_name)r rerrs rr zDataObjectCollection.__init__s]  }"  !99999;;7;;;rr!cdd|jD}|jdd|dS)Nc,g|]}t|Srr6rs rrz0DataObjectCollection.__str__..s444!s1vv444rr,r)rrerr  member_strss rrzDataObjectCollection.__str__s:44t|444 999chh{&;&;&;&;<.s5551tAww555rrrYr)rrrrZs rrzDataObjectCollection.__repr__s:55 555 >>>388K+@+@+@+@AArct|tr*|j|jz}t|j|j|St|t r$t|j|j|j|gzSt )zDExtending DataCollections with other DataCollections or DataObjects.)rr"rrerrrr r rs rr$zDataObjectCollection.__add__so e1 2 2 lU]2G' 49gFF F z * * ' 49dleW>TUU UOrr5cpg}|}t|r|d}|dkr||fS||jvr-td||||jfz|j|}||}||t|||fS)aDecode any number of DOs from the collection until the end of the input data, or uninitialized memory (0xFF) is found. Args: binary : binary bytes of encoded data Returns: tuple of (decoded_result, binary_remainder) r)%s: Unknown Tag 0x%02x in %s; expected %s)rrTr7keysr2rr))r r5rIr7robjs rr8zDataObjectCollection.decodes )nn &A,Cd{{Y''$--- !L"&Y8K8P8P8R8R!S"TUUU%c*C Y//I JJs{{}} % % %)nn &Yrct}|D]D}||d}||E|SrJ) bytearrayrUrr4)r r rIrrfs rr:zDataObjectCollection.encodesSkk % %A&&qt,,C JJszz|| $ $ $ $ rr;r=)r>r?r@rAr6rr rrr$rrrr8r:rrrr"r"s< !d)))H"C1D1I1I1K1KLMNN N!#&LL((  y))rc|jt|d}t|d|_|SrJ)rUrrvaluesr r4)r r rfs rr:zDataObjectChoice.encode5sF"4==#347>>++,,Q/ zz||rNr<) r>r?r@rAr$r!rrrBr8r:rrrrr s    *U*uT5['9****$rrceZdZdZddedeefdZdefdZdefdZdd Z d e de e e ffd Z d e de e e ffd Zde fdZde fdZdS)DataObjectSequenceaDA sequence of DataObjects or DataObjectChoices. This allows us to express a certain ordered sequence of DOs or choices of DOs that have to appear as per the specification. By wrapping them into this formal DataObjectSequence, we can offer convenience methods for encoding or decoding an entire sequence.Nrerc4|pg|_||_||_dSr)sequencerer)r rerrrs rr zDataObjectSequence.__init__As B   rr!cdd|jD}|jdd|dS)Nc,g|]}t|SrrXrs rrz.DataObjectSequence.__str__..Gs555!s1vv555rrrYr)rrrerrZs rrzDataObjectSequence.__str__Fs:55t}555 999chh{&;&;&;&;<.Ks6661tAww666rrrYr)rrrrrZs rrzDataObjectSequence.__repr__Js:66 666 >>>388K+@+@+@+@AArcFt|dr$t|j|j|j|gzSt|dr$t|j|j|j|gzSt|dr(t|j|j|j|jzSdS)z>Add (append) a DataObject or DataObjectChoice to the sequence.rrrpN)rrprerrrrs rr$zDataObjectSequence.__add__Ns e\ * * \%diDMUGr?r@rAr6rr rrr$rrrrr8r}r:rrrrrprp;s(77 S  =====B#BBBB\\\\  U  uT5['9      u tU{);    * u      rrpc,eZdZdZddZdZdZdZdS) CardCommandz$A single card command / instruction.Ncn||_||_|pg|_d|jD|_||_dS)Nc6g|]}|Sr)rrs rrz(CardCommand.__init__..s :::q:::r)reinscla_listr)r rerrrs rr zCardCommand.__init__s=  B ::DM:::  rc|jSrrrs rrzCardCommand.__str__rrc0d|j|j|jfzS)Nz%s(INS=%02x,CLA=%s))rerrrs rrzCardCommand.__repr__s$ 48T]'KKKrct|tsd|z}|}|jD]=}d}t ddD]}||dkr|dz }|||z } ||krdS>dS)z6Does the given CLA match the CLA list of the command?.z%02urrr$rTF)rr6rrr)r cla cla_match cla_maskedrs r match_clazCardCommand.match_clas#s## 3,Ciikk  IJ1a[[ ) )Q<3&&#%JJ#a&(JJY&&tt'urr;)r>r?r@rAr rrrrrrrrs^..LLLrrc6eZdZdZgfdZdZdZdZddZdS) CardCommandSetz@A set of card instructions, typically specified within one spec.c6||_d|D|_dS)Nci|] }|j| Sr)r)rcs rrRz+CardCommandSet.__init__..s,,,!QUA,,,r)recmds)r rers rr zCardCommandSet.__init__s" ,,t,,, rc|jSrrrs rrzCardCommandSet.__str__rrc|j|Sr)r)r idxs r __getitem__zCardCommandSet.__getitem__sy~rcvt|trI|j|jvr*t d||j|j|jfz||j|j<dSt|t r3|jD]}|j||j|<dSt |d|)Nz"%s: INS 0x%02x already defined: %sz$: Unsupported type to add operator: )rrrrr7rre)r r rs rr$zCardCommandSet.__add__s e[ ) ) LyDI%% !E"& 49UY3G!H"IJJJ#(DIei ~ . . LZ__&& - -$z!} !  - ->BddEEJLL LrNct|}||jvrdS|j|}|r||sdS|S)z*look-up the command within the CommandSet.N)r'rr)r rrcmds rlookupzCardCommandSet.lookupsO#hhdi4in  s}}S)) 4 rr) r>r?r@rAr rrr$rrrrrrsuJJ"$---- L L Lrr)F)rr)rr$rT)r)ArAjsonrCstringdatetimeargparseiortypingrrrrrr r osmocom.utils osmocom.tlvr r r6rrHexstrResTuplerr*r-r2r'r:rCrBrJrVrGr^rHryrrrr8r9rboolrrPr]rrrrrrrrABCrrFr"rrprrrrrrs2 CCCCCCCCCCCCCCCCCC<<<<<<<