Esempio n. 1
0
    def piv_change_pin(self, old_pin, new_pin):
        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)
            try:
                session.change_pin(old_pin, new_pin)
                logger.debug('PIN change successful!')
                return success()
            except InvalidPinError as e:
                attempts = e.attempts_remaining
                if attempts:
                    logger.debug("Failed to change PIN, %d tries left", attempts, exc_info=e)
                    return failure('wrong_pin', {'tries_left': attempts})
                else:
                    logger.debug("PIN is blocked.", exc_info=e)
                    return failure('pin_blocked')
            except ApduError as e:
                if e.sw == SW.INCORRECT_PARAMETERS:
                    return failure('incorrect_parameters')

                tries_left = e.attempts_remaining
                logger.debug('PIN change failed. %s tries left.',
                             tries_left, exc_info=e)
                return {
                    'success': False,
                    'tries_left': tries_left,
                }
Esempio n. 2
0
    def refresh_piv(self):
        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)
            pivman = get_pivman_data(session)

            try:
                key_type = session.get_management_key_metadata().key_type
            except NotSupportedError:
                key_type = MANAGEMENT_KEY_TYPE.TDES

            return success({
                'piv_data': {
                    'certs':
                    self._piv_list_certificates(session),
                    'has_derived_key':
                    pivman.has_derived_key,
                    'has_protected_key':
                    pivman.has_protected_key,
                    'has_stored_key':
                    pivman.has_stored_key,
                    'pin_tries':
                    session.get_pin_attempts(),
                    'puk_blocked':
                    pivman.puk_blocked,
                    'supported_algorithms':
                    _supported_algorithms(
                        self._dev_info['version'].split('.')),
                    'key_type':
                    key_type,
                },
            })
Esempio n. 3
0
 def sign(self, message):
     if 'mplock' in globals():
         mplock.acquire()
     try:
         conn = self._connect()
         with conn:
             session = PivSession(conn)
             if self.pin:
                 try:
                     session.verify_pin(self.pin)
                 except InvalidPinError as err:
                     controlflow.system_error_exit(7, f'YubiKey - {err}')
             try:
                 signed = session.sign(slot=self.slot,
                                       key_type=self.key_type,
                                       message=message,
                                       hash_algorithm=hashes.SHA256(),
                                       padding=padding.PKCS1v15())
             except ApduError as err:
                 controlflow.system_error_exit(8, f'YubiKey - {err}')
     except ValueError as err:
         controlflow.system_error_exit(9, f'YubiKey - {err}')
     if 'mplock' in globals():
         mplock.release()
     return signed
Esempio n. 4
0
 def piv_export_certificate(self, slot, file_url):
     file_path = self._get_file_path(file_url)
     with self._open_device([SmartCardConnection]) as conn:
         session = PivSession(conn)
         cert = session.get_certificate(SLOT[slot])
         with open(file_path, 'wb') as file:
             file.write(
                 cert.public_bytes(encoding=serialization.Encoding.PEM))
     return success()
Esempio n. 5
0
 def piv_unblock_pin(self, puk, new_pin):
     with self._open_device([SmartCardConnection]) as conn:
         session = PivSession(conn)
         try:
             session.unblock_pin(puk, new_pin)
             return success()
         except InvalidPinError as e:
             attempts = e.attempts_remaining
             if attempts:
                 logger.debug("Failed to unblock PIN, %d tries left", attempts, exc_info=e)
                 return failure('wrong_puk', {'tries_left': attempts})
             else:
                 logger.debug("PUK is blocked.", exc_info=e)
                 return failure('puk_blocked')
Esempio n. 6
0
def piv(ctx):
    """
    Manage PIV Application.

    Examples:

    \b
      Generate an ECC P-256 private key and a self-signed certificate in
      slot 9a:
      $ ykman piv generate-key --algorithm ECCP256 9a pubkey.pem
      $ ykman piv generate-certificate --subject "yubico" 9a pubkey.pem

    \b
      Change the PIN from 123456 to 654321:
      $ ykman piv change-pin --pin 123456 --new-pin 654321

    \b
      Reset all PIV data and restore default settings:
      $ ykman piv reset
    """
    try:
        app = PivSession(ctx.obj["conn"])
        ctx.obj["controller"] = PivController(app)
    except ApduError as e:
        if e.sw == SW.FILE_NOT_FOUND:
            ctx.fail("The PIV application can't be found on this YubiKey.")
        raise
Esempio n. 7
0
def pivman_change_pin(session: PivSession, old_pin: str, new_pin: str) -> None:
    """Change the PIN, while keeping PivmanData in sync."""
    session.change_pin(old_pin, new_pin)

    pivman = get_pivman_data(session)
    if pivman.has_derived_key:
        session.authenticate(
            MANAGEMENT_KEY_TYPE.TDES,
            derive_management_key(old_pin, cast(bytes, pivman.salt)),
        )
        session.verify_pin(new_pin)
        new_salt = os.urandom(16)
        new_key = derive_management_key(new_pin, new_salt)
        session.set_management_key(MANAGEMENT_KEY_TYPE.TDES, new_key)
        pivman.salt = new_salt
        session.put_object(OBJECT_ID_PIVMAN_DATA, pivman.get_bytes())
Esempio n. 8
0
def sign_csr_builder(
    session: PivSession,
    slot: SLOT,
    public_key: Union[rsa.RSAPublicKey, ec.EllipticCurvePublicKey],
    builder: x509.CertificateSigningRequestBuilder,
    hash_algorithm: Type[hashes.HashAlgorithm] = hashes.SHA256,
) -> x509.CertificateSigningRequest:
    """Sign a CSR."""
    key_type = KEY_TYPE.from_public_key(public_key)
    dummy_key = _dummy_key(key_type)
    csr = builder.sign(dummy_key, hash_algorithm(), default_backend())
    seq = Tlv.parse_list(Tlv.unpack(0x30, csr.public_bytes(Encoding.DER)))

    # Replace public key
    pub_format = (PublicFormat.PKCS1 if key_type.algorithm == ALGORITHM.RSA
                  else PublicFormat.SubjectPublicKeyInfo)
    dummy_bytes = dummy_key.public_key().public_bytes(Encoding.DER, pub_format)
    pub_bytes = public_key.public_bytes(Encoding.DER, pub_format)
    seq[0] = Tlv(seq[0].replace(dummy_bytes, pub_bytes))

    sig = session.sign(
        slot,
        key_type,
        seq[0],
        hash_algorithm(),
        padding.PKCS1v15(),  # Only used for RSA
    )

    # Replace signature, add unused bits = 0
    seq[2] = Tlv(seq[2].tag, b"\0" + sig)
    # Re-assemble sequence
    der = Tlv(0x30, b"".join(seq))

    return x509.load_der_x509_csr(der, default_backend())
Esempio n. 9
0
    def piv_change_mgm_key(self, pin, current_key_hex, new_key_hex, key_type,
                           store_on_device=False):
        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)

            pivman = get_pivman_data(session)

            if pivman.has_protected_key or store_on_device:
                pin_failed = self._piv_verify_pin(
                    session, pin=pin)
                if pin_failed:
                    return pin_failed
            with PromptTimeout():

                auth_failed = self._piv_ensure_authenticated(
                    session, pin=pin, mgm_key_hex=current_key_hex)
            if auth_failed:
                return auth_failed

            try:

                new_key = a2b_hex(new_key_hex) if new_key_hex else None
            except Exception as e:
                logger.debug('Failed to parse new management key', exc_info=e)
                return failure('new_mgm_key_bad_hex')

            if new_key is not None and len(new_key) != MANAGEMENT_KEY_TYPE(key_type).key_len:
                logger.debug('Wrong length for new management key: %d',
                             len(new_key))
                return failure('new_mgm_key_bad_length')

            pivman_set_mgm_key(
                        session, new_key, MANAGEMENT_KEY_TYPE(key_type), touch=False, store_on_device=store_on_device
                    )
            return success()
Esempio n. 10
0
def sign_certificate_builder(
    session: PivSession,
    slot: SLOT,
    key_type: KEY_TYPE,
    builder: x509.CertificateBuilder,
    hash_algorithm: Type[hashes.HashAlgorithm] = hashes.SHA256,
) -> x509.Certificate:
    """Sign a Certificate."""
    dummy_key = _dummy_key(key_type)
    cert = builder.sign(dummy_key, hash_algorithm(), default_backend())

    sig = session.sign(
        slot,
        key_type,
        cert.tbs_certificate_bytes,
        hash_algorithm(),
        padding.PKCS1v15(),  # Only used for RSA
    )

    seq = Tlv.parse_list(Tlv.unpack(0x30, cert.public_bytes(Encoding.DER)))
    # Replace signature, add unused bits = 0
    seq[2] = Tlv(seq[2].tag, b"\0" + sig)
    # Re-assemble sequence
    der = Tlv(0x30, b"".join(seq))

    return x509.load_der_x509_certificate(der, default_backend())
Esempio n. 11
0
def piv_info(conn):
    try:
        piv = PivSession(conn)
        return ["\tPIV"] + [
            f"\t\t{ln}" for ln in get_piv_info(piv).splitlines() if ln
        ]
    except Exception as e:
        return [f"\tPIV not accessible {e}"]
Esempio n. 12
0
def get_pivman_data(session: PivSession) -> PivmanData:
    """Reads out the Pivman data from a YubiKey."""
    try:
        return PivmanData(session.get_object(OBJECT_ID_PIVMAN_DATA))
    except ApduError as e:
        if e.sw == SW.FILE_NOT_FOUND:
            # No data there, initialise a new object.
            return PivmanData()
        raise
Esempio n. 13
0
def get_pivman_protected_data(session: PivSession) -> PivmanProtectedData:
    """Reads out the Pivman protected data from a YubiKey.

    This function requires PIN verification prior to being called.
    """
    try:
        return PivmanProtectedData(session.get_object(OBJECT_ID_PIVMAN_PROTECTED_DATA))
    except ApduError as e:
        if e.sw == SW.FILE_NOT_FOUND:
            # No data there, initialise a new object.
            return PivmanProtectedData()
        raise
Esempio n. 14
0
 def get_certificate(self):
     try:
         conn = self._connect()
         with conn:
             session = PivSession(conn)
             if self.pin:
                 try:
                     session.verify_pin(self.pin)
                 except InvalidPinError as err:
                     controlflow.system_error_exit(7, f'YubiKey - {err}')
             try:
                 cert = session.get_certificate(self.slot)
             except ApduError as err:
                 controlflow.system_error_exit(9, f'YubiKey - {err}')
         cert_pem = cert.public_bytes(serialization.Encoding.PEM).decode()
         publicKeyData = b64encode(cert_pem.encode())
         if isinstance(publicKeyData, bytes):
             publicKeyData = publicKeyData.decode()
         return publicKeyData
     except ValueError as err:
         controlflow.system_error_exit(9, f'YubiKey - {err}')
Esempio n. 15
0
    def piv_import_file(self,
                        slot,
                        file_url,
                        password=None,
                        pin=None,
                        mgm_key=None):
        is_cert = False
        is_private_key = False
        file_path = self._get_file_path(file_url)
        if password:
            password = password.encode()
        with open(file_path, 'r+b') as file:
            data = file.read()
            try:
                certs = parse_certificates(data, password)
                is_cert = True
            except (ValueError, TypeError):
                pass
            try:
                private_key = parse_private_key(data, password)
                is_private_key = True
            except (ValueError, TypeError, InvalidPasswordError):
                pass

            if not (is_cert or is_private_key):
                return failure('failed_parsing')

            with self._open_device([SmartCardConnection]) as conn:
                session = PivSession(conn)
                with PromptTimeout():
                    auth_failed = self._piv_ensure_authenticated(
                        session, pin, mgm_key)
                    if auth_failed:
                        return auth_failed
                    if is_private_key:
                        session.put_key(SLOT[slot], private_key)
                    if is_cert:
                        if len(certs) > 1:
                            leafs = get_leaf_certificates(certs)
                            cert_to_import = leafs[0]
                        else:
                            cert_to_import = certs[0]

                        session.put_certificate(SLOT[slot], cert_to_import)
                        session.put_object(OBJECT_ID.CHUID, generate_chuid())
        return success({
            'imported_cert': is_cert,
            'imported_key': is_private_key
        })
Esempio n. 16
0
def pivman_set_mgm_key(
    session: PivSession,
    new_key: bytes,
    algorithm: MANAGEMENT_KEY_TYPE,
    touch: bool = False,
    store_on_device: bool = False,
) -> None:
    """Set a new management key, while keeping PivmanData in sync."""
    pivman = get_pivman_data(session)

    if store_on_device or (not store_on_device and pivman.has_stored_key):
        # Ensure we have access to protected data before overwriting key
        try:
            pivman_prot = get_pivman_protected_data(session)
        except Exception as e:
            logger.debug("Failed to initialize protected pivman data",
                         exc_info=e)
            if store_on_device:
                raise

    # Set the new management key
    session.set_management_key(algorithm, new_key, touch)

    if pivman.has_derived_key:
        # Clear salt for old derived keys.
        pivman.salt = None
    # Set flag for stored or not stored key.
    pivman.mgm_key_protected = store_on_device

    # Update readable pivman data
    session.put_object(OBJECT_ID_PIVMAN_DATA, pivman.get_bytes())
    if store_on_device:
        # Store key in protected pivman data
        pivman_prot.key = new_key
        session.put_object(OBJECT_ID_PIVMAN_PROTECTED_DATA,
                           pivman_prot.get_bytes())
    elif not store_on_device and pivman.has_stored_key:
        # If new key should not be stored and there is an old stored key,
        # try to clear it.
        try:
            pivman_prot.key = None
            session.put_object(
                OBJECT_ID_PIVMAN_PROTECTED_DATA,
                pivman_prot.get_bytes(),
            )
        except ApduError as e:
            logger.debug("No PIN provided, can't clear key...", exc_info=e)
Esempio n. 17
0
def list_certificates(session: PivSession) -> Mapping[SLOT, Optional[x509.Certificate]]:
    """Reads out and parses stored certificates.

    Only certificates which are successfully parsed are returned.
    """
    certs = OrderedDict()
    for slot in set(SLOT) - {SLOT.ATTESTATION}:
        try:
            certs[slot] = session.get_certificate(slot)
        except ApduError:
            pass
        except BadResponseError:
            certs[slot] = None  # type: ignore

    return certs
Esempio n. 18
0
def check_key(
    session: PivSession,
    slot: SLOT,
    public_key: Union[rsa.RSAPublicKey, ec.EllipticCurvePublicKey],
) -> bool:
    """Check that a given public key corresponds to the private key in a slot.

    This will create a signature using the private key, so the PIN must be verified
    prior to calling this function if the PIN policy requires it.
    """
    try:
        test_data = b"test"

        test_sig = session.sign(
            slot,
            KEY_TYPE.from_public_key(public_key),
            test_data,
            hashes.SHA256(),
            padding.PKCS1v15(),  # Only used for RSA
        )

        if isinstance(public_key, rsa.RSAPublicKey):
            public_key.verify(
                test_sig,
                test_data,
                padding.PKCS1v15(),
                hashes.SHA256(),
            )
        elif isinstance(public_key, ec.EllipticCurvePublicKey):
            public_key.verify(test_sig, test_data, ec.ECDSA(hashes.SHA256()))
        else:
            raise ValueError("Unknown key type: " + type(public_key))
        return True

    except ApduError as e:
        if e.sw in (SW.INCORRECT_PARAMETERS, SW.WRONG_PARAMETERS_P1P2):
            return False
        raise

    except InvalidSignature:
        return False
Esempio n. 19
0
def piv(ctx):
    """
    Manage the PIV application.

    Examples:

    \b
      Generate an ECC P-256 private key and a self-signed certificate in
      slot 9a:
      $ ykman piv keys generate --algorithm ECCP256 9a pubkey.pem
      $ ykman piv certificates generate --subject "yubico" 9a pubkey.pem

    \b
      Change the PIN from 123456 to 654321:
      $ ykman piv access change-pin --pin 123456 --new-pin 654321

    \b
      Reset all PIV data and restore default settings:
      $ ykman piv reset
    """
    session = PivSession(ctx.obj["conn"])
    ctx.obj["session"] = session
    ctx.obj["pivman_data"] = get_pivman_data(session)
Esempio n. 20
0
    def piv_delete_certificate(self, slot_name, pin=None, mgm_key_hex=None):
        logger.debug('piv_delete_certificate %s', slot_name)

        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)
            with PromptTimeout():
                auth_failed = self._piv_ensure_authenticated(
                    session, pin=pin, mgm_key_hex=mgm_key_hex)
                if auth_failed:
                    return auth_failed
                try:
                    session.delete_certificate(SLOT[slot_name])
                    session.put_object(OBJECT_ID.CHUID, generate_chuid())
                    return success()
                except ApduError as e:
                    if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
                        logger.debug("Wrong management key", exc_info=e)
                        return failure('wrong_mgm_key')
Esempio n. 21
0
    def reset_piv(self):
        '''Resets YubiKey PIV app and generates new key for GAM to use.'''
        reply = str(
            input(
                'This will wipe all PIV keys and configuration from your YubiKey. Are you sure? (y/N) '
            ).lower().strip())
        if reply != 'y':
            sys.exit(1)
        try:
            conn = self._connect()
            with conn:
                piv = PivSession(conn)
                piv.reset()
                rnd = SystemRandom()
                pin_puk_chars = string.ascii_letters + string.digits + string.punctuation
                new_puk = ''.join(rnd.choice(pin_puk_chars) for _ in range(8))
                new_pin = ''.join(rnd.choice(pin_puk_chars) for _ in range(8))
                piv.change_puk('12345678', new_puk)
                piv.change_pin('123456', new_pin)
                print(f'PIN set to:  {new_pin}')
                piv.authenticate(MANAGEMENT_KEY_TYPE.TDES,
                                 DEFAULT_MANAGEMENT_KEY)

                piv.verify_pin(new_pin)
                print('YubiKey is generating a non-exportable private key...')
                pubkey = piv.generate_key(SLOT.AUTHENTICATION,
                                          KEY_TYPE.RSA2048, PIN_POLICY.ALWAYS,
                                          TOUCH_POLICY.NEVER)
                now = datetime.datetime.utcnow()
                valid_to = now + datetime.timedelta(days=36500)
                subject = 'CN=GAM Created Key'
                piv.authenticate(MANAGEMENT_KEY_TYPE.TDES,
                                 DEFAULT_MANAGEMENT_KEY)
                piv.verify_pin(new_pin)
                cert = generate_self_signed_certificate(
                    piv, SLOT.AUTHENTICATION, pubkey, subject, now, valid_to)
                piv.put_certificate(SLOT.AUTHENTICATION, cert)
                piv.put_object(OBJECT_ID.CHUID, generate_chuid())
        except ValueError as err:
            controlflow.system_error_exit(8, f'YubiKey - {err}')
Esempio n. 22
0
def get_piv_info(session: PivSession) -> str:
    """Get human readable information about the PIV configuration."""
    pivman = get_pivman_data(session)
    lines = []

    lines.append("PIV version: %d.%d.%d" % session.version)

    try:
        pin_data = session.get_pin_metadata()
        if pin_data.default_value:
            lines.append("WARNING: Using default PIN!")
        tries_str = "%d/%d" % (pin_data.attempts_remaining,
                               pin_data.total_attempts)
    except NotSupportedError:
        # Largest possible number of PIN tries to get back is 15
        tries = session.get_pin_attempts()
        tries_str = "15 or more." if tries == 15 else str(tries)
    lines.append(f"PIN tries remaining: {tries_str}")
    if pivman.puk_blocked:
        lines.append("PUK blocked.")

    try:
        metadata = session.get_management_key_metadata()
        if metadata.default_value:
            lines.append("WARNING: Using default Management key!")
        key_type = metadata.key_type
    except NotSupportedError:
        key_type = MANAGEMENT_KEY_TYPE.TDES
    lines.append(f"Management key algorithm: {key_type.name}")

    if pivman.has_derived_key:
        lines.append("Management key is derived from PIN.")
    if pivman.has_stored_key:
        lines.append(
            "Management key is stored on the YubiKey, protected by PIN.")

    try:
        chuid = session.get_object(OBJECT_ID.CHUID).hex()
    except ApduError as e:
        if e.sw == SW.FILE_NOT_FOUND:
            chuid = "No data available."
    lines.append("CHUID:\t" + chuid)

    try:
        ccc = session.get_object(OBJECT_ID.CAPABILITY).hex()
    except ApduError as e:
        if e.sw == SW.FILE_NOT_FOUND:
            ccc = "No data available."
    lines.append("CCC: \t" + ccc)

    for (slot, cert) in list_certificates(session).items():
        lines.append(f"Slot {slot:02x}:")

        if isinstance(cert, x509.Certificate):
            try:
                # Try to read out full DN, fallback to only CN.
                # Support for DN was added in crytography 2.5
                subject_dn = cert.subject.rfc4514_string()
                issuer_dn = cert.issuer.rfc4514_string()
                print_dn = True
            except AttributeError:
                print_dn = False
                logger.debug("Failed to read DN, falling back to only CNs")
                cn = cert.subject.get_attributes_for_oid(
                    x509.NameOID.COMMON_NAME)
                subject_cn = cn[0].value if cn else "None"
                cn = cert.issuer.get_attributes_for_oid(
                    x509.NameOID.COMMON_NAME)
                issuer_cn = cn[0].value if cn else "None"
            except ValueError as e:
                # Malformed certificates may throw ValueError
                logger.debug("Failed parsing certificate", exc_info=e)
                lines.append(f"\tMalformed certificate: {e}")
                continue

            fingerprint = cert.fingerprint(hashes.SHA256()).hex()
            try:
                key_algo = KEY_TYPE.from_public_key(cert.public_key()).name
            except ValueError:
                key_algo = "Unsupported"
            serial = cert.serial_number
            try:
                not_before: Optional[datetime] = cert.not_valid_before
            except ValueError as e:
                logger.debug("Failed reading not_valid_before", exc_info=e)
                not_before = None
            try:
                not_after: Optional[datetime] = cert.not_valid_after
            except ValueError as e:
                logger.debug("Failed reading not_valid_after", exc_info=e)
                not_after = None
            # Print out everything
            lines.append(f"\tAlgorithm:\t{key_algo}")
            if print_dn:
                lines.append(f"\tSubject DN:\t{subject_dn}")
                lines.append(f"\tIssuer DN:\t{issuer_dn}")
            else:
                lines.append(f"\tSubject CN:\t{subject_cn}")
                lines.append(f"\tIssuer CN:\t{issuer_cn}")
            lines.append(f"\tSerial:\t\t{serial}")
            lines.append(f"\tFingerprint:\t{fingerprint}")
            if not_before:
                lines.append(f"\tNot before:\t{not_before}")
            if not_after:
                lines.append(f"\tNot after:\t{not_after}")
        else:
            lines.append("\tError: Failed to parse certificate.")

    return "\n".join(lines)
Esempio n. 23
0
 def setUpClass(cls):
     with open_device()[0] as conn:
         controller = PivController(PivSession(conn))
         controller.reset()
Esempio n. 24
0
 def reconnect(self):
     self.conn.close()
     self.conn = open_device()[0]
     self.controller = PivController(PivSession(self.conn))
Esempio n. 25
0
def session(ccid_connection):
    piv = PivSession(ccid_connection)
    piv.reset()
    yield piv
    reset_state(piv)
Esempio n. 26
0
    def piv_generate_certificate(
            self, slot_name, algorithm, subject, expiration_date,
            self_sign=True, csr_file_url=None, pin=None, mgm_key_hex=None):
        logger.debug('slot_name=%s algorithm=%s common_name=%s '
                     'expiration_date=%s self_sign=%s csr_file_url=%s',
                     slot_name, algorithm, subject, expiration_date,
                     self_sign, csr_file_url)
        if csr_file_url:
            file_path = self._get_file_path(csr_file_url)

        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)
            with PromptTimeout():
                auth_failed = self._piv_ensure_authenticated(
                    session, pin=pin, mgm_key_hex=mgm_key_hex)
            if auth_failed:
                return auth_failed

            pin_failed = self._piv_verify_pin(session, pin)
            if pin_failed:
                return pin_failed

            if self_sign:
                now = datetime.datetime.utcnow()
                try:
                    year = int(expiration_date[0:4])
                    month = int(expiration_date[(4+1):(4+1+2)])
                    day = int(expiration_date[(4+1+2+1):(4+1+2+1+2)])
                    valid_to = datetime.datetime(year, month, day)
                except ValueError as e:
                    logger.debug(
                        'Failed to parse date: ' + expiration_date,
                        exc_info=e)
                    return failure(
                        'invalid_iso8601_date',
                        {'date': expiration_date})
            try:
                public_key = session.generate_key(
                    SLOT[slot_name], KEY_TYPE[algorithm])
            except ApduError as e:
                if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
                    logger.debug("Wrong management key", exc_info=e)
                    return failure('wrong_mgm_key')

            pin_failed = self._piv_verify_pin(session, pin)
            if pin_failed:
                return pin_failed

            if "=" not in subject:
                # Old style, common name only.
                subject = "CN=" + subject

            try:
                if self_sign:
                    cert = generate_self_signed_certificate(session,
                        SLOT[slot_name], public_key, subject, now,
                        valid_to)
                    session.put_certificate(SLOT[slot_name], cert)
                    session.put_object(OBJECT_ID.CHUID, generate_chuid())

                else:
                    csr = generate_csr(session,
                        SLOT[slot_name], public_key, subject)

                    with open(file_path, 'w+b') as csr_file:
                        csr_file.write(csr.public_bytes(
                            encoding=serialization.Encoding.PEM))

            except ApduError as e:
                if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
                    return failure('pin_required')
                raise

            return success()
Esempio n. 27
0
 def setUp(self):
     self.conn = open_device()[0]
     self.controller = PivController(PivSession(self.conn))
Esempio n. 28
0
 def piv_reset(self):
     with self._open_device([SmartCardConnection]) as conn:
         session = PivSession(conn)
         session.reset()
         return success()