예제 #1
0
def _read_info_otp(conn, key_type, interfaces):
    otp = None
    serial = None

    try:
        mgmt = ManagementSession(conn)
    except ApplicationNotAvailableError:
        otp = YubiOtpSession(conn)

    # Retry during potential reclaim timeout period (~3s).
    for _ in range(8):
        try:
            if otp is None:
                try:
                    return mgmt.read_device_info()  # Rejected while reclaim
                except NotSupportedError:
                    otp = YubiOtpSession(conn)
            serial = otp.get_serial(
            )  # Rejected if reclaim (or not API_SERIAL_VISIBLE)
            break
        except CommandRejectedError:
            sleep(0.5)  # Potential reclaim
    else:
        otp = YubiOtpSession(conn)

    # Synthesize info
    logger.debug("Unable to get info via Management application, use fallback")

    version = otp.version
    if key_type == YUBIKEY.NEO:
        usb_supported = BASE_NEO_APPS
        if USB_INTERFACE.FIDO in interfaces or version >= (3, 3, 0):
            usb_supported |= CAPABILITY.U2F
        capabilities = {
            TRANSPORT.USB: usb_supported,
            TRANSPORT.NFC: usb_supported,
        }
    elif key_type == YUBIKEY.YKP:
        capabilities = {
            TRANSPORT.USB: CAPABILITY.OTP | TRANSPORT.U2F,
        }
    else:
        capabilities = {
            TRANSPORT.USB: CAPABILITY.OTP,
        }

    return DeviceInfo(
        config=DeviceConfig(
            enabled_capabilities={},  # Populated later
            auto_eject_timeout=0,
            challenge_response_timeout=0,
            device_flags=0,
        ),
        serial=serial,
        version=version,
        form_factor=FORM_FACTOR.UNKNOWN,
        supported_capabilities=capabilities.copy(),
        is_locked=False,
    )
예제 #2
0
def _otp_read_data(conn):
    otp = YubiOtpSession(conn)
    version = otp.version
    try:
        serial = otp.get_serial()
    except Exception as e:
        logger.debug("Unable to read serial over OTP, no serial", exc_info=e)
        serial = None
    return version, serial
예제 #3
0
def get_overall_fips_status(pid, info):
    statuses = {}

    usb_enabled = info.config.enabled_applications[TRANSPORT.USB]

    statuses["OTP"] = False
    if usb_enabled & APPLICATION.OTP:
        for dev in list_otp_devices():
            if dev.pid == pid:
                with dev.open_connection(OtpConnection) as conn:
                    app = YubiOtpSession(conn)
                    if app.get_serial() == info.serial:
                        statuses["OTP"] = otp_in_fips_mode(app)
                        break

    statuses["OATH"] = False
    if usb_enabled & APPLICATION.OATH:
        for dev in list_ccid():
            with dev.open_connection(SmartCardConnection) as conn:
                info2 = read_info(pid, conn)
                if info2.serial == info.serial:
                    app = OathSession(conn)
                    statuses["OATH"] = oath_in_fips_mode(app)
                    break

    statuses["FIDO U2F"] = False
    if usb_enabled & APPLICATION.U2F:
        for dev in list_ctap_devices():
            if dev.pid == pid:
                with dev.open_connection(FidoConnection) as conn:
                    info2 = read_info(pid, conn)
                    if info2.serial == info.serial:
                        statuses["FIDO U2F"] = ctap_in_fips_mode(conn)
                        break

    return statuses
예제 #4
0
 def serial_modhex(self):
     with self._open_device([OtpConnection]) as conn:
         session = YubiOtpSession(conn)
         return modhex_encode(b'\xff\x00' + struct.pack(b'>I', session.get_serial()))