diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/SEutils.py b/virtualsmartcard/src/vpicc/virtualsmartcard/SEutils.py index 89830d9..b7a457e 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/SEutils.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/SEutils.py @@ -226,7 +226,7 @@ class Security_Environment(object): #Verification, encryption, external authentication and key agreement if se & 0x08: self.external_auth = True - return self.__set_SE(p2, data) + return self._set_SE(p2, data) elif(cmd== 0x02): return self.sam.store_SE(p2) elif(cmd == 0x03): @@ -237,15 +237,12 @@ class Security_Environment(object): 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 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: return self.at.parse_SE_config(data) elif p2 == 0xA6: @@ -258,6 +255,8 @@ class Security_Environment(object): return self.dst.parse_SE_config(data) elif p2 == 0xB8: return self.ct.parse_SE_config(data) + + raise SwError(SW["ERR_INCORRECTP1P2"]) def parse_SM_CAPDU(self, CAPDU, authenticate_header): """ diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py index 8bc5de8..158cdcf 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py @@ -30,6 +30,7 @@ class nPA_AT_CRT(ControlReferenceTemplate): ControlReferenceTemplate.__init__(self, CRT_TEMPLATE["AT"]) def parse_SE_config(self, config): + r = 0x9000 try: ControlReferenceTemplate.parse_SE_config(self, config) except SwError as e: @@ -37,12 +38,11 @@ class nPA_AT_CRT(ControlReferenceTemplate): for tlv in structure: tag, length, value = tlv if tag == 0x7f4c: - from chat import CHAT chat = CHAT(bertlv_pack([[tag, length, value]])) print(chat) elif tag == 0x67: 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 pass elif tag == 0x91: @@ -51,7 +51,16 @@ class nPA_AT_CRT(ControlReferenceTemplate): else: 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): # TODO call __eac_abort whenever an error occurred @@ -63,6 +72,20 @@ class nPA_SE(Security_Environment): self.sec = 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): if (p1, p2) != (0x00, 0x00): raise SwError(SW["ERR_INCORRECTPARAMETERS"]) @@ -80,7 +103,9 @@ class nPA_SE(Security_Environment): def __eac_abort(self): pace.EAC_CTX_clear_free(self.eac_ctx) + self.eac_ctx = None pace.PACE_SEC_clear_free(self.sec) + self.sec = None @staticmethod def __unpack_general_authenticate(data): @@ -113,9 +138,21 @@ class nPA_SE(Security_Environment): elif self.at.keyref == '\x02': self.sec = pace.PACE_SEC_new(self.sam.can, pace.PACE_CAN) 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': + if self.sam.counter_puk <= 0: + raise SwError(SW["WARN_NOINFO63"]) self.sec = pace.PACE_SEC_new(self.sam.puk, pace.PACE_PUK) + self.sam.counter_puk -= 1 else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) @@ -172,13 +209,28 @@ class nPA_SE(Security_Environment): 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 = "" for tag, length, value in tlv_data: if tag == 0x85: - pace.PACE_STEP3D_verify_authentication_token(self.eac_ctx, pace.get_buf(value)) + token = value else: 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 # 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]]) 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): eac_step = make_property("eac_step", "next step to performed for EAC") 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.pin = pin self.can = can self.mrz = mrz self.puk = puk + self.counter_puk = 10 def general_authenticate(self, p1, p2, data): return self.current_SE.general_authenticate(p1, p2, data)