def _e_imsi(self, imsi): """Converts a string imsi into the value of the EF""" l = (len(imsi) + 1) // 2 # Required bytes oe = len(imsi) & 1 # Odd (1) / Even (0) ei = '%02x' % l + swap_nibbles( lpad('%01x%s' % ((oe << 3) | 1, imsi), 16)) return ei
def set_phonebook(slot, name, number, capability='ff'): num_records = sc.record_count(['3f00','7f10','6f3a']) record_size = sc.record_size(['3f00','7f10','6f3a']) record_num = int(slot) if (record_num < 1) or (record_num > num_records): raise RuntimeError("Invalid phonebook record number") encoded_name = rpad(b2h(name), (record_size - 14) * 2) if len(encoded_name) > ((record_size - 14) * 2): raise RuntimeError("Name is longer than %s bytes" % ((record_size-14))) if len(number) > 20: raise RuntimeError("Number is too long") encoded_number = swap_nibbles(rpad(number, 20)) record = encoded_name + ('%02x' % len(number)) + capability + encoded_number + 'ffff' sc.update_record(['3f00','7f10','6f3a'], record_num, record)
def gen_parameters(opts): """Generates Name, ICCID, MCC, MNC, IMSI, SMSP, Ki, PIN-ADM from the options given by the user""" # MCC/MNC mcc = opts.mcc mnc = opts.mnc if not ((0 < mcc < 999) and (0 < mnc < 999)): raise ValueError('mcc & mnc must be between 0 and 999') # Digitize country code (2 or 3 digits) cc_digits = _cc_digits(opts.country) # Digitize MCC/MNC (5 or 6 digits) plmn_digits = _mcc_mnc_digits(mcc, mnc) # ICCID (19 digits, E.118), though some phase1 vendors use 20 :( if opts.iccid is not None: iccid = opts.iccid if not _isnum(iccid, 19) and not _isnum(iccid, 20): raise ValueError('ICCID must be 19 or 20 digits !') else: if opts.num is None: raise ValueError('Neither ICCID nor card number specified !') iccid = ( '89' + # Common prefix (telecom) cc_digits + # Country Code on 2/3 digits plmn_digits # MCC/MNC on 5/6 digits ) ml = 18 - len(iccid) if opts.secret is None: # The raw number iccid += ('%%0%dd' % ml) % opts.num else: # Randomized digits iccid += _digits(opts.secret, 'ccid', ml, opts.num) # Add checksum digit iccid += ('%1d' % calculate_luhn(iccid)) # IMSI (15 digits usually) if opts.imsi is not None: imsi = opts.imsi if not _isnum(imsi): raise ValueError('IMSI must be digits only !') else: if opts.num is None: raise ValueError('Neither IMSI nor card number specified !') ml = 15 - len(plmn_digits) if opts.secret is None: # The raw number msin = ('%%0%dd' % ml) % opts.num else: # Randomized digits msin = _digits(opts.secret, 'imsi', ml, opts.num) imsi = ( plmn_digits + # MCC/MNC on 5/6 digits msin # MSIN ) # SMSP if opts.smsp is not None: smsp = opts.smsp if not _ishex(smsp): raise ValueError('SMSP must be hex digits only !') if len(smsp) < 28 * 2: raise ValueError('SMSP must be at least 28 bytes') else: if opts.smsc is not None: smsc = opts.smsc if not _isnum(smsc): raise ValueError('SMSC must be digits only !') else: smsc = '00%d' % opts.country + '5555' # Hack ... smsc = '%02d' % ( (len(smsc) + 3) // 2, ) + "81" + swap_nibbles(rpad(smsc, 20)) smsp = ( 'e1' + # Parameters indicator 'ff' * 12 + # TP-Destination address smsc + # TP-Service Centre Address '00' + # TP-Protocol identifier '00' + # TP-Data coding scheme '00' # TP-Validity period ) # ACC if opts.acc is not None: acc = opts.acc if not _ishex(acc): raise ValueError('ACC must be hex digits only !') if len(acc) != 2 * 2: raise ValueError('ACC must be exactly 2 bytes') else: acc = None # Ki (random) if opts.ki is not None: ki = opts.ki if not re.match('^[0-9a-fA-F]{32}$', ki): raise ValueError('Ki needs to be 128 bits, in hex format') else: ki = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)]) # OPC (random) if opts.opc is not None: opc = opts.opc if not re.match('^[0-9a-fA-F]{32}$', opc): raise ValueError('OPC needs to be 128 bits, in hex format') elif opts.op is not None: opc = derive_milenage_opc(ki, opts.op) else: opc = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)]) if opts.pin_adm is not None: if len(opts.pin_adm) <= 8: pin_adm = ''.join(['%02x' % (ord(x)) for x in opts.pin_adm]) pin_adm = rpad(pin_adm, 16) elif len(opts.pin_adm) == 16: pin_adm = opts.pin_adm else: raise ValueError( "PIN-ADM needs to be <=8 digits (ascii) or exactly 16 digits (raw hex)" ) else: pin_adm = None # Return that return { 'name': opts.name, 'iccid': iccid, 'mcc': mcc, 'mnc': mnc, 'imsi': imsi, 'smsp': smsp, 'ki': ki, 'opc': opc, 'acc': acc, 'pin_adm': pin_adm, }
if opts.erase: print "Formatting ..." card.erase() card.reset() # Generate parameters if opts.source == 'cmdline': cp = gen_parameters(opts) elif opts.source == 'csv': if opts.read_imsi: if opts.dry_run: # Connect transport print "Insert card now (or CTRL-C to cancel)" sl.wait_for_card(newcardonly=not first) (res, _) = scc.read_binary(EF['IMSI']) imsi = swap_nibbles(res)[3:] else: imsi = opts.imsi cp = read_params_csv(opts, imsi) if cp is None: print "Error reading parameters\n" sys.exit(2) print_parameters(cp) if opts.dry_run is False: # Program the card print "Programming ..." if opts.dry_run is not True: card.program(cp) else: print "Dry Run: NOT PROGRAMMING!"
sl = DummySL() pass else: raise RuntimeError("Need to specify either --serialport, --pcsc or --smpp") sc = SimCardCommands(sl) ac = AppLoaderCommands(sl) if not args.smpp: sl.wait_for_card(newcardonly=args.new_card_required) time.sleep(args.sleep_after_insertion) if not args.smpp: # Get the ICCID print "ICCID: " + swap_nibbles(sc.read_binary(['3f00', '2fe2'])[0]) ac.send_terminal_profile() if len(args.aram_apdu) > 0: # Select the ARA-M applet from its AID aram_rv = rv = ac._tp.send_apdu('00A4040009A00000015141434C00') if '9000' != aram_rv[1]: raise RuntimeError("SW match failed! Expected %s and got %s." % ('9000', aram_rv[1])) # Add/Delete Access rules list in ARA-M rv = ac._tp.send_apdu(args.aram_apdu) if '9000' != rv[1] and '6a88' != rv[1]: raise RuntimeError("SW match failed! Expected %s and got %s." % ('9000', rv[1])) if '80CAFF4000' == args.aram_apdu: res = h2i(rv[0])
def _encode(self, obj, context, path): return h2b(swap_nibbles(obj))
if args.pcsc is not None: from pySim.transport.pcsc import PcscSimLink sl = PcscSimLink(args.pcsc) elif args.serialport is not None: from pySim.transport.serial import SerialSimLink sl = SerialSimLink(device=args.serialport, baudrate=9600) else: raise RuntimeError("Need to specify either --serialport or --pcsc") sc = SimCardCommands(sl) sl.wait_for_card(newcardonly=args.new_card_required) time.sleep(args.sleep_after_insertion) # Get the ICCID print("ICCID: %s" % swap_nibbles(sc.read_binary(['3f00', '2fe2'])[0])) if args.pin: sc.verify_chv(1, args.pin) if args.print_info: print("--print-info not implemented yet.") if args.disable_pin: sl.send_apdu_checksw('0026000108' + args.disable_pin.encode("hex") + 'ff' * (8 - len(args.disable_pin))) if args.dump_phonebook: num_records = sc.record_count(['3f00','7f10','6f3a']) print("Phonebook: %d records available" % num_records) for record_id in range(1, num_records + 1): print(sc.read_record(['3f00','7f10','6f3a'], record_id))
for record_id in range(1, num_records + 1): print sc.read_record(['3f00', '7f10', '6f3a'], record_id) if args.set_phonebook_entry: num_records = sc.record_count(['3f00', '7f10', '6f3a']) record_size = sc.record_size(['3f00', '7f10', '6f3a']) record_num = int(args.set_phonebook_entry[0]) if (record_num < 1) or (record_num > num_records): raise RuntimeError("Invalid phonebook record number") encoded_name = rpad(b2h(args.set_phonebook_entry[1]), (record_size - 14) * 2) if len(encoded_name) > ((record_size - 14) * 2): raise RuntimeError("Name is too long") if len(args.set_phonebook_entry[2]) > 20: raise RuntimeError("Number is too long") encoded_number = swap_nibbles(rpad(args.set_phonebook_entry[2], 20)) record = encoded_name + ( '%02x' % len(args.set_phonebook_entry[2]) ) + args.set_phonebook_entry[3] + encoded_number + 'ffff' sc.update_record(['3f00', '7f10', '6f3a'], record_num, record) if args.list_applets: (data, status) = ac.send_wrapped_apdu_ram('80f21000024f0000c0000000') while status == '6310': (partData, status) = ac.send_wrapped_apdu_ram('80f21001024f0000c0000000') data = data + partData while len(data) > 0: aidlen = int(data[0:2], 16) * 2 aid = data[2:aidlen + 2]
def _e_imsi(self, imsi): """Converts a string imsi into the value of the EF""" l = (len(imsi) + 1) // 2 # Required bytes oe = len(imsi) & 1 # Odd (1) / Even (0) ei = '%02x' % l + swap_nibbles(lpad('%01x%s' % ((oe<<3)|1, imsi), 16)) return ei
def _e_iccid(self, iccid): return swap_nibbles(rpad(iccid, 20))
def get_imsi(): imsi_raw = (sc.read_binary(['3f00', '7f20', '6f07'])[0]) imsi_len = imsi_raw[1] imsi = swap_nibbles(imsi_raw[2:])[1:] print("IMSI: %s" % imsi) return imsi
if args.pcsc is not None: from pySim.transport.pcsc import PcscSimLink sl = PcscSimLink(args.pcsc) elif args.serialport is not None: from pySim.transport.serial import SerialSimLink sl = SerialSimLink(device=args.serialport, baudrate=9600) else: raise RuntimeError("Need to specify either --serialport or --pcsc") sc = SimCardCommands(sl) sl.wait_for_card(newcardonly=args.new_card_required) time.sleep(args.sleep_after_insertion) # Get the ICCID print("ICCID: %s" % swap_nibbles(sc.read_binary(['3f00', '2fe2'])[0])) if args.pin: sc.verify_chv(1, args.pin) if args.print_info: print("--print-info not implemented yet.") if args.disable_pin: sl.send_apdu_checksw('0026000108' + args.disable_pin.encode("hex") + 'ff' * (8 - len(args.disable_pin))) if args.dump_phonebook: num_records = sc.record_count(['3f00', '7f10', '6f3a']) print("Phonebook: %d records available" % num_records) for record_id in range(1, num_records + 1):
parser.add_argument('-p', '--pcsc', nargs='?', const=0, type=int) args = parser.parse_args() if args.pcsc is not None: from pySim.transport.pcsc import PcscSimLink sl = PcscSimLink(args.pcsc) elif args.serialport is not None: from pySim.transport.serial import SerialSimLink sl = SerialSimLink(device=args.serialport, baudrate=9600) else: raise RuntimeError("Need to specify either --serialport or --pcsc") sc = SimCardCommands(sl) ac = MessageCommands(sl) sl.wait_for_card(0) print "ICCID: " + swap_nibbles(sc.read_binary(['3f00', '2fe2'])[0]) ac.send_terminal_profile() # Send OTA SMS-PP Download messages (with incrementing CNTR) for x in range(0,1): # Send following binary data # a0a40000023f00 = Select master file 3f00 (data, status) = ac.send_ota_sms('a0a40000023f00') print "Status Code: " + status # If it succeeds a response of length 0x18 is waiting, so read it data = ac.send_read_data(0x18) print "OTA Response: " + data[0]
def get_imsi(): imsi_raw = (sc.read_binary(['3f00', '7f20', '6f07'])[0]) imsi_len = imsi_raw[1] imsi = swap_nibbles(imsi_raw[2:])[1:] print ("IMSI: %s" % imsi) return imsi
def gen_parameters(opts): """Generates Name, ICCID, MCC, MNC, IMSI, SMSP, Ki, PIN-ADM from the options given by the user""" # MCC/MNC mcc = opts.mcc mnc = opts.mnc if not mcc.isdigit() or not mnc.isdigit(): raise ValueError('mcc & mnc must only contain decimal digits') if len(mcc) < 1 or len(mcc) > 3: raise ValueError('mcc must be between 1 .. 3 digits') if len(mnc) < 1 or len(mnc) > 3: raise ValueError('mnc must be between 1 .. 3 digits') # MCC always has 3 digits mcc = lpad(mcc, 3, "0") # MNC must be at least 2 digits mnc = lpad(mnc, 2, "0") # Digitize country code (2 or 3 digits) cc_digits = _cc_digits(opts.country) # Digitize MCC/MNC (5 or 6 digits) plmn_digits = _mcc_mnc_digits(mcc, mnc) if opts.name is not None: if len(opts.name) > 16: raise ValueError('Service Provider Name must max 16 characters!') if opts.msisdn is not None: msisdn = opts.msisdn if msisdn[0] == '+': msisdn = msisdn[1:] if not msisdn.isdigit(): raise ValueError('MSISDN must be digits only! ' 'Start with \'+\' for international numbers.') if len(msisdn) > 10 * 2: # TODO: Support MSISDN of length > 20 (10 Bytes) raise ValueError( 'MSISDNs longer than 20 digits are not (yet) supported.') # ICCID (19 digits, E.118), though some phase1 vendors use 20 :( if opts.iccid is not None: iccid = opts.iccid if not _isnum(iccid, 19) and not _isnum(iccid, 20): raise ValueError('ICCID must be 19 or 20 digits !') else: if opts.num is None: raise ValueError('Neither ICCID nor card number specified !') iccid = ( '89' + # Common prefix (telecom) cc_digits + # Country Code on 2/3 digits plmn_digits # MCC/MNC on 5/6 digits ) ml = 18 - len(iccid) if opts.secret is None: # The raw number iccid += ('%%0%dd' % ml) % opts.num else: # Randomized digits iccid += _digits(opts.secret, 'ccid', ml, opts.num) # Add checksum digit iccid += ('%1d' % calculate_luhn(iccid)) # IMSI (15 digits usually) if opts.imsi is not None: imsi = opts.imsi if not _isnum(imsi): raise ValueError('IMSI must be digits only !') else: if opts.num is None: raise ValueError('Neither IMSI nor card number specified !') ml = 15 - len(plmn_digits) if opts.secret is None: # The raw number msin = ('%%0%dd' % ml) % opts.num else: # Randomized digits msin = _digits(opts.secret, 'imsi', ml, opts.num) imsi = ( plmn_digits + # MCC/MNC on 5/6 digits msin # MSIN ) # SMSP if opts.smsp is not None: smsp = opts.smsp if not _ishex(smsp): raise ValueError('SMSP must be hex digits only !') if len(smsp) < 28 * 2: raise ValueError('SMSP must be at least 28 bytes') else: ton = "81" if opts.smsc is not None: smsc = opts.smsc if smsc[0] == '+': ton = "91" smsc = smsc[1:] if not _isnum(smsc): raise ValueError('SMSC must be digits only!\n \ Start with \'+\' for international numbers') else: smsc = '00%d' % opts.country + '5555' # Hack ... smsc = '%02d' % ( (len(smsc) + 3) // 2, ) + ton + swap_nibbles(rpad(smsc, 20)) smsp = ( 'e1' + # Parameters indicator 'ff' * 12 + # TP-Destination address smsc + # TP-Service Centre Address '00' + # TP-Protocol identifier '00' + # TP-Data coding scheme '00' # TP-Validity period ) # ACC if opts.acc is not None: acc = opts.acc if not _ishex(acc): raise ValueError('ACC must be hex digits only !') if len(acc) != 2 * 2: raise ValueError('ACC must be exactly 2 bytes') else: acc = None # Ki (random) if opts.ki is not None: ki = opts.ki if not re.match('^[0-9a-fA-F]{32}$', ki): raise ValueError('Ki needs to be 128 bits, in hex format') else: ki = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)]) # OPC (random) if opts.opc is not None: opc = opts.opc if not re.match('^[0-9a-fA-F]{32}$', opc): raise ValueError('OPC needs to be 128 bits, in hex format') elif opts.op is not None: opc = derive_milenage_opc(ki, opts.op) else: opc = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)]) pin_adm = sanitize_pin_adm(opts.pin_adm, opts.pin_adm_hex) # ePDG Selection Information if opts.epdgSelection: if len(opts.epdgSelection) < 5 or len(opts.epdgSelection) > 6: raise ValueError('ePDG Selection Information is not valid') epdg_mcc = opts.epdgSelection[:3] epdg_mnc = opts.epdgSelection[3:] if not epdg_mcc.isdigit() or not epdg_mnc.isdigit(): raise ValueError( 'PLMN for ePDG Selection must only contain decimal digits') # Return that return { 'name': opts.name, 'iccid': iccid, 'mcc': mcc, 'mnc': mnc, 'imsi': imsi, 'smsp': smsp, 'ki': ki, 'opc': opc, 'acc': acc, 'pin_adm': pin_adm, 'msisdn': opts.msisdn, 'epdgid': opts.epdgid, 'epdgSelection': opts.epdgSelection, 'pcscf': opts.pcscf, 'ims_hdomain': opts.ims_hdomain, 'impi': opts.impi, 'impu': opts.impu, 'opmode': opts.opmode, }
def _e_plmn(self, mcc, mnc): """Converts integer MCC/MNC into 6 bytes for EF""" return swap_nibbles(lpad('%d' % mcc, 3) + lpad('%d' % mnc, 3))
def process_card(opts, first, card_handler): if opts.dry_run is False: # Connect transport card_handler.get(first) if opts.dry_run is False: # Get card card = card_detect(opts.type, scc) if card is None: print("No card detected!") return -1 # Probe only if opts.probe: return 0 # Erase if requested if opts.erase: print("Formatting ...") card.erase() card.reset() # Generate parameters if opts.source == 'cmdline': cp = gen_parameters(opts) elif opts.source == 'csv': imsi = None iccid = None if opts.read_iccid: if opts.dry_run: # Connect transport card_handler.get(False) (res, _) = scc.read_binary(['3f00', '2fe2'], length=10) iccid = dec_iccid(res) elif opts.read_imsi: if opts.dry_run: # Connect transport card_handler.get(False) (res, _) = scc.read_binary(EF['IMSI']) imsi = swap_nibbles(res)[3:] else: imsi = opts.imsi cp = read_params_csv(opts, imsi=imsi, iccid=iccid) if cp is None: print("Error reading parameters from CSV file!\n") return 2 print_parameters(cp) if opts.dry_run is False: # Program the card print("Programming ...") card.program(cp) else: print("Dry Run: NOT PROGRAMMING!") # Write parameters permanently write_parameters(opts, cp) # Batch mode state update and save if opts.num is not None: opts.num += 1 save_batch(opts) card_handler.done() return 0
def gen_parameters(opts): """Generates Name, ICCID, MCC, MNC, IMSI, SMSP, Ki, PIN-ADM from the options given by the user""" # MCC/MNC mcc = opts.mcc mnc = opts.mnc if not ((0 < mcc < 999) and (0 < mnc < 999)): raise ValueError('mcc & mnc must be between 0 and 999') # Digitize country code (2 or 3 digits) cc_digits = _cc_digits(opts.country) # Digitize MCC/MNC (5 or 6 digits) plmn_digits = _mcc_mnc_digits(mcc, mnc) # ICCID (19 digits, E.118), though some phase1 vendors use 20 :( if opts.iccid is not None: iccid = opts.iccid if not _isnum(iccid, 19): raise ValueError('ICCID must be 19 digits !'); else: if opts.num is None: raise ValueError('Neither ICCID nor card number specified !') iccid = ( '89' + # Common prefix (telecom) cc_digits + # Country Code on 2/3 digits plmn_digits # MCC/MNC on 5/6 digits ) ml = 18 - len(iccid) if opts.secret is None: # The raw number iccid += ('%%0%dd' % ml) % opts.num else: # Randomized digits iccid += _digits(opts.secret, 'ccid', ml, opts.num) # Add checksum digit iccid += ('%1d' % calculate_luhn(iccid)) # IMSI (15 digits usually) if opts.imsi is not None: imsi = opts.imsi if not _isnum(imsi): raise ValueError('IMSI must be digits only !') else: if opts.num is None: raise ValueError('Neither IMSI nor card number specified !') ml = 15 - len(plmn_digits) if opts.secret is None: # The raw number msin = ('%%0%dd' % ml) % opts.num else: # Randomized digits msin = _digits(opts.secret, 'imsi', ml, opts.num) imsi = ( plmn_digits + # MCC/MNC on 5/6 digits msin # MSIN ) # SMSP if opts.smsp is not None: smsp = opts.smsp if not _ishex(smsp): raise ValueError('SMSP must be hex digits only !') if len(smsp) < 28*2: raise ValueError('SMSP must be at least 28 bytes') else: if opts.smsc is not None: smsc = opts.smsc if not _isnum(smsc): raise ValueError('SMSC must be digits only !') else: smsc = '00%d' % opts.country + '5555' # Hack ... smsc = '%02d' % ((len(smsc) + 3)//2,) + "81" + swap_nibbles(rpad(smsc, 20)) smsp = ( 'e1' + # Parameters indicator 'ff' * 12 + # TP-Destination address smsc + # TP-Service Centre Address '00' + # TP-Protocol identifier '00' + # TP-Data coding scheme '00' # TP-Validity period ) # ACC if opts.acc is not None: acc = opts.acc if not _ishex(acc): raise ValueError('ACC must be hex digits only !') if len(acc) != 2*2: raise ValueError('ACC must be exactly 2 bytes') else: acc = None # Ki (random) if opts.ki is not None: ki = opts.ki if not re.match('^[0-9a-fA-F]{32}$', ki): raise ValueError('Ki needs to be 128 bits, in hex format') else: ki = ''.join(['%02x' % random.randrange(0,256) for i in range(16)]) # Ki (random) if opts.opc is not None: opc = opts.opc if not re.match('^[0-9a-fA-F]{32}$', opc): raise ValueError('OPC needs to be 128 bits, in hex format') elif opts.op is not None: opc = derive_milenage_opc(ki, opts.op) else: opc = ''.join(['%02x' % random.randrange(0,256) for i in range(16)]) if opts.pin_adm is not None: if len(opts.pin_adm) > 8: raise ValueError("PIN-ADM needs to be <=8 digits") pin_adm = ''.join(['%02x'%(ord(x)) for x in opts.pin_adm]) pin_adm = rpad(pin_adm, 16) else: pin_adm = None # Return that return { 'name' : opts.name, 'iccid' : iccid, 'mcc' : mcc, 'mnc' : mnc, 'imsi' : imsi, 'smsp' : smsp, 'ki' : ki, 'opc' : opc, 'acc' : acc, 'pin_adm' : pin_adm, }
def _decode(self, obj, context, path): return swap_nibbles(b2h(obj))
from pySim.transport.pcsc import PcscSimLink sl = PcscSimLink(args.pcsc) elif args.serialport is not None: from pySim.transport.serial import SerialSimLink sl = SerialSimLink(device=args.serialport, baudrate=9600) else: raise RuntimeError("Need to specify either --serialport or --pcsc") sc = SimCardCommands(sl) ac = AppLoaderCommands(sl) sl.wait_for_card(newcardonly=args.new_card_required) time.sleep(args.sleep_after_insertion) # Get the ICCID print "ICCID: " + swap_nibbles(sc.read_binary(['3f00', '2fe2'])[0]) ac.send_terminal_profile() if args.pin: sc.verify_chv(1, args.pin) if args.delete_app: ac.delete_aid(args.delete_app) if args.load_app: ac.load_app(args.load_app) if args.install: ac.install_app(args) if args.print_info: