added support for TA and CA (currently untested)
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@676 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -149,7 +149,6 @@ class CardGenerator(object):
|
||||
self.mf = MF()
|
||||
self.mf.append(TransparentStructureEF(parent=self.mf, fid=0x011c, shortfid=0x1c, data=card_access))
|
||||
self.sam = nPA_SAM(pin="pin", can="can", mrz="mrz", puk="puk", mf=self.mf)
|
||||
self.sam.card_access = card_access
|
||||
|
||||
def __generate_cryptoflex(self):
|
||||
"""Generate the Filesystem and SAM of a cryptoflex card"""
|
||||
|
||||
@@ -499,6 +499,7 @@ class NPAOS(Iso7816OS):
|
||||
def __init__(self, mf, sam, ins2handler=None, maxle=MAX_EXTENDED_LE):
|
||||
Iso7816OS.__init__(self, mf, sam, ins2handler, maxle)
|
||||
self.ins2handler[0x86] = self.SAM.general_authenticate
|
||||
self.atr = '\x3B\x8A\x80\x01\x80\x31\xF8\x73\xF7\x41\xE0\x82\x90\x00\x75'
|
||||
|
||||
def formatResult(self, seekable, le, data, sw, sm):
|
||||
if seekable:
|
||||
@@ -564,7 +565,6 @@ class VirtualICC(object):
|
||||
self.os = Iso7816OS(MF, SAM)
|
||||
elif card_type == "nPA":
|
||||
self.os = NPAOS(MF, SAM)
|
||||
self.os.atr = '\x3B\x8A\x80\x01\x80\x31\xF8\x73\xF7\x41\xE0\x82\x90\x00\x75'
|
||||
elif card_type == "cryptoflex":
|
||||
self.os = CryptoflexOS(MF, SAM)
|
||||
elif card_type == "relay":
|
||||
|
||||
@@ -41,13 +41,12 @@ class nPA_AT_CRT(ControlReferenceTemplate):
|
||||
chat = CHAT(bertlv_pack([[tag, length, value]]))
|
||||
print(chat)
|
||||
elif tag == 0x67:
|
||||
auxiliary_data = value
|
||||
self.auxiliary_data = value
|
||||
elif tag == 0x80 or tag == 0x84 or tag == 0x83:
|
||||
# handled by ControlReferenceTemplate.parse_SE_config
|
||||
pass
|
||||
elif tag == 0x91:
|
||||
eph_key = value
|
||||
# TODO handle security environment
|
||||
self.eph_pub_key = value
|
||||
else:
|
||||
raise SwError(SW["ERR_REFNOTUSABLE"])
|
||||
|
||||
@@ -81,7 +80,7 @@ class nPA_SE(Security_Environment):
|
||||
if self.eac_step != 4:
|
||||
SwError(SW["ERR_AUTHBLOCKED"])
|
||||
elif self.at.algorithm == "CA":
|
||||
if self.eac_step != 7:
|
||||
if self.eac_step != 5:
|
||||
SwError(SW["ERR_AUTHBLOCKED"])
|
||||
|
||||
return sw, resp
|
||||
@@ -90,14 +89,16 @@ class nPA_SE(Security_Environment):
|
||||
if (p1, p2) != (0x00, 0x00):
|
||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||
|
||||
if (self.eac_step == 0):
|
||||
if self.eac_step == 0 and self.at.algorithm == "PACE":
|
||||
return self.__eac_pace_step1(data)
|
||||
elif (self.eac_step == 1):
|
||||
elif self.eac_step == 1 and self.at.algorithm == "PACE":
|
||||
return self.__eac_pace_step2(data)
|
||||
elif (self.eac_step == 2):
|
||||
elif self.eac_step == 2 and self.at.algorithm == "PACE":
|
||||
return self.__eac_pace_step3(data)
|
||||
elif (self.eac_step == 3):
|
||||
elif self.eac_step == 3 and self.at.algorithm == "PACE":
|
||||
return self.__eac_pace_step4(data)
|
||||
elif self.eac_step == 5 and self.at.algorithm == "CA":
|
||||
return self.__eac_ca(data)
|
||||
|
||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||
|
||||
@@ -126,8 +127,7 @@ class nPA_SE(Security_Environment):
|
||||
|
||||
def __eac_pace_step1(self, data):
|
||||
tlv_data = nPA_SE.__unpack_general_authenticate(data)
|
||||
if self.at.algorithm != "PACE" or tlv_data != []:
|
||||
print 'value %r' % tlv_data
|
||||
if tlv_data != []:
|
||||
raise SwError(SW["WARN_NOINFO63"])
|
||||
|
||||
self.__eac_abort()
|
||||
@@ -169,8 +169,6 @@ class nPA_SE(Security_Environment):
|
||||
|
||||
def __eac_pace_step2(self, data):
|
||||
tlv_data = nPA_SE.__unpack_general_authenticate(data)
|
||||
if self.at.algorithm != "PACE":
|
||||
raise SwError(SW["WARN_NOINFO63"])
|
||||
|
||||
pubkey = pace.buf2string(pace.PACE_STEP3A_generate_mapping_data(self.eac_ctx))
|
||||
|
||||
@@ -186,8 +184,6 @@ class nPA_SE(Security_Environment):
|
||||
|
||||
def __eac_pace_step3(self, data):
|
||||
tlv_data = nPA_SE.__unpack_general_authenticate(data)
|
||||
if self.at.algorithm != "PACE":
|
||||
raise SwError(SW["WARN_NOINFO63"])
|
||||
|
||||
my_epp_pubkey = pace.buf2string(pace.PACE_STEP3B_generate_ephemeral_key(self.eac_ctx))
|
||||
|
||||
@@ -204,9 +200,6 @@ class nPA_SE(Security_Environment):
|
||||
|
||||
def __eac_pace_step4(self, data):
|
||||
tlv_data = nPA_SE.__unpack_general_authenticate(data)
|
||||
if self.at.algorithm != "PACE":
|
||||
raise SwError(SW["WARN_NOINFO63"])
|
||||
|
||||
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))
|
||||
token = ""
|
||||
@@ -237,12 +230,59 @@ class nPA_SE(Security_Environment):
|
||||
|
||||
return 0x9000, nPA_SE.__pack_general_authenticate([[0x86, len(my_token), my_token]])
|
||||
|
||||
def __eac_ca(self, data):
|
||||
tlv_data = nPA_SE.__unpack_general_authenticate(data)
|
||||
|
||||
pubkey = ""
|
||||
for tag, length, value in tlv_data:
|
||||
if tag == 0x80:
|
||||
pubkey = value
|
||||
else:
|
||||
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
|
||||
|
||||
pace.CA_STEP4_compute_shared_secret(self.eac_ctx,
|
||||
pace.get_buf(pubkey))
|
||||
|
||||
nonce, token = pace.CA_STEP5_derive_keys(self.eac_ctx,
|
||||
pace.get_buf(pubkey))
|
||||
|
||||
# TODO activate SM
|
||||
|
||||
return 0x9000, nPA_SE.__pack_general_authenticate([[0x81,
|
||||
len(nonce), nonce], [0x82, len(token), token]])
|
||||
|
||||
def verify_certificate(se, p1, p2, data):
|
||||
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))
|
||||
cert = bertlv_pack([[0x7f, len(data), data]])
|
||||
if 1 != pace.TA_STEP2_import_certificate(self.eac_ctx, pace.get_buf(cert)):
|
||||
raise SwError(SW["ERR_NOINFO69"])
|
||||
|
||||
def external_authenticate(self, p1, p2, data):
|
||||
"""
|
||||
Authenticate the terminal to the card. Check whether Terminal correctly
|
||||
encrypted the given challenge or not
|
||||
"""
|
||||
if self.at.algorithm == "TA":
|
||||
if self.last_challenge is None:
|
||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||
|
||||
pace.EAC_CTX_init_ta(self.eac_ctx, "", 0, self.dst.keyref,
|
||||
len(self.dst.keyref), "", 0)
|
||||
|
||||
if 1 != pace.TA_STEP6_verify(self.eac_ctx,
|
||||
pace.get_buf(self.at.eph_pub_key), id_picc,
|
||||
pace.get_buf(self.last_challenge),
|
||||
pace.get_buf(self.auxiliary_data), pace.get_buf(data)):
|
||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||
|
||||
self.eac_step += 1
|
||||
|
||||
return 0x9000, ""
|
||||
|
||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||
|
||||
|
||||
class nPA_SAM(SAM):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user