added PIN management for nPA
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@675 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -226,7 +226,7 @@ class Security_Environment(object):
|
|||||||
#Verification, encryption, external authentication and key agreement
|
#Verification, encryption, external authentication and key agreement
|
||||||
if se & 0x08:
|
if se & 0x08:
|
||||||
self.external_auth = True
|
self.external_auth = True
|
||||||
return self.__set_SE(p2, data)
|
return self._set_SE(p2, data)
|
||||||
elif(cmd== 0x02):
|
elif(cmd== 0x02):
|
||||||
return self.sam.store_SE(p2)
|
return self.sam.store_SE(p2)
|
||||||
elif(cmd == 0x03):
|
elif(cmd == 0x03):
|
||||||
@@ -237,15 +237,12 @@ class Security_Environment(object):
|
|||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
|
|
||||||
|
|
||||||
def __set_SE(self, p2, data):
|
def _set_SE(self, p2, data):
|
||||||
"""
|
"""
|
||||||
Manipulate the current Security Environment. P2 is the tag of a
|
Manipulate the current Security Environment. P2 is the tag of a
|
||||||
control reference template, data contains control reference objects
|
control reference template, data contains control reference objects
|
||||||
"""
|
"""
|
||||||
|
|
||||||
valid_p2 = (0xA4, 0xA6, 0xB4, 0xB6, 0xB8)
|
|
||||||
if not p2 in valid_p2:
|
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
|
||||||
if p2 == 0xA4:
|
if p2 == 0xA4:
|
||||||
return self.at.parse_SE_config(data)
|
return self.at.parse_SE_config(data)
|
||||||
elif p2 == 0xA6:
|
elif p2 == 0xA6:
|
||||||
@@ -258,6 +255,8 @@ class Security_Environment(object):
|
|||||||
return self.dst.parse_SE_config(data)
|
return self.dst.parse_SE_config(data)
|
||||||
elif p2 == 0xB8:
|
elif p2 == 0xB8:
|
||||||
return self.ct.parse_SE_config(data)
|
return self.ct.parse_SE_config(data)
|
||||||
|
|
||||||
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
|
|
||||||
def parse_SM_CAPDU(self, CAPDU, authenticate_header):
|
def parse_SM_CAPDU(self, CAPDU, authenticate_header):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class nPA_AT_CRT(ControlReferenceTemplate):
|
|||||||
ControlReferenceTemplate.__init__(self, CRT_TEMPLATE["AT"])
|
ControlReferenceTemplate.__init__(self, CRT_TEMPLATE["AT"])
|
||||||
|
|
||||||
def parse_SE_config(self, config):
|
def parse_SE_config(self, config):
|
||||||
|
r = 0x9000
|
||||||
try:
|
try:
|
||||||
ControlReferenceTemplate.parse_SE_config(self, config)
|
ControlReferenceTemplate.parse_SE_config(self, config)
|
||||||
except SwError as e:
|
except SwError as e:
|
||||||
@@ -37,12 +38,11 @@ class nPA_AT_CRT(ControlReferenceTemplate):
|
|||||||
for tlv in structure:
|
for tlv in structure:
|
||||||
tag, length, value = tlv
|
tag, length, value = tlv
|
||||||
if tag == 0x7f4c:
|
if tag == 0x7f4c:
|
||||||
from chat import CHAT
|
|
||||||
chat = CHAT(bertlv_pack([[tag, length, value]]))
|
chat = CHAT(bertlv_pack([[tag, length, value]]))
|
||||||
print(chat)
|
print(chat)
|
||||||
elif tag == 0x67:
|
elif tag == 0x67:
|
||||||
auxiliary_data = value
|
auxiliary_data = value
|
||||||
elif tag == 0x80 or tag == 0x83 or tag == 0x84:
|
elif tag == 0x80 or tag == 0x84 or tag == 0x83:
|
||||||
# handled by ControlReferenceTemplate.parse_SE_config
|
# handled by ControlReferenceTemplate.parse_SE_config
|
||||||
pass
|
pass
|
||||||
elif tag == 0x91:
|
elif tag == 0x91:
|
||||||
@@ -51,7 +51,16 @@ class nPA_AT_CRT(ControlReferenceTemplate):
|
|||||||
else:
|
else:
|
||||||
raise SwError(SW["ERR_REFNOTUSABLE"])
|
raise SwError(SW["ERR_REFNOTUSABLE"])
|
||||||
|
|
||||||
return 0x9000 , ""
|
structure = unpack(config)
|
||||||
|
for tlv in structure:
|
||||||
|
if [0x83, len('\x03'), '\x03'] == tlv:
|
||||||
|
if self.sam.counter <= 0:
|
||||||
|
r = 0x63c0
|
||||||
|
elif self.sam.counter == 1:
|
||||||
|
r = 0x63c1
|
||||||
|
elif self.sam.counter == 2:
|
||||||
|
r = 0x63c2
|
||||||
|
return r, ""
|
||||||
|
|
||||||
class nPA_SE(Security_Environment):
|
class nPA_SE(Security_Environment):
|
||||||
# TODO call __eac_abort whenever an error occurred
|
# TODO call __eac_abort whenever an error occurred
|
||||||
@@ -63,6 +72,20 @@ class nPA_SE(Security_Environment):
|
|||||||
self.sec = None
|
self.sec = None
|
||||||
self.eac_ctx = None
|
self.eac_ctx = None
|
||||||
|
|
||||||
|
def _set_SE(self, p2, data):
|
||||||
|
sw, resp = Security_Environment._set_SE(self, p2, data)
|
||||||
|
|
||||||
|
if self.at.algorithm == "PACE":
|
||||||
|
self.eac_step = 0
|
||||||
|
elif self.at.algorithm == "TA":
|
||||||
|
if self.eac_step != 4:
|
||||||
|
SwError(SW["ERR_AUTHBLOCKED"])
|
||||||
|
elif self.at.algorithm == "CA":
|
||||||
|
if self.eac_step != 7:
|
||||||
|
SwError(SW["ERR_AUTHBLOCKED"])
|
||||||
|
|
||||||
|
return sw, resp
|
||||||
|
|
||||||
def general_authenticate(self, p1, p2, data):
|
def general_authenticate(self, p1, p2, data):
|
||||||
if (p1, p2) != (0x00, 0x00):
|
if (p1, p2) != (0x00, 0x00):
|
||||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||||
@@ -80,7 +103,9 @@ class nPA_SE(Security_Environment):
|
|||||||
|
|
||||||
def __eac_abort(self):
|
def __eac_abort(self):
|
||||||
pace.EAC_CTX_clear_free(self.eac_ctx)
|
pace.EAC_CTX_clear_free(self.eac_ctx)
|
||||||
|
self.eac_ctx = None
|
||||||
pace.PACE_SEC_clear_free(self.sec)
|
pace.PACE_SEC_clear_free(self.sec)
|
||||||
|
self.sec = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __unpack_general_authenticate(data):
|
def __unpack_general_authenticate(data):
|
||||||
@@ -113,9 +138,21 @@ class nPA_SE(Security_Environment):
|
|||||||
elif self.at.keyref == '\x02':
|
elif self.at.keyref == '\x02':
|
||||||
self.sec = pace.PACE_SEC_new(self.sam.can, pace.PACE_CAN)
|
self.sec = pace.PACE_SEC_new(self.sam.can, pace.PACE_CAN)
|
||||||
elif self.at.keyref == '\x03':
|
elif self.at.keyref == '\x03':
|
||||||
self.sec = pace.PACE_SEC_new(self.sam.pin, pace.PACE_PIN)
|
if self.sam.counter <= 0:
|
||||||
|
print "Must use PUK to unblock"
|
||||||
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
|
if self.sam.counter == 1 and not self.sam.active:
|
||||||
|
print "Must use CAN to activate"
|
||||||
|
return 0x63c1, ""
|
||||||
|
self.sec = pace.PACE_SEC_new(self.sam.PIN, pace.PACE_PIN)
|
||||||
|
self.sam.counter -= 1
|
||||||
|
if self.sam.counter <= 1:
|
||||||
|
self.sam.active = False
|
||||||
elif self.at.keyref == '\x04':
|
elif self.at.keyref == '\x04':
|
||||||
|
if self.sam.counter_puk <= 0:
|
||||||
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
self.sec = pace.PACE_SEC_new(self.sam.puk, pace.PACE_PUK)
|
self.sec = pace.PACE_SEC_new(self.sam.puk, pace.PACE_PUK)
|
||||||
|
self.sam.counter_puk -= 1
|
||||||
else:
|
else:
|
||||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||||
|
|
||||||
@@ -172,13 +209,28 @@ class nPA_SE(Security_Environment):
|
|||||||
|
|
||||||
pace.PACE_STEP3C_derive_keys(self.eac_ctx)
|
pace.PACE_STEP3C_derive_keys(self.eac_ctx)
|
||||||
my_token = pace.buf2string(pace.PACE_STEP3D_compute_authentication_token(self.eac_ctx, self.pace_opp_pub_key))
|
my_token = pace.buf2string(pace.PACE_STEP3D_compute_authentication_token(self.eac_ctx, self.pace_opp_pub_key))
|
||||||
|
token = ""
|
||||||
for tag, length, value in tlv_data:
|
for tag, length, value in tlv_data:
|
||||||
if tag == 0x85:
|
if tag == 0x85:
|
||||||
pace.PACE_STEP3D_verify_authentication_token(self.eac_ctx, pace.get_buf(value))
|
token = value
|
||||||
else:
|
else:
|
||||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||||
|
|
||||||
|
if 1 != pace.PACE_STEP3D_verify_authentication_token(self.eac_ctx, pace.get_buf(token)):
|
||||||
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
|
|
||||||
|
if self.at.keyref == '\x02':
|
||||||
|
if (self.sam.counter == 1):
|
||||||
|
self.sam.active = True
|
||||||
|
print "PIN resumed"
|
||||||
|
elif self.at.keyref == '\x04':
|
||||||
|
self.sam.active = True
|
||||||
|
self.sam.counter = 3
|
||||||
|
print "PIN unblocked"
|
||||||
|
elif self.at.keyref == '\x03':
|
||||||
|
self.sam.active = True
|
||||||
|
self.sam.counter = 3
|
||||||
|
|
||||||
self.eac_step += 1
|
self.eac_step += 1
|
||||||
|
|
||||||
# TODO activate SM
|
# TODO activate SM
|
||||||
@@ -186,19 +238,24 @@ class nPA_SE(Security_Environment):
|
|||||||
return 0x9000, nPA_SE.__pack_general_authenticate([[0x86, len(my_token), my_token]])
|
return 0x9000, nPA_SE.__pack_general_authenticate([[0x86, len(my_token), my_token]])
|
||||||
|
|
||||||
def verify_certificate(se, p1, p2, data):
|
def verify_certificate(se, p1, p2, data):
|
||||||
pass
|
if (p1, p2) != (0x00, 0xbe):
|
||||||
|
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||||
|
|
||||||
|
cert = CHAT(bertlv_pack([[0x7f, len(data), data]]))
|
||||||
|
pace.TA_STEP2_import_certificate(self.eac_ctx, pace.get_buf(cert))
|
||||||
|
|
||||||
class nPA_SAM(SAM):
|
class nPA_SAM(SAM):
|
||||||
|
|
||||||
eac_step = make_property("eac_step", "next step to performed for EAC")
|
eac_step = make_property("eac_step", "next step to performed for EAC")
|
||||||
|
|
||||||
def __init__(self, pin, can, mrz, puk, mf, default_se = nPA_SE):
|
def __init__(self, pin, can, mrz, puk, mf, default_se = nPA_SE):
|
||||||
SAM.__init__(self, None, None, mf)
|
SAM.__init__(self, pin, None, mf)
|
||||||
|
self.active = True
|
||||||
self.current_SE = default_se(self.mf, self)
|
self.current_SE = default_se(self.mf, self)
|
||||||
self.pin = pin
|
|
||||||
self.can = can
|
self.can = can
|
||||||
self.mrz = mrz
|
self.mrz = mrz
|
||||||
self.puk = puk
|
self.puk = puk
|
||||||
|
self.counter_puk = 10
|
||||||
|
|
||||||
def general_authenticate(self, p1, p2, data):
|
def general_authenticate(self, p1, p2, data):
|
||||||
return self.current_SE.general_authenticate(p1, p2, data)
|
return self.current_SE.general_authenticate(p1, p2, data)
|
||||||
|
|||||||
Reference in New Issue
Block a user