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"]) if eac.CA_STEP4_compute_shared_secret(self.eac_ctx, pubkey) != 1: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) nonce, token = eac.CA_STEP5_derive_keys(self.eac_ctx, pubkey) if not nonce or not token: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) self.eac_step += 1 print "Generated Nonce and Authentication Token for CA" # TODO activate SM self.new_encryption_ctx = eac.EAC_ID_CA return 0x9000, nPA_SE.__pack_general_authenticate([[0x81, len(nonce), nonce], [0x82, len(token), token]])
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.dst.keyref_public_key: # TODO check if this is the correct CAR id_picc = eac.EAC_Comp(self.eac_ctx, eac.EAC_ID_PACE, self.my_pace_eph_pubkey) # FIXME auxiliary_data might be from an older run of PACE if hasattr(self.at, "auxiliary_data"): auxiliary_data = self.at.auxiliary_data else: auxiliary_data = None if 1 != eac.TA_STEP6_verify(self.eac_ctx, self.at.iv, id_picc, auxiliary_data, data): eac.print_ossl_err() print("Could not verify Terminal's signature") raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) print("Terminal's signature verified") self.eac_step += 1 return 0x9000, b"" raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
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"]) if eac.CA_STEP4_compute_shared_secret(self.eac_ctx, pubkey) != 1: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) nonce, token = eac.CA_STEP5_derive_keys(self.eac_ctx, pubkey) if not nonce or not token: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) self.eac_step += 1 print("Generated Nonce and Authentication Token for CA") # TODO activate SM self.new_encryption_ctx = eac.EAC_ID_CA return 0x9000, \ nPA_SE.__pack_general_authenticate([[0x81, len(nonce), nonce], [0x82, len(token), token]])
def compute_cryptographic_checksum(self, p1, p2, data): checksum = eac.EAC_authenticate(self.eac_ctx, data) if not checksum: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) return checksum
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.dst.keyref_public_key: # TODO check if this is the correct CAR id_picc = eac.EAC_Comp(self.eac_ctx, eac.EAC_ID_PACE, self.my_pace_eph_pubkey) # FIXME auxiliary_data might be from an older run of PACE if hasattr(self.at, "auxiliary_data"): auxiliary_data = self.at.auxiliary_data else: auxiliary_data = None if 1 != eac.TA_STEP6_verify(self.eac_ctx, self.at.iv, id_picc, auxiliary_data, data): eac.print_ossl_err() print "Could not verify Terminal's signature" raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) print "Terminal's signature verified" self.eac_step += 1 return 0x9000, "" raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
def decipher(self, p1, p2, data): plain = eac.EAC_decrypt(self.eac_ctx, data) if not plain: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) return plain
def encipher(self, p1, p2, data): padded = vsCrypto.append_padding(self.cct.blocklength, data) cipher = eac.EAC_encrypt(self.eac_ctx, padded) if not cipher: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) return cipher
def __str__(self): eac.print_ossl_err() print ret_str = "Error " if (self.protocol_step is not None): ret_str += "during " + self.protocol_step + " " if (self.role is not None): ret_str += "at the " + self.role + " side:\n\t" return ret_str + self.reason
def verify_certificate(self, p1, p2, data): if (p1, p2) != (0x00, 0xbe): raise SwError(SW["ERR_INCORRECTPARAMETERS"]) cert = bertlv_pack([[0x7f21, len(data), data]]) if 1 != eac.TA_STEP2_import_certificate(self.eac_ctx, cert): eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) print("Imported Certificate") return b""
def verify_certificate(self, p1, p2, data): if (p1, p2) != (0x00, 0xbe): raise SwError(SW["ERR_INCORRECTPARAMETERS"]) cert = bertlv_pack([[0x7f21, len(data), data]]) if 1 != eac.TA_STEP2_import_certificate(self.eac_ctx, cert): eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) print "Imported Certificate" return ""
def get_challenge(self, p1, p2, data): if self.current_SE.eac_step == 4: # TA if (p1 != 0x00 or p2 != 0x00): raise SwError(SW["ERR_INCORRECTP1P2"]) self.last_challenge = eac.TA_STEP4_get_nonce(self.current_SE.eac_ctx) if not self.last_challenge: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) else: SAM.get_challenge(self, p1, p2, data) return SW["NORMAL"], self.last_challenge
def __eac_pace_step4(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) eac.PACE_STEP3C_derive_keys(self.eac_ctx) my_token = \ eac.PACE_STEP3D_compute_authentication_token(self.eac_ctx, self.pace_opp_pub_key) token = b"" for tag, length, value in tlv_data: if tag == 0x85: token = value else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) ver = eac.PACE_STEP3D_verify_authentication_token(self.eac_ctx, token) if not my_token or ver != 1: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) print("Established PACE channel") if self.at.keyref_is_can(): if (self.sam.counter == 1): self.sam.active = True print("PIN resumed") elif self.at.keyref_is_pin(): self.sam.active = True self.sam.counter = 3 elif self.at.keyref_is_puk(): self.sam.active = True self.sam.counter = 3 print("PIN unblocked") self.eac_step += 1 self.at.algorithm = "TA" self.new_encryption_ctx = eac.EAC_ID_PACE result = [[0x86, len(my_token), my_token]] if self.at.chat: if self.cvca: self.car = CVC(self.cvca).get_chr() result.append([0x87, len(self.car), self.car]) if (self.disable_checks): eac.TA_disable_checks(self.eac_ctx) if not eac.EAC_CTX_init_ta(self.eac_ctx, None, self.cvca): eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) return 0x9000, nPA_SE.__pack_general_authenticate(result)
def __eac_pace_step4(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) eac.PACE_STEP3C_derive_keys(self.eac_ctx) my_token = \ eac.PACE_STEP3D_compute_authentication_token(self.eac_ctx, self.pace_opp_pub_key) token = "" for tag, length, value in tlv_data: if tag == 0x85: token = value else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) ver = eac.PACE_STEP3D_verify_authentication_token(self.eac_ctx, token) if not my_token or ver != 1: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) print "Established PACE channel" if self.at.keyref_is_can(): if (self.sam.counter == 1): self.sam.active = True print "PIN resumed" elif self.at.keyref_is_pin(): self.sam.active = True self.sam.counter = 3 elif self.at.keyref_is_puk(): self.sam.active = True self.sam.counter = 3 print "PIN unblocked" self.eac_step += 1 self.at.algorithm = "TA" self.new_encryption_ctx = eac.EAC_ID_PACE result = [[0x86, len(my_token), my_token]] if self.at.chat: if self.cvca: self.car = CVC(self.cvca).get_chr() result.append([0x87, len(self.car), self.car]) if (self.disable_checks): eac.TA_disable_checks(self.eac_ctx) if not eac.EAC_CTX_init_ta(self.eac_ctx, None, self.cvca): eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) return 0x9000, nPA_SE.__pack_general_authenticate(result)
def get_challenge(self, p1, p2, data): if self.current_SE.eac_step == 4: # TA if (p1 != 0x00 or p2 != 0x00): raise SwError(SW["ERR_INCORRECTP1P2"]) self.last_challenge = \ eac.TA_STEP4_get_nonce(self.current_SE.eac_ctx) if not self.last_challenge: eac.print_ossl_err() raise SwError(SW["ERR_NOINFO69"]) else: SAM.get_challenge(self, p1, p2, data) return SW["NORMAL"], self.last_challenge
def __eac_pace_step2(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) pubkey = eac.PACE_STEP3A_generate_mapping_data(self.eac_ctx) if not pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) for tag, length, value in tlv_data: if tag == 0x81: eac.PACE_STEP3A_map_generator(self.eac_ctx, value) else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.eac_step += 1 return 0x9000, nPA_SE.__pack_general_authenticate([[0x82, len(pubkey), pubkey]])
def __eac_pace_step2(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) pubkey = eac.PACE_STEP3A_generate_mapping_data(self.eac_ctx) if not pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) for tag, length, value in tlv_data: if tag == 0x81: eac.PACE_STEP3A_map_generator(self.eac_ctx, value) else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.eac_step += 1 return 0x9000, \ nPA_SE.__pack_general_authenticate([[0x82, len(pubkey), pubkey]])
def __eac_pace_step3(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) self.my_pace_eph_pubkey = eac.PACE_STEP3B_generate_ephemeral_key(self.eac_ctx) if not self.my_pace_eph_pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) eph_pubkey = self.my_pace_eph_pubkey for tag, length, value in tlv_data: if tag == 0x83: self.pace_opp_pub_key = value eac.PACE_STEP3B_compute_shared_secret(self.eac_ctx, self.pace_opp_pub_key) else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.eac_step += 1 return 0x9000, nPA_SE.__pack_general_authenticate([[0x84, len(eph_pubkey), eph_pubkey]])
def __eac_pace_step3(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) self.my_pace_eph_pubkey = eac.PACE_STEP3B_generate_ephemeral_key( self.eac_ctx) if not self.my_pace_eph_pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) eph_pubkey = self.my_pace_eph_pubkey for tag, length, value in tlv_data: if tag == 0x83: self.pace_opp_pub_key = value eac.PACE_STEP3B_compute_shared_secret(self.eac_ctx, self.pace_opp_pub_key) else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.eac_step += 1 return 0x9000, nPA_SE.__pack_general_authenticate( [[0x84, len(eph_pubkey), eph_pubkey]])
def __init__(self, value): self.value = eac.print_ossl_err() + value
def __eac_pace_step1(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) if tlv_data != []: raise SwError(SW["WARN_NOINFO63"]) if self.at.keyref_is_mrz(): self.PACE_SEC = PACE_SEC(self.sam.mrz, eac.PACE_MRZ) elif self.at.keyref_is_can(): self.PACE_SEC = PACE_SEC(self.sam.can, eac.PACE_CAN) elif self.at.keyref_is_pin(): if self.sam.counter <= 0: print("Must use PUK to unblock") return 0x63c0, b"" if self.sam.counter == 1 and not self.sam.active: print("Must use CAN to activate") return 0x63c1, b"" self.PACE_SEC = PACE_SEC(self.sam.eid_pin, eac.PACE_PIN) self.sam.counter -= 1 if self.sam.counter <= 1: self.sam.active = False elif self.at.keyref_is_puk(): if self.sam.counter_puk <= 0: raise SwError(SW["WARN_NOINFO63"]) self.PACE_SEC = PACE_SEC(self.sam.puk, eac.PACE_PUK) self.sam.counter_puk -= 1 else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.sec = self.PACE_SEC.sec if not self.eac_ctx: eac.EAC_init() self.EAC_CTX = EAC_CTX() self.eac_ctx = self.EAC_CTX.ctx eac.CA_disable_passive_authentication(self.eac_ctx) ef_card_security = self.mf.select('fid', 0x011d) ef_card_security_data = ef_card_security.data eac.EAC_CTX_init_ef_cardsecurity(ef_card_security_data, self.eac_ctx) if self.ca_key: ca_pubkey = eac.CA_get_pubkey(self.eac_ctx, ef_card_security_data) if 1 != eac.CA_set_key(self.eac_ctx, self.ca_key, ca_pubkey): eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) else: # we don't have a good CA key, so we simply generate an # ephemeral one comp_pubkey = eac.TA_STEP3_generate_ephemeral_key(self.eac_ctx) pubkey = eac.CA_STEP2_get_eph_pubkey(self.eac_ctx) if not comp_pubkey or not pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) # save public key in EF.CardSecurity (and invalidate the # signature) # FIXME this only works for the default EF.CardSecurity. # Better use an ASN.1 parser to do this manipulation ef_card_security = self.mf.select('fid', 0x011d) ef_card_security_data = ef_card_security.data ef_card_security_data = \ ef_card_security_data[:61+4+239+2+1] + pubkey + \ ef_card_security_data[61+4+239+2+1+len(pubkey):] ef_card_security.data = ef_card_security_data nonce = eac.PACE_STEP1_enc_nonce(self.eac_ctx, self.sec) if not nonce: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) resp = nPA_SE.__pack_general_authenticate([[0x80, len(nonce), nonce]]) self.eac_step += 1 return 0x9000, resp
def __eac_pace_step1(self, data): tlv_data = nPA_SE.__unpack_general_authenticate(data) if tlv_data != []: raise SwError(SW["WARN_NOINFO63"]) if self.at.keyref_is_mrz(): self.PACE_SEC = PACE_SEC(self.sam.mrz, eac.PACE_MRZ) elif self.at.keyref_is_can(): self.PACE_SEC = PACE_SEC(self.sam.can, eac.PACE_CAN) elif self.at.keyref_is_pin(): if self.sam.counter <= 0: print "Must use PUK to unblock" return 0x63c0, "" if self.sam.counter == 1 and not self.sam.active: print "Must use CAN to activate" return 0x63c1, "" self.PACE_SEC = PACE_SEC(self.sam.eid_pin, eac.PACE_PIN) self.sam.counter -= 1 if self.sam.counter <= 1: self.sam.active = False elif self.at.keyref_is_puk(): if self.sam.counter_puk <= 0: raise SwError(SW["WARN_NOINFO63"]) self.PACE_SEC = PACE_SEC(self.sam.puk, eac.PACE_PUK) self.sam.counter_puk -= 1 else: raise SwError(SW["ERR_INCORRECTPARAMETERS"]) self.sec = self.PACE_SEC.sec if not self.eac_ctx: eac.EAC_init() self.EAC_CTX = EAC_CTX() self.eac_ctx = self.EAC_CTX.ctx eac.CA_disable_passive_authentication(self.eac_ctx) ef_card_security = self.mf.select('fid', 0x011d) ef_card_security_data = ef_card_security.data eac.EAC_CTX_init_ef_cardsecurity(ef_card_security_data, self.eac_ctx) if self.ca_key: ca_pubkey = eac.CA_get_pubkey(self.eac_ctx, ef_card_security_data) if 1 != eac.CA_set_key(self.eac_ctx, self.ca_key, ca_pubkey): eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) else: # we don't have a good CA key, so we simply generate an ephemeral one comp_pubkey = eac.TA_STEP3_generate_ephemeral_key(self.eac_ctx) pubkey = eac.CA_STEP2_get_eph_pubkey(self.eac_ctx) if not comp_pubkey or not pubkey: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) # save public key in EF.CardSecurity (and invalidate the signature) # FIXME this only works for the default EF.CardSecurity. # Better use an ASN.1 parser to do this manipulation ef_card_security = self.mf.select('fid', 0x011d) ef_card_security_data = ef_card_security.data ef_card_security_data = ef_card_security_data[:61+4+239+2+1] + pubkey + ef_card_security_data[61+4+239+2+1+len(pubkey):] ef_card_security.data = ef_card_security_data nonce = eac.PACE_STEP1_enc_nonce(self.eac_ctx, self.sec) if not nonce: eac.print_ossl_err() raise SwError(SW["WARN_NOINFO63"]) resp = nPA_SE.__pack_general_authenticate([[0x80, len(nonce), nonce]]) self.eac_step += 1 return 0x9000, resp