Example #1
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
        })
Example #2
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')
Example #3
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}')
Example #4
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()