auth: prevent unintential card lock down

If the user submints a wrong ADM1 key with the commandline, the
authentication will fail. However, by the output of the program
it mey not be clear to the user that the reason for the failure
was a wrong ADM1 key. The user might try the same command with
the same parameters a few time and lock down the card.

This commit fixes that by failing gracefully with a very clear
error message. Furthermore, if a decreased authentication counter
is detected, no further authentication attempts will be made
until the user supplies the option -f (--force).
This commit is contained in:
Philipp Maier 2017-03-17 16:43:35 +01:00
parent a73acbc8e4
commit 14aaab262e
3 changed files with 54 additions and 18 deletions

View File

@ -146,13 +146,24 @@ class Simcard():
cla = self.__get_cla(self.usim)
ins = GSM_SIM_INS_VERIFY_CHV
length = 0x08
length = len(chv)
apdu = self.card.apdu(cla, ins, p2 = chv_no,
p3 = length, data = chv)
return self.card.transact(apdu, dry, strict)
# Read CHV retry counter
def chv_retrys(self, chv_no, dry = False, strict = True):
cla = self.__get_cla(self.usim)
ins = GSM_SIM_INS_VERIFY_CHV
length = 0
apdu = self.card.apdu(cla, ins, p2 = chv_no,
p3 = length, sw=[0x63, None])
res = self.card.transact(apdu, dry, strict)
return res.sw[1] & 0x0F
# Perform file operation (Write)
def update_binary(self, data, offset = 0, dry = False, strict = True):

View File

@ -70,15 +70,16 @@ def main(argv):
getopt_write_opc = None
getopt_show_ki = None
getopt_write_ki = None
getopt_force = False
# Analyze commandline options
try:
opts, args = getopt.getopt(argv,
"hva:ucmtT:lL:oO:C:kK:",
"hva:ucmtT:lL:oO:C:kK:f",
["help","verbose","adm1=","usim","classic",
"mode","auth","set-auth=","milenage",
"set-milenage","opc","set-op=","set-opc=",
"ki","set-ki="])
"ki","set-ki=","force"])
except getopt.GetoptError:
print " * Error: Invalid commandline options"
sys.exit(2)
@ -115,6 +116,8 @@ def main(argv):
getopt_show_ki = True
elif opt in ("-K", "--set-ki"):
getopt_write_ki = asciihex_to_list(arg)
elif opt in ("-f", "--force"):
getopt_force = True
if not getopt_adm1:
@ -129,6 +132,15 @@ def main(argv):
sim = Simcard(c)
print("")
# Authenticate
print "Authenticating..."
if sysmo_usim_admin_auth(sim, getopt_adm1, getopt_force) == False:
print ""
print " === Authentication problem! The Card will permanently ==="
print " === lock down after 3 failed attemts! Double check ADM1! ==="
print ""
exit(1)
print("")
# Execute tasks
if getopt_write_sim_mode != None:

View File

@ -137,16 +137,39 @@ def sysmo_usim_init(sim):
# Authenticate as administrator
def sysmo_usim_admin_auth(sim, adm1):
print " * Authenticating at card as administrator..."
sim.verify_chv(adm1, SYSMO_USIMSJS1_ADM1)
def sysmo_usim_admin_auth(sim, adm1, force = False):
rc = True
rem_attemts = sim.chv_retrys(SYSMO_USIMSJS1_ADM1)
print " * Remaining attempts: " + str(rem_attemts)
# Stop if a decreased ADM1 retry counter is detected
if(rem_attemts < 3) and force == False:
print " * Error: Only two authentication attemts remaining, we don't"
print " want to risk another failed authentication attempt!"
print " (double check ADM1 and use option -f to override)"
return False
# Try to authenticate
try:
print " * Authenticating..."
sim.verify_chv(adm1, SYSMO_USIMSJS1_ADM1)
print " * Authentication successful"
except:
print " * Error: Authentication failed!"
rc = False
# Read back and display remaining attemts
rem_attemts = sim.chv_retrys(SYSMO_USIMSJS1_ADM1)
print " * Remaining attempts: " + str(rem_attemts)
return rc
# Show current athentication parameters
# (Which algorithim is used for which rat?)
def sysmo_usim_show_auth_params(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Reading..."
sim.select(SYSMO_USIMSJS1_DF_AUTH)
@ -165,7 +188,6 @@ def sysmo_usim_write_auth_params(sim, adm1, algo_2g, algo_3g):
print " 3G: " + str(hex(algo_3g))
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Programming..."
sim.select(SYSMO_USIMSJS1_DF_AUTH)
@ -176,7 +198,6 @@ def sysmo_usim_write_auth_params(sim, adm1, algo_2g, algo_3g):
# Show current milenage parameters
def sysmo_usim_show_milenage_params(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
sim.select(SYSMO_USIMSJS1_DF_AUTH)
sim.select(SYSMO_USIMSJS1_EF_MLNGC)
@ -211,7 +232,6 @@ def sysmo_usim_show_milenage_params(sim, adm1):
# Write new milenage parameters
def sysmo_usim_write_milenage_params(sim, adm1, ef_mlngc):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * New Milenage Parameters for (EF.MLNGC):"
print str(ef_mlngc)
@ -235,7 +255,6 @@ def sysmo_usim_write_milenage_params(sim, adm1, ef_mlngc):
# Show current OPc value
def sysmo_usim_show_opc_params(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Reading..."
sim.select(GSM_SIM_DF_GSM)
@ -254,7 +273,6 @@ def sysmo_usim_write_opc_params(sim, adm1, select, op):
print " OP/OPc: " + hexdump(op)
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
sim.select(GSM_SIM_DF_GSM)
sim.select(SYSMO_USIMSJS1_EF_OPC)
@ -266,7 +284,6 @@ def sysmo_usim_write_opc_params(sim, adm1, select, op):
# Show current KI value
def sysmo_usim_show_ki_params(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Reading..."
sim.select(GSM_SIM_DF_GSM)
@ -283,7 +300,6 @@ def sysmo_usim_write_ki_params(sim, adm1, ki):
print " KI: " + hexdump(ki)
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
sim.select(GSM_SIM_DF_GSM)
sim.select(SYSMO_USIMSJS1_EF_KI)
@ -295,7 +311,6 @@ def sysmo_usim_write_ki_params(sim, adm1, ki):
# Show the enable status of the USIM application (app is enabled or disabled?)
def sysmo_usim_show_usim_status(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Reading..."
sim.select(GSM_USIM_EF_DIR)
@ -308,7 +323,6 @@ def sysmo_usim_show_usim_status(sim, adm1):
# Show the enable status of the USIM application (app is enabled or disabled?)
def sysmo_usim_show_sim_mode(sim, adm1):
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Reading..."
sim.select(GSM_USIM_EF_DIR)
@ -338,7 +352,6 @@ def sysmo_usim_write_sim_mode(sim, adm1, usim_enabled = True):
print " ==> USIM application disabled"
sysmo_usim_init(sim)
sysmo_usim_admin_auth(sim, adm1)
print " * Programming..."
sim.select(GSM_USIM_EF_DIR)