Beispiel #1
0
def send(sm_object: SMObject, apdu: APDU) -> bytes:
    """
    Send APDU to the channel and return the data if there are no errors.
    """
    channel = sm_object.channel
    apdu_bytes = secure_messaging(sm_object, apdu)

    data, sw1, sw2 = channel.transmit(list(apdu_bytes))

    # success
    if [sw1, sw2] == [0x90, 0x00]:
        try:
            data = process_rapdu(sm_object, bytes(data))
        except ReplyAPDUError as ex:
            raise CardCommunicationError(
                "[-] Reply APDU MAC doesn't match!") from ex
        else:
            return data
    # signals that there is more data to read
    if sw1 == 0x61:
        print("[=] TAKE A LOOK! More data to read:", sw2)
        return data + send(sm_object,
                           APDU(b"\x00", b"\xC0", b"\x00", b"\x00",
                                Le=nb(sw2)))  # GET RESPONSE of sw2 bytes
    if sw1 == 0x6C:
        print("[=] TAKE A LOOK! Resending with Le:", sw2)
        return send(sm_object,
                    APDU(apdu.cla, apdu.ins, apdu.p1, apdu.p2,
                         Le=nb(sw2)))  # resend APDU with Le = sw2
    # probably error condition
    # channel.disconnect()
    print("[-] Card communication error occured.")
    print("Error: %02x %02x, sending APDU: %s" %
          (sw1, sw2, " ".join(["{:02x}".format(x)
                               for x in apdu_bytes]).upper()))
    print("Plain APDU: " + " ".join([
        "{:02x}".format(x)
        for x in (apdu.get_command_header() + (apdu.Lc or b"") +
                  (apdu.cdata or b"") + (apdu.Le or b""))
    ]).upper())
    raise CardCommunicationError(
        "Error: %02x %02x, sending APDU: %s" %
        (sw1, sw2, " ".join(["{:02x}".format(x) for x in apdu_bytes]).upper()))
Beispiel #2
0
def establish_bac_session_keys(sm_object: SMObject, secret: bytes):
    """
    This function establishes session keys with the card
    Sets the necessary values of sm_object
    """
    # Calculate the SHA-1 hash of ‘MRZ_information’ and
    # take the most significant 16 bytes to form the basic access key seed
    ba_key_seed = hashlib.sha1(secret).digest()[:16]
    # Calculate the basic access keys (ba_key_enc and ba_key_mac)
    print("[+] Computing basic access keys...")
    ba_key_enc = compute_key(ba_key_seed, "enc", "3DES")
    ba_key_mac = compute_key(ba_key_seed, "mac", "3DES")

    ## AUTHENTICATION AND ESTABLISHMENT OF SESSION KEYS ##
    print("[+] Establishing session keys...")
    # exception caught in main program loop
    rnd_ic = send(sm_object,
                  APDU(b"\x00", b"\x84", b"\x00", b"\x00", Le=b"\x08"))

    rnd_ifd = urandom(8)
    k_ifd = urandom(16)
    s = rnd_ifd + rnd_ic + k_ifd
    e_cipher = DES3.new(ba_key_enc, DES3.MODE_CBC, bytes([0] * 8))
    e_ifd = e_cipher.encrypt(s)
    m_ifd = compute_mac(ba_key_mac, padding_method_2(e_ifd, 8), "DES")
    # Construct command data for EXTERNAL AUTHENTICATE
    cmd_data = e_ifd + m_ifd

    # exception caught in main program loop
    resp_data_enc = send(
        sm_object,
        APDU(b"\x00",
             b"\x82",
             b"\x00",
             b"\x00",
             Lc=nb(len(cmd_data)),
             cdata=cmd_data,
             Le=b"\x28"),
    )
    m_ic = compute_mac(ba_key_mac, padding_method_2(resp_data_enc[:-8], 8),
                       "DES")
    if m_ic != resp_data_enc[-8:]:
        raise SessionKeyEstablishmentError(
            "[-] Encrypted message MAC is not correct!")

    d_cipher = DES3.new(ba_key_enc, DES3.MODE_CBC, bytes([0] * 8))
    resp_data = d_cipher.decrypt(resp_data_enc[:-8])
    if resp_data[:8] != rnd_ic:
        raise SessionKeyEstablishmentError(
            "[-] Received RND.IC DOES NOT match with the earlier RND.IC")
    if resp_data[8:16] != rnd_ifd:
        raise SessionKeyEstablishmentError(
            "[-] Received RND.IFD DOES NOT match with the generated RND.IFD")

    k_ic = resp_data[16:]

    # Calculate XOR of KIFD and KIC
    ses_key_seed = strxor(k_ifd, k_ic)
    # Calculate session keys (ks_enc and ks_mac)
    print("[+] Computing session keys...")
    ks_enc = compute_key(ses_key_seed, "enc", "3DES")
    ks_mac = compute_key(ses_key_seed, "mac", "3DES")

    # Calculate send sequence counter
    ssc = rnd_ic[-4:] + rnd_ifd[-4:]

    sm_object.enc_alg = "3DES"
    sm_object.mac_alg = "DES"
    sm_object.pad_len = 8
    sm_object.ks_enc = ks_enc
    sm_object.ks_mac = ks_mac
    sm_object.ssc = ssc
def program_logic(window: sg.Window):
    camera_id = -1
    mrz, _ = capture_mrz(window, camera_id)
    mrz_print = "\n".join(mrz)
    print(f"[i] MRZ Read:\n{mrz_print}")
    document_number, birthdate, expiry_date, issuing_country, name, surname = parse_mrz_text(
        mrz)
    mrz_information = other_mrz(document_number, birthdate, expiry_date)

    sm_object = SMObject(wait_for_card())

    atr = sm_object.channel.getATR()
    print("[+] Card ATR: " + toHexString(atr))

    # Select MF
    try:
        send(sm_object, APDU(b"\x00", b"\xA4", b"\x00", b"\x0C"))
    except CardCommunicationError:
        pass
    except CardConnectionException as ex:
        print(ex)
        pass
    else:
        print("[+] MF selected.")

    # Read EF.CardAccess
    ef_cardaccess = None
    try:
        ef_cardaccess = read_data_from_ef(window, sm_object, b"\x01\x1C",
                                          "EF.CardAccess")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.CardAccess.")
        pass
    except CardCommunicationError:
        pass
    except CardConnectionException as ex:
        print(ex)
        pass
    else:
        # print(f"[i] EF.CardAccess Read: {toHexString(list(ef_cardaccess))}")
        security_infos_efca = parse_security_infos(ef_cardaccess)
        # pace(security_infos_efca, sm_object)

    # Read EF.DIR
    try:
        ef_dir = read_data_from_ef(window, sm_object, b"\x2F\x00", "EF.DIR")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.DIR.")
    except CardCommunicationError:
        pass
    except CardConnectionException as ex:
        print(ex)
        pass
    else:
        print(f"[i] EF.DIR Read: {toHexString(list(ef_cardaccess))}")

    # Select eMRTD Applet
    print("[+] Selecting LDS DF AID: A0000002471001...")
    aid = bytes.fromhex("A0000002471001")
    try:
        send(
            sm_object,
            APDU(b"\x00",
                 b"\xA4",
                 b"\x04",
                 b"\x0C",
                 Lc=nb(len(aid)),
                 cdata=aid))
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    ## SECURE MESSAGING ##
    try:
        establish_bac_session_keys(sm_object, mrz_information.encode("utf-8"))
    except SessionKeyEstablishmentError as ex:
        print(ex)
        print("[-] Error while establishing BAC session keys")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    # Read EF.COM
    try:
        efcom = read_data_from_ef(window, sm_object, b"\x01\x1E", "EF.COM")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.COM.")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    else:
        # print(f"[i] EF.COM Read: {toHexString(list(efcom))}")
        ef_com_dg_list = parse_efcom(efcom)
        print(f"[i] DGs specified in EF.COM: {list(ef_com_dg_list.values())}")

    # Read EF.DG14
    try:
        dg14 = read_data_from_ef(window, sm_object, b"\x01\x0E", "EF.DG14")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.DG14.")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    else:
        # print(f"[i] EF.DG14 Read: {toHexString(list(dg14))}")
        security_infos_dg14 = parse_security_infos(dg14)
        for si in security_infos_efca:
            assert si in security_infos_dg14
            # print(dump_asn1(si))

    window.write_event_value("-RESTART-", "")
    return
Beispiel #4
0
def main(
    window: sg.Window,
    args: argparse.Namespace,
    db: TinyDB,
    q: Queue,
    q2: Queue,
    lock: threading.Lock,
    lock2: threading.Lock,
    first_run: bool,
) -> None:
    """main function"""

    # Get dir arguments else fallback to EE certs
    CSCA_certs_dir = args.certs or Path("certs/csca_certs")
    crls_dir = args.certs or Path("certs/crls")
    output_dir = args.output
    output_files = not args.output is None
    camera_id = -1
    outfile: Union[TextIO, BinaryIO]

    if (args.online and first_run) or (
        not os.path.isdir(CSCA_certs_dir) or not os.path.isdir(crls_dir)
    ):
        window.write_event_value(
            "-DOWNLOAD CSCA CERT AND CRL-",
            [True, "text_download_csca_crl", "Downloading CSCA certificates and CRLs...", "white"],
        )
        download_certs(CSCA_certs_dir, crls_dir)
        window.write_event_value(
            "-DOWNLOAD CSCA CERT AND CRL-",
            [True, "text_download_csca_crl_status", "OK", "green"],
        )

    if first_run:
        dsccrl_dir = Path(os.path.join(os.path.dirname(CSCA_certs_dir), Path("icao_pkd_dsccrl")))
        ml_dir = Path(os.path.join(os.path.dirname(CSCA_certs_dir), Path("icao_pkd_ml")))
        window.write_event_value(
            "-BUILD CERT STORE-",
            [True, "build_cert_store", "Building certificate store...", "white"],
        )
        build_store(CSCA_certs_dir, crls_dir, ml_dir, dsccrl_dir)
        window.write_event_value(
            "-BUILD CERT STORE-",
            [True, "build_cert_store_status", "OK", "green"],
        )

        # create face detector network
        if args.biometric:
            from emrtd_face_access.face_compare import opencv_dnn_detector

            opencv_dnn_detector()

    if args.mrz:
        window.write_event_value(
            "-SHOW DOCUMENT TO CAMERA-",
            [
                True,
                "text_instruction",
                "Please show the Machine Readable Zone (MRZ) of your document to the camera.",
                "white",
            ],
        )
        window.write_event_value(
            "-READ MRZ-",
            [True, "read_mrz", "Trying to capture MRZ information...", "white"],
        )
        mrz, mrz_image = capture_mrz(window, camera_id)

        document_number, birthdate, expiry_date, issuing_country, name, surname = parse_mrz_text(
            mrz
        )
        mrz_information = other_mrz(document_number, birthdate, expiry_date)
        window.write_event_value(
            "-WRITE NAME-",
            [True, "text_name_surname", f"NAME: {name} {surname}", "white"],
        )
        window.write_event_value(
            "-WRITE DOC NUM-",
            [True, "text_doc_num", f"DOCUMENT NUMBER: {document_number}", "white"],
        )
        window.write_event_value(
            "-READ MRZ-",
            [True, "read_mrz_status", "OK", "green"],
        )

    print("[?] Please place your document onto the card reader.")
    window.write_event_value(
        "-PLACE DOCUMENT-",
        [
            True,
            "text_instruction",
            "Please place your document onto the card reader.",
            "white",
        ],
    )
    window.write_event_value(
        "-WAIT FOR DOCUMENT-",
        [True, "text_card_insert", "Waiting for a document...", "white"],
    )
    sm_object = SMObject(wait_for_card())
    window.write_event_value("-PLACE DOCUMENT-", [True, "text_instruction", "", "white"])
    window.write_event_value(
        "-WAIT FOR DOCUMENT-",
        [True, "text_card_insert_status", "OK", "green"],
    )
    atr = sm_object.channel.getATR()

    print("[+] Card ATR: " + toHexString(atr))

    ## DERIVATION OF DOCUMENT BASIC ACCESS KEYS (KENC AND KMAC) ##
    if args.ee:
        try:
            (
                mrz_information,
                document_number,
                personal_id_code,
                name,
                surname,
            ) = estonia_read_mrz(sm_object)
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        else:
            issuing_country = "EST"
            window.write_event_value(
                "-WRITE NAME-",
                [True, "text_name_surname", f"NAME: {name} {surname}", "white"],
            )
            window.write_event_value(
                "-WRITE DOC NUM-",
                [True, "text_doc_num", f"DOCUMENT NUMBER: {document_number}", "white"],
            )
            window.write_event_value(
                "-WRITE ID CODE-",
                [True, "text_personal_code", f"PERSONAL ID CODE: {personal_id_code}", "white"],
            )
    if output_files:
        folder_name = create_output_folder(output_dir, document_number)

    if args.mrz and output_files:
        with open(os.path.join(folder_name, "mrz_text.txt"), "wt") as outfile:
            outfile.write("\n".join(mrz))

        mrz_image.save(os.path.join(folder_name, "mrz_photo.jpeg"))

    # Select eMRTD application
    print("[+] Selecting eMRTD Application ‘International AID’: A0000002471001...")
    aid = bytes.fromhex("A0000002471001")
    try:
        send(sm_object, APDU(b"\x00", b"\xA4", b"\x04", b"\x0C", Lc=nb(len(aid)), cdata=aid))
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    ## SECURE MESSAGING ##
    try:
        establish_bac_session_keys(sm_object, mrz_information.encode("utf-8"))
    except SessionKeyEstablishmentError as ex:
        print(ex)
        print("[-] Error while establishing BAC session keys")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    # Read EF.COM
    try:
        efcom = read_data_from_ef(window, sm_object, b"\x01\x1E", "EF.COM")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.COM.")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    else:
        if output_files:
            with open(os.path.join(folder_name, "EF_COM.BIN"), "wb") as outfile:
                outfile.write(efcom)
        ef_com_dg_list = parse_efcom(efcom)

    # Read EF.SOD
    try:
        efsod = read_data_from_ef(window, sm_object, b"\x01\x1D", "EF.SOD")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.SOD.")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    else:
        if output_files:
            with open(os.path.join(folder_name, "EF_SOD.BIN"), "wb") as outfile:
                outfile.write(efsod)

    window.write_event_value(
        "-PASSIVE AUTHENTICATION-",
        [True, "text_authentic", "Passive Authentication...", "white"],
    )
    pa_error = False
    ee_deviant_doc = False
    if issuing_country == "EST":
        try:
            with open(Path("certs/erpdeviationlist.bin"), "rb") as infile:
                deviation_docs = infile.read()
        except FileNotFoundError:
            pass
        else:
            if deviation_docs.find(document_number.encode("utf-8")) != -1:
                ee_deviant_doc = True
    try:
        passive_auth_return = passive_auth(efsod, ee_deviant_doc=ee_deviant_doc, dump=False)
    except PassiveAuthenticationCriticalError as ex:
        print(ex)
        window.write_event_value(
            "-PASSIVE AUTHENTICATION-",
            [False, "text_authentic_status", "ERROR", "red"],
        )
    else:
        if output_files:
            with open(os.path.join(folder_name, "CDS.der"), "wb") as outfile:
                outfile.write(passive_auth_return[2])
        if passive_auth_return[3] is None:
            pa_error = False
            hash_alg, data_group_hash_values, _, _ = passive_auth_return
        else:
            pa_error = True
            hash_alg, data_group_hash_values, _, exception = passive_auth_return
            print(exception)
            window.write_event_value(
                "-PASSIVE AUTHENTICATION-",
                [False, "text_authentic_status", "ERROR", "red"],
            )

    if atr in atr_exceptions and hash_alg == "sha256":
        hash_alg = "sha1"

    ef_sod_dg_list = get_dg_numbers(data_group_hash_values)

    if ef_com_dg_list != ef_sod_dg_list:
        print(
            "[-] EF.COM might have been changed, there are "
            "differences between EF_COM DGs and EF_SOD DGs!"
        )
        window.write_event_value(
            "-PASSIVE AUTHENTICATION-",
            [False, "text_authentic_status", "ERROR", "red"],
        )
        pa_error = True

    window.write_event_value(
        "-FILE VERIFICATION-",
        [True, "text_read_file", "Reading and verifying document files...", "white"],
    )

    file_read_error = False
    security_infos = []
    if b"\x0e" in ef_sod_dg_list:
        window.write_event_value(
            "-FILE VERIFICATION-",
            [True, "text_read_file_status", "EF.DG14", "yellow"],
        )
        try:
            DG = read_data_from_ef(window, sm_object, b"\x01" + b"\x0e", "EF.DG14")
        except EFReadError as ex:
            print(ex)
            print("[-] Error while reading file EF.DG14.")
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return

        if not assert_dg_hash(DG, data_group_hash_values, hash_alg, b"\x0e"):
            pa_error = True
            window.write_event_value(
                "-PASSIVE AUTHENTICATION-",
                [False, "text_authentic_status", "ERROR", "red"],
            )
            window.write_event_value(
                "-FILE VERIFICATION-",
                [False, "text_read_file_status", "EF.DG14", "red"],
            )
            file_read_error = True
        else:
            window.write_event_value(
                "-FILE VERIFICATION-",
                [True, "text_read_file_status", "EF.DG14", "green"],
            )
        security_infos = parse_security_infos(DG)
        window.write_event_value(
            "-CHIP AUTHENTICATION-",
            [True, "text_copied_2", "Chip Authentication...", "white"],
        )
        try:
            chip_auth(security_infos, sm_object)
        except ChipAuthenticationError as ex:
            print(ex)
            window.write_event_value(
                "-CHIP AUTHENTICATION-",
                [False, "text_copied_2_status", "ERROR", "red"],
            )
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        else:
            window.write_event_value(
                "-CHIP AUTHENTICATION-",
                [True, "text_copied_2_status", "OK", "green"],
            )

    if b"\x0f" in ef_sod_dg_list:
        window.write_event_value(
            "-FILE VERIFICATION-",
            [True, "text_read_file_status", "EF.DG15", "yellow"],
        )
        try:
            DG = read_data_from_ef(window, sm_object, b"\x01" + b"\x0f", "EF.DG15")
        except EFReadError as ex:
            print(ex)
            print("[-] Error while reading file EF.DG15.")
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return

        if output_files:
            with open(os.path.join(folder_name, "EF.DG15.BIN"), "wb") as outfile:
                outfile.write(DG)
        if not assert_dg_hash(DG, data_group_hash_values, hash_alg, b"\x0f"):
            pa_error = True
            window.write_event_value(
                "-PASSIVE AUTHENTICATION-",
                [False, "text_authentic_status", "ERROR", "red"],
            )
            window.write_event_value(
                "-FILE VERIFICATION-",
                [False, "text_read_file_status", "EF.DG15", "red"],
            )
            file_read_error = True
        else:
            window.write_event_value(
                "-FILE VERIFICATION-",
                [True, "text_read_file_status", "EF.DG15", "green"],
            )
        window.write_event_value(
            "-ACTIVE AUTHENTICATION-",
            [True, "text_copied_1", "Active Authentication...", "white"],
        )
        try:
            active_auth(DG, sm_object, security_infos)
        except ActiveAuthenticationError as ex:
            print(ex)
            window.write_event_value(
                "-ACTIVE AUTHENTICATION-",
                [False, "text_copied_1_status", "ERROR", "red"],
            )
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        else:
            window.write_event_value(
                "-ACTIVE AUTHENTICATION-",
                [True, "text_copied_1_status", "OK", "green"],
            )
    for dg, dgname in ef_sod_dg_list.items():
        if dg == b"\x0f" or dg == b"\x0e":
            # Active Authentication and Chip Authentication assumed completed
            continue

        if dg == b"\x03" or dg == b"\x04":
            # Sensitive Data: Finger and iris image data stored in the LDS
            # Data Groups 3 and 4, respectively. These data are considered
            # to be more privacy sensitive than data stored in the other
            # Data Groups.
            continue

        window.write_event_value(
            "-FILE VERIFICATION-",
            [True, "text_read_file_status", dgname, "yellow"],
        )
        try:
            DG = read_data_from_ef(window, sm_object, b"\x01" + dg, dgname)
        except EFReadError as ex:
            print(ex)
            print(f"[-] Error while reading file {dgname}.")
            if dg in [b"\x01", b"\x02"]:
                window.write_event_value("-RAISED EXCEPTION-", "")
                return
            continue
        except CardCommunicationError:
            window.write_event_value("-RAISED EXCEPTION-", "")
            return
        except CardConnectionException as ex:
            print(ex)
            window.write_event_value("-RAISED EXCEPTION-", "")
            return

        if output_files:
            with open(os.path.join(folder_name, dgname + ".BIN"), "wb") as outfile:
                outfile.write(DG)

        dg1_okay = True
        if not assert_dg_hash(DG, data_group_hash_values, hash_alg, dg):
            if dg == b"\x01":
                dg1_okay = False
            pa_error = True
            window.write_event_value(
                "-PASSIVE AUTHENTICATION-",
                [False, "text_authentic_status", "ERROR", "red"],
            )
            window.write_event_value(
                "-FILE VERIFICATION-",
                [False, "text_read_file_status", dgname, "red"],
            )
            file_read_error = True
        else:
            window.write_event_value(
                "-FILE VERIFICATION-",
                [True, "text_read_file_status", dgname, "green"],
            )

        if dg == b"\x02":
            id_image = get_jpeg_im(DG)
            window.write_event_value("-SHOW ID IMAGE-", [jpeg_to_png(id_image)])

        if dg == b"\x01":
            window.write_event_value(
                "-DOCUMENT EXPIRY CHECK-",
                [True, "document_expired", "Checking expiration status...", "white"],
            )
            mrz_read = get_dg1_content(DG)
            if dg1_okay:
                mrz_expiration_date = b""
                if len(mrz_read) == 90:
                    mrz_expiration_date = mrz_read[38:44]
                elif len(mrz_read) == 72:
                    mrz_expiration_date = mrz_read[57:63]
                elif len(mrz_read) == 88:
                    mrz_expiration_date = mrz_read[65:71]
                else:
                    print("[-] Error in MRZ that was read from DG1")
                    window.write_event_value(
                        "-DOCUMENT EXPIRY CHECK-",
                        [False, "document_expired_status", "ERROR", "red"],
                    )
                if mrz_expiration_date != b"":
                    valid = check_expiration(mrz_expiration_date)
                    if valid:
                        window.write_event_value(
                            "-DOCUMENT EXPIRY CHECK-",
                            [True, "document_expired_status", "OK", "green"],
                        )
                    else:
                        window.write_event_value(
                            "-DOCUMENT EXPIRY CHECK-",
                            [False, "document_expired_status", "EXPIRED", "red"],
                        )
            else:
                # Assume the document expired
                window.write_event_value(
                    "-DOCUMENT EXPIRY CHECK-",
                    [False, "document_expired_status", "ERROR", "red"],
                )

            if args.mrz:
                window.write_event_value(
                    "-MRZ COMPARE-",
                    [
                        True,
                        "text_mrz_compare",
                        "Comparing Machine Readable Zone with the DG1 inside the card...",
                        "white",
                    ],
                )
                mrz_scanned = str.encode("".join(mrz))
                if mrz_read != mrz_scanned:
                    print(
                        "[-] MRZ in DG1 doesn't match the MRZ read from the card!"
                        f"\nMRZ SCANNED:\n{mrz_scanned!s}\n\nMRZ READ:\n{mrz_read!s}"
                    )
                    window.write_event_value(
                        "-MRZ COMPARE-",
                        [
                            False,
                            "text_mrz_compare_status",
                            "ERROR",
                            "red",
                        ],
                    )
                else:
                    window.write_event_value(
                        "-MRZ COMPARE-",
                        [
                            True,
                            "text_mrz_compare_status",
                            "OK",
                            "green",
                        ],
                    )

            if db is not None:
                # Search MRZ in the db
                window.write_event_value(
                    "-CHECK DATABASE-",
                    [True, "check_database", "Checking database...", "white"],
                )
                database_obj = Query()
                if db.search(database_obj.mrz == "".join(mrz)) == []:
                    window.write_event_value(
                        "-CHECK DATABASE-",
                        [False, "check_database_status", "NOT FOUND", "red"],
                    )
                else:
                    window.write_event_value(
                        "-CHECK DATABASE-",
                        [True, "check_database_status", "OK", "green"],
                    )
            issuing_country = mrz_read[2:5]
            if issuing_country == b"EST":
                check_validity(window, document_number)

    if file_read_error:
        window.write_event_value(
            "-FILE VERIFICATION-",
            [False, "text_read_file_status", "ERROR", "red"],
        )
    else:
        window.write_event_value(
            "-FILE VERIFICATION-",
            [True, "text_read_file_status", "ALL OK", "green"],
        )

    if pa_error:
        window.write_event_value(
            "-PASSIVE AUTHENTICATION-",
            [False, "text_authentic_status", "ERROR", "red"],
        )
    else:
        window.write_event_value(
            "-PASSIVE AUTHENTICATION-",
            [True, "text_authentic_status", "OK", "green"],
        )

    if args.biometric:
        from emrtd_face_access.camera import capture_image
        from emrtd_face_access.face_compare import compare_faces
        from emrtd_face_access.image_operations import show_result

        print("[?] Please take a picture.")
        camera_image, face_location = capture_image(window, q, q2, lock2, camera_id)
        with lock:
            window.write_event_value(
                "-COMPARE RESULT-",
                [True, "text_face_compare", "Performing face comparison...", "white"],
            )
            comparison_result = compare_faces(
                id_image, camera_image, face_location, None if not output_files else folder_name
            )

            show_result(window, comparison_result)

            # termios.tcflush(sys.stdin, termios.TCIOFLUSH)
            # input("[?] Please take your ID card out and press [Enter] to run again.")
    window.write_event_value(
        "-TAKE ID OUT-",
        [
            True,
            "text_instruction",
            "Please take your document out and press [Enter] to run again.",
            "white",
        ],
    )
    window.write_event_value("-RUN COMPLETE-", "")
    return
Beispiel #5
0
def estonia_read_mrz(sm_object: SMObject) -> Tuple[str, str, str, str, str]:
    """Read Estonian ID card information from personal data"""
    # reading personal data file (EstEID spec page 30)
    print(
        "[+] Selecting IAS ECC applet AID: A000000077010800070000FE00000100..."
    )
    ias_ecc_aid = bytes.fromhex("A000000077010800070000FE00000100")

    # exception caught in main program loop
    send(
        sm_object,
        APDU(b"\x00",
             b"\xA4",
             b"\x04",
             b"\x00",
             Lc=nb(len(ias_ecc_aid)),
             cdata=ias_ecc_aid),
    )
    print("[+] Selecting DF ID: 5000...")
    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x00"))
    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x07"))
    print("[+] Reading personal data files...")
    document_number = send(
        sm_object, APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                        Le=b"\x00")).decode("utf8")

    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x05"))
    date_of_birth = send(sm_object,
                         APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                              Le=b"\x00"))[:10].decode("utf8")
    date_of_birth = date_of_birth[-2:] + date_of_birth[3:5] + date_of_birth[:2]
    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x08"))
    date_of_expiry = send(sm_object,
                          APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                               Le=b"\x00")).decode("utf8")
    date_of_expiry = date_of_expiry[-2:] + date_of_expiry[
        3:5] + date_of_expiry[:2]
    # Construct the 'MRZ information'
    print("[+] Constructing the MRZ information...")
    mrz_information = (document_number +
                       calculate_check_digit(document_number) + date_of_birth +
                       calculate_check_digit(date_of_birth) + date_of_expiry +
                       calculate_check_digit(date_of_expiry))

    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x01"))
    surname = send(sm_object,
                   APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                        Le=b"\x00")).decode("utf8")
    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x02"))
    name = send(sm_object, APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                                Le=b"\x00")).decode("utf8")
    send(
        sm_object,
        APDU(b"\x00", b"\xA4", b"\x01", b"\x0C", Lc=b"\x02",
             cdata=b"\x50\x06"))
    personal_id_code = send(
        sm_object, APDU(b"\x00", b"\xB0", b"\x00", b"\x00",
                        Le=b"\x00")).decode("utf8")

    # Select LDS applet
    # A00000024710FF is applet id
    print("[+] Selecting LDS AID: A00000024710FF...")
    aid = bytes.fromhex("A00000024710FF")
    send(sm_object,
         APDU(b"\x00", b"\xA4", b"\x04", b"\x00", Lc=nb(len(aid)), cdata=aid))

    return mrz_information, document_number, personal_id_code, name, surname
Beispiel #6
0
def database_builder_loop(window: sg.Window):
    camera_id = -1
    mrz, _ = capture_mrz(window, camera_id)
    mrz_scan = "".join(mrz)
    print(f"[i] MRZ Read:\n{mrz_scan}")
    document_number, birthdate, expiry_date, _, _, _ = parse_mrz_text(mrz)
    mrz_information = other_mrz(document_number, birthdate, expiry_date)

    sm_object = SMObject(wait_for_card())

    atr = sm_object.channel.getATR()
    print("[+] Card ATR: " + toHexString(atr))

    # Select eMRTD Applet
    print("[+] Selecting LDS DF AID: A0000002471001...")
    aid = bytes.fromhex("A0000002471001")
    try:
        send(sm_object, APDU(b"\x00", b"\xA4", b"\x04", b"\x0C", Lc=nb(len(aid)), cdata=aid))
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    ## SECURE MESSAGING ##
    try:
        establish_bac_session_keys(sm_object, mrz_information.encode("utf-8"))
    except SessionKeyEstablishmentError as ex:
        print(ex)
        print("[-] Error while establishing BAC session keys")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return

    # Read EF.DG1
    try:
        dg1 = read_data_from_ef(window, sm_object, b"\x01\x01", "EF.DG1")
    except EFReadError as ex:
        print(ex)
        print("[-] Error while reading file EF.DG1.")
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardCommunicationError:
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    except CardConnectionException as ex:
        print(ex)
        window.write_event_value("-RAISED EXCEPTION-", "")
        return
    else:
        mrz_read = get_dg1_content(dg1).decode("utf-8")
        print(mrz_read)
        if mrz_read == mrz_scan:
            window.write_event_value("-SHOW WARNING-", mrz_read)
        else:
            window.write_event_value("-PROBLEM IN EITHER READ OR DOCUMENT-", "")