Ejemplo n.º 1
0
 def change_chv(self, chv_no: int, pin_code: str, new_pin_code: str):
     """Change a given CHV (Card Holder Verification == PIN)"""
     fc = rpad(b2h(pin_code), 16) + rpad(b2h(new_pin_code), 16)
     data, sw = self._tp.send_apdu(self.cla_byte + '2400' +
                                   ('%02X' % chv_no) + '10' + fc)
     self._chv_process_sw('change', chv_no, pin_code, sw)
     return (data, sw)
Ejemplo n.º 2
0
 def unblock_chv(self, chv_no: int, puk_code: str, pin_code: str):
     """Unblock a given CHV (Card Holder Verification == PIN)"""
     fc = rpad(b2h(puk_code), 16) + rpad(b2h(pin_code), 16)
     data, sw = self._tp.send_apdu(self.cla_byte + '2C00' +
                                   ('%02X' % chv_no) + '10' + fc)
     self._chv_process_sw('unblock', chv_no, pin_code, sw)
     return (data, sw)
Ejemplo n.º 3
0
	def program(self, p):
		# Go to dir
		self._scc.select_file(['3f00', '7f4d'])

		# Home PLMN in PLMN_Sel format
		hplmn = enc_plmn(p['mcc'], p['mnc'])

		# Operator name ( 3f00/7f4d/8f0c )
		self._scc.update_record(self._files['name'][0], 2,
			rpad(b2h(p['name']), 32)  + ('%02x' % len(p['name'])) + '01'
		)

		# ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
		v = ''

			# inline Ki
		if self._ki_file is None:
			v += p['ki']

			# ICCID
		v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])

			# IMSI
		v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])

			# Ki
		if self._ki_file:
			v += self._ki_file + '10' + p['ki']

			# PLMN_Sel
		v+= '6f30' + '18' +  rpad(hplmn, 36)

			# ACC
			# This doesn't work with "fake" SuperSIM cards,
			# but will hopefully work with real SuperSIMs.
		if p.get('acc') is not None:
			v+= '6f78' + '02' + lpad(p['acc'], 4)

		self._scc.update_record(self._files['b_ef'][0], 1,
			rpad(v, self._files['b_ef'][1]*2)
		)

		# SMSP ( 3f00/7f4d/8f0e )
			# FIXME

		# Write PLMN_Sel forcefully as well
		r = self._scc.select_file(['3f00', '7f20', '6f30'])
		tl = int(r[-1][4:8], 16)

		hplmn = enc_plmn(p['mcc'], p['mnc'])
		self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
Ejemplo n.º 4
0
	def program(self, p):
		# Go to dir
		self._scc.select_file(['3f00', '7f4d'])

		# Home PLMN in PLMN_Sel format
		hplmn = enc_plmn(p['mcc'], p['mnc'])

		# Operator name ( 3f00/7f4d/8f0c )
		self._scc.update_record(self._files['name'][0], 2,
			rpad(b2h(p['name']), 32)  + ('%02x' % len(p['name'])) + '01'
		)

		# ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
		v = ''

			# inline Ki
		if self._ki_file is None:
			v += p['ki']

			# ICCID
		v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])

			# IMSI
		v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])

			# Ki
		if self._ki_file:
			v += self._ki_file + '10' + p['ki']

			# PLMN_Sel
		v+= '6f30' + '18' +  rpad(hplmn, 36)

			# ACC
			# This doesn't work with "fake" SuperSIM cards,
			# but will hopefully work with real SuperSIMs.
		if p.get('acc') is not None:
			v+= '6f78' + '02' + lpad(p['acc'], 4)

		self._scc.update_record(self._files['b_ef'][0], 1,
			rpad(v, self._files['b_ef'][1]*2)
		)

		# SMSP ( 3f00/7f4d/8f0e )
			# FIXME

		# Write PLMN_Sel forcefully as well
		r = self._scc.select_file(['3f00', '7f20', '6f30'])
		tl = int(r[-1][4:8], 16)

		hplmn = enc_plmn(p['mcc'], p['mnc'])
		self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
	def update_record(self, ef, rec_no:int, data:str, force_len:bool=False, verify:bool=False,
					  conserve:bool=False):
		res = self.select_path(ef)

		if force_len:
			# enforce the record length by the actual length of the given data input
			rec_length = len(data) // 2
		else:
			# determine the record length from the select response of the file and pad
			# the input data with 0xFF if necessary. In cases where the input data
			# exceed we throw an exception.
			rec_length = self.__record_len(res)
			if (len(data) // 2 > rec_length):
				raise ValueError('Data length exceeds record length (expected max %d, got %d)' % (rec_length, len(data) // 2))
			elif (len(data) // 2 < rec_length):
				data = rpad(data, rec_length * 2)

		# Save write cycles by reading+comparing before write
		if conserve:
			data_current, sw = self.read_record(ef, rec_no)
			data_current = data_current[0:rec_length*2]
			if data_current == data:
				return None, sw

		pdu = (self.cla_byte + 'dc%02x04%02x' % (rec_no, rec_length)) + data
		res = self._tp.send_apdu_checksw(pdu)
		if verify:
			self.verify_record(ef, rec_no, data)
		return res
Ejemplo n.º 7
0
 def enable_chv(self, chv_no: int, pin_code: str):
     """Enable a given CHV (Card Holder Verification == PIN)"""
     fc = rpad(b2h(pin_code), 16)
     data, sw = self._tp.send_apdu(self.cla_byte + '2800' +
                                   ('%02X' % chv_no) + '08' + fc)
     self._chv_process_sw('enable', chv_no, pin_code, sw)
     return (data, sw)
Ejemplo n.º 8
0
 def verify_chv(self, chv_no: int, code: str):
     """Verify a given CHV (Card Holder Verification == PIN)"""
     fc = rpad(b2h(code), 16)
     data, sw = self._tp.send_apdu(self.cla_byte + '2000' +
                                   ('%02X' % chv_no) + '08' + fc)
     self._chv_process_sw('verify', chv_no, code, sw)
     return (data, sw)
Ejemplo n.º 9
0
def read_params_csv(opts, imsi=None, iccid=None):
    row = _read_params_csv(opts, iccid=iccid, imsi=imsi)
    if row is not None:
        row['mcc'] = row.get('mcc', mcc_from_imsi(row.get('imsi')))
        row['mnc'] = row.get('mnc', mnc_from_imsi(row.get('imsi')))

        pin_adm = None
        # We need to escape the pin_adm we get from the csv
        if 'pin_adm' in row:
            pin_adm = ''.join(['%02x' % (ord(x)) for x in row['pin_adm']])
        # Stay compatible to the odoo csv format
        elif 'adm1' in row:
            pin_adm = ''.join(['%02x' % (ord(x)) for x in row['adm1']])
        if pin_adm:
            row['pin_adm'] = rpad(pin_adm, 16)

        # If the CSV-File defines a pin_adm_hex field use this field to
        # generate pin_adm from that.
        pin_adm_hex = row.get('pin_adm_hex')
        if pin_adm_hex:
            if len(pin_adm_hex) == 16:
                row['pin_adm'] = pin_adm_hex
                # Ensure that it's hex-encoded
                try:
                    try_encode = h2b(pin_adm)
                except ValueError:
                    raise ValueError(
                        "pin_adm_hex needs to be hex encoded using this option"
                    )
            else:
                raise ValueError(
                    "pin_adm_hex needs to be exactly 16 digits (hex encoded)")

    return row
Ejemplo n.º 10
0
	def program(self, p):
		# Go to dir
		self._scc.select_file(['3f00', '7f4d'])

		# Home PLMN in PLMN_Sel format
		hplmn = self._e_plmn(p['mcc'], p['mnc'])

		# Operator name ( 3f00/7f4d/8f0c )
		self._scc.update_record(self._files['name'][0], 2,
			rpad(b2h(p['name']), 32)  + ('%02x' % len(p['name'])) + '01'
		)

		# ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
		v = ''

			# inline Ki
		if self._ki_file is None:
			v += p['ki']

			# ICCID
		v += '3f00' + '2fe2' + '0a' + self._e_iccid(p['iccid'])

			# IMSI
		v += '7f20' + '6f07' + '09' + self._e_imsi(p['imsi'])

			# Ki
		if self._ki_file:
			v += self._ki_file + '10' + p['ki']

			# PLMN_Sel
		v+= '6f30' + '18' +  rpad(hplmn, 36)

		self._scc.update_record(self._files['b_ef'][0], 1,
			rpad(v, self._files['b_ef'][1]*2)
		)

		# SMSP ( 3f00/7f4d/8f0e )
			# FIXME

		# Write PLMN_Sel forcefully as well
		r = self._scc.select_file(['3f00', '7f20', '6f30'])
		tl = int(r[-1][4:8], 16)

		hplmn = self._e_plmn(p['mcc'], p['mnc'])
		self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
Ejemplo n.º 11
0
 def verify_chv(self, chv_no, code):
     fc = rpad(b2h(code), 16)
     data, sw = self._tp.send_apdu(self.cla_byte + '2000' +
                                   ('%02X' % chv_no) + '08' + fc)
     if (sw != '9000'):
         raise RuntimeError(
             'Failed to authenticate with ADM key %s, %i tries left.' %
             (code, int(sw[3])))
     return (data, sw)
Ejemplo n.º 12
0
    def program(self, p):
        # Go to dir
        self._scc.select_file(['3f00', '7f4d'])

        # Home PLMN in PLMN_Sel format
        hplmn = self._e_plmn(p['mcc'], p['mnc'])

        # Operator name ( 3f00/7f4d/8f0c )
        self._scc.update_record(
            self._files['name'][0], 2,
            rpad(b2h(p['name']), 32) + ('%02x' % len(p['name'])) + '01')

        # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
        v = ''

        # inline Ki
        if self._ki_file is None:
            v += p['ki']

            # ICCID
        v += '3f00' + '2fe2' + '0a' + self._e_iccid(p['iccid'])

        # IMSI
        v += '7f20' + '6f07' + '09' + self._e_imsi(p['imsi'])

        # Ki
        if self._ki_file:
            v += self._ki_file + '10' + p['ki']

            # PLMN_Sel
        v += '6f30' + '18' + rpad(hplmn, 36)

        self._scc.update_record(self._files['b_ef'][0], 1,
                                rpad(v, self._files['b_ef'][1] * 2))

        # SMSP ( 3f00/7f4d/8f0e )
        # FIXME

        # Write PLMN_Sel forcefully as well
        r = self._scc.select_file(['3f00', '7f20', '6f30'])
        tl = int(r[-1][4:8], 16)

        hplmn = self._e_plmn(p['mcc'], p['mnc'])
        self._scc.update_binary('6f30', hplmn + 'ff' * (tl - 3))
Ejemplo n.º 13
0
def read_params_csv(opts, imsi=None, iccid=None):
	row = _read_params_csv(opts, iccid=iccid, imsi=imsi)
	if row is not None:
		row['mcc'] = int(row.get('mcc', row['imsi'][0:3]))
		row['mnc'] = int(row.get('mnc', row['imsi'][3:5]))
		pin_adm = None
		# We need to escape the pin_adm we get from the csv
		if 'pin_adm' in row:
			pin_adm = ''.join(['%02x'%(ord(x)) for x in row['pin_adm']])
		# Stay compatible to the odoo csv format
		elif 'adm1' in row:
			pin_adm = ''.join(['%02x'%(ord(x)) for x in row['adm1']])
		if pin_adm:
			row['pin_adm'] = rpad(pin_adm, 16)
	return row
Ejemplo n.º 14
0
    def program(self, p):
        # Home PLMN
        r = self._scc.select_file(['3f00', '7f20', '6f30'])
        tl = int(r[-1][4:8], 16)

        hplmn = self._e_plmn(p['mcc'], p['mnc'])
        self._scc.update_binary('6f30', hplmn + 'ff' * (tl - 3))

        # Get total number of entries and entry size
        rec_cnt, rec_len = self._get_infos()

        # Set first entry
        entry = (
            '81' +  #  1b  Status: Valid & Active
            rpad(b2h(p['name'][0:14]), 28) +  # 14b  Entry Name
            self._e_iccid(p['iccid']) +  # 10b  ICCID
            self._e_imsi(p['imsi']) +  #  9b  IMSI_len + id_type(9) + IMSI
            p['ki'] +  # 16b  Ki
            lpad(p['smsp'], 80)  # 40b  SMSP (padded with ff if needed)
        )
        self._scc.update_record('000c', 1, entry)
Ejemplo n.º 15
0
	def program(self, p):
		# Home PLMN
		r = self._scc.select_file(['3f00', '7f20', '6f30'])
		tl = int(r[-1][4:8], 16)

		hplmn = self._e_plmn(p['mcc'], p['mnc'])
		self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))

		# Get total number of entries and entry size
		rec_cnt, rec_len = self._get_infos()

		# Set first entry
		entry = (
			'81' +								#  1b  Status: Valid & Active
			rpad(b2h(p['name'][0:14]), 28) +	# 14b  Entry Name
			self._e_iccid(p['iccid']) +			# 10b  ICCID
			self._e_imsi(p['imsi']) +			#  9b  IMSI_len + id_type(9) + IMSI
			p['ki'] +							# 16b  Ki
			lpad(p['smsp'], 80)					# 40b  SMSP (padded with ff if needed)
		)
		self._scc.update_record('000c', 1, entry)
Ejemplo n.º 16
0
	def verify_chv(self, chv_no, code):
		fc = rpad(b2h(code), 16)
		return self._tp.send_apdu_checksw(self.cla_byte + '2000' + ('%02X' % chv_no) + '08' + fc)
Ejemplo n.º 17
0
 def _e_iccid(self, iccid):
     return swap_nibbles(rpad(iccid, 20))
Ejemplo n.º 18
0
    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)

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')
Ejemplo n.º 19
0
	def verify_chv(self, chv_no, code):
		fc = rpad(b2h(code), 16)
		return self._tp.send_apdu_checksw(self.cla_byte + '2000' + ('%02X' % chv_no) + '08' + fc)
Ejemplo n.º 20
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 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,
    }
Ejemplo n.º 21
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,
	}
Ejemplo n.º 22
0
	def _e_iccid(self, iccid):
		return swap_nibbles(rpad(iccid, 20))
Ejemplo n.º 23
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) 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,
    }
Ejemplo n.º 24
0
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)

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('80f21000024f0000c0000000')
	while status == '6310':
		(partData, status) = ac.send_wrapped_apdu('80f21001024f0000c0000000')
		data = data + partData

	while len(data) > 0: