You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.6 KiB
216 lines
5.6 KiB
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Gadgets to modify SYSMO USIM SJS1 parameters
|
|
|
|
(C) 2017 by Sysmocom s.f.m.c. GmbH
|
|
All Rights Reserved
|
|
|
|
Author: Philipp Maier
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
from card import *
|
|
from simcard import *
|
|
from utils import *
|
|
import sys
|
|
|
|
# CHV Types
|
|
SYSMO_USIM_ADM1 = 0x0A
|
|
|
|
class Sysmo_usim:
|
|
|
|
sim = None
|
|
|
|
def __init__(self, atr):
|
|
print("Initializing smartcard terminal...")
|
|
self.sim = Simcard(GSM_USIM, toBytes(atr))
|
|
self.sim.card.SELECT_ADF_USIM()
|
|
print(" * Detected Card IMSI: %s" % self.sim.card.get_imsi())
|
|
if self.sim.has_isim:
|
|
print(" ISIM Application installed")
|
|
if self.sim.has_usim:
|
|
print(" USIM Application installed")
|
|
print("")
|
|
|
|
def _warn_failed_auth(self, attempts = 3, keytype = "ADM1"):
|
|
print(" === Authentication problem! The Card will permanently ===")
|
|
print(" === lock down after %d failed attemts! Double check %s! ===" % (attempts, keytype))
|
|
print("")
|
|
|
|
def _warn_remaining_auth(self, attempts = 3, keytype = "ADM1"):
|
|
print(" * Error: Only two authentication attempts remaining, we don't")
|
|
print(" want to risk another failed authentication attempt!")
|
|
print(" (double check ADM1 and use option -f to override)")
|
|
print("")
|
|
|
|
|
|
# Initalize card (select master file)
|
|
def _init(self):
|
|
print " * Initalizing..."
|
|
self.sim.select(GSM_SIM_MF)
|
|
|
|
|
|
# Read files sensitively
|
|
def _read_binary(self, length, offset=0):
|
|
res = self.sim.read_binary(length, offset)
|
|
if len(res.apdu) != length:
|
|
print(" Error: could not read file (sw=%02x%02x) -- abort!\n" % (res.sw[0], res.sw[1]))
|
|
exit(1)
|
|
return res
|
|
|
|
|
|
# Authenticate as administrator
|
|
def admin_auth(self, adm1, force = False):
|
|
print("Authenticating...")
|
|
rc = True
|
|
rem_attemts = self.sim.chv_retrys(SYSMO_USIM_ADM1)
|
|
|
|
print(" * Remaining attempts: " + str(rem_attemts))
|
|
|
|
# Stop if a decreased ADM1 retry counter is detected
|
|
if(rem_attemts < 3) and force == False:
|
|
self._warn_remaining_auth()
|
|
self._warn_failed_auth()
|
|
return False
|
|
|
|
if(len(adm1) != 8):
|
|
print(" * Error: Short ADM1, a valid ADM1 is 8 digits long!")
|
|
print("")
|
|
self._warn_failed_auth()
|
|
return False
|
|
|
|
# Try to authenticate
|
|
try:
|
|
print(" * Authenticating...")
|
|
res = self.sim.verify_chv(adm1, SYSMO_USIM_ADM1)
|
|
if res.sw != [0x90, 0x00]:
|
|
raise
|
|
print(" * Authentication successful")
|
|
except:
|
|
print(" * Error: Authentication failed!")
|
|
rc = False
|
|
|
|
# Read back and display remaining attemts
|
|
rem_attemts = self.sim.chv_retrys(SYSMO_USIM_ADM1)
|
|
print(" * Remaining attempts: " + str(rem_attemts))
|
|
print("")
|
|
|
|
if rc == False:
|
|
self._warn_failed_auth()
|
|
return rc
|
|
|
|
|
|
# Show current ICCID value
|
|
def show_iccid(self):
|
|
print("Reading ICCID value...")
|
|
self._init()
|
|
print(" * Reading...")
|
|
print(" * Card ICCID: %s" % self.sim.card.get_ICCID())
|
|
print("")
|
|
|
|
|
|
# Program new ICCID value
|
|
# Note: Since the ICCID is a stanard file writing to it works the same
|
|
# way for all card models. However, the ICCID may be linked to the
|
|
# license management of the card O/S, so changing it might cause
|
|
# problems for some cards models. (USE WITH CAUTION!)
|
|
def write_iccid(self, iccid):
|
|
print("Writing ICCID value...")
|
|
self._init()
|
|
|
|
print(" * New ICCID setting:")
|
|
print(" ICCID: " + hexdump(iccid))
|
|
|
|
self.sim.select(GSM_SIM_EF_ICCID)
|
|
|
|
print(" * Programming...")
|
|
self.sim.update_binary(swap_nibbles(iccid))
|
|
print("")
|
|
|
|
|
|
# Program new IMSI value
|
|
def write_imsi(self, imsi):
|
|
print("Writing IMSI value...")
|
|
self._init()
|
|
|
|
print(" * New ISMI setting:")
|
|
print(" IMSI: " + hexdump(imsi))
|
|
|
|
self.sim.select(GSM_SIM_DF_GSM)
|
|
self.sim.select(GSM_SIM_EF_IMSI)
|
|
|
|
imsi = [len(imsi)] + swap_nibbles(imsi)
|
|
|
|
print(" * Programming...")
|
|
self.sim.update_binary(imsi)
|
|
print("")
|
|
|
|
|
|
# Show current mnc length value
|
|
def show_mnclen(self):
|
|
print("Reading MNCLEN value...")
|
|
self._init()
|
|
|
|
print(" * Reading...")
|
|
self.sim.select(GSM_SIM_DF_GSM)
|
|
self.sim.select(GSM_SIM_EF_AD)
|
|
res = self.sim.read_binary(4)
|
|
|
|
print(" * Current MNCLEN setting:")
|
|
print(" MNCLEN: " + "0x%02x" % res.apdu[3])
|
|
print("")
|
|
|
|
|
|
# Program new mnc length value
|
|
def write_mnclen(self, mnclen):
|
|
print("Writing MNCLEN value...")
|
|
self._init()
|
|
|
|
print(" * New MNCLEN setting:")
|
|
print(" MNCLEN: " + "0x" + hexdump(mnclen))
|
|
|
|
if len(mnclen) != 1:
|
|
print(" * Error: mnclen value must consist of a single byte!")
|
|
return
|
|
|
|
self.sim.select(GSM_SIM_DF_GSM)
|
|
self.sim.select(GSM_SIM_EF_AD)
|
|
|
|
res = self.sim.read_binary(4)
|
|
new_ad = res.apdu[0:3] + mnclen
|
|
|
|
print(" * Programming...")
|
|
self.sim.update_binary(new_ad)
|
|
print("")
|
|
|
|
|
|
# Show installed applications (AIDs)
|
|
def show_aid(self):
|
|
print("Reading application directory...");
|
|
self._init()
|
|
self.sim.card.get_AID()
|
|
AID = self.sim.card.AID
|
|
for a in AID:
|
|
if a[0:7] == [0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x02]:
|
|
appstr = "USIM"
|
|
elif a[0:7] == [0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x04]:
|
|
appstr = "ISIM"
|
|
else:
|
|
appstr = "(unknown)"
|
|
print " AID: " + hexdump(a[0:5]) + " " + hexdump(a[5:7]) + " " + hexdump(a[7:]) + " ==> " + appstr
|
|
print ""
|