--- /dev/null
+This library aims to support the FIDO U2F and FIDO 2.0 protocols for
+communicating with a USB authenticator via the Client-to-Authenticator
+Protocol (CTAP 1 and 2). In addition to this low-level device access,
+classes defined in the fido2.client and fido2.server modules implement
+higher level operations which are useful when interfacing with an
+Authenticator, or when implementing WebAuthn support for a Relying
+Party.
--- /dev/null
+# $NetBSD: Makefile,v 1.4 2022/04/21 11:00:01 wiz Exp $
+
+DISTNAME= fido2-1.1.0
+PKGNAME= ${PYPKGPREFIX}-${DISTNAME}
+CATEGORIES= security
+MASTER_SITES= ${MASTER_SITE_GITHUB:=Yubico/}
+GITHUB_PROJECT= python-fido2
+GITHUB_TAG= ${PKGVERSION_NOREV}
+
+MAINTAINER= pkgsrc-users@NetBSD.org
+HOMEPAGE= https://developers.yubico.com/python-fido2/
+COMMENT= Yubico FIDO U2F and FIDO 2.0 USB Python library
+LICENSE= 2-clause-bsd AND apache-2.0 AND mpl-2.0
+
+DEPENDS+= ${PYPKGPREFIX}-scard>=0:../../devel/py-scard
+DEPENDS+= ${PYPKGPREFIX}-cryptography>=0:../../security/py-cryptography
+TEST_DEPENDS+= ${PYPKGPREFIX}-test>=2:../../devel/py-test
+TOOL_DEPENDS+= ${PYPKGPREFIX}-poetry-core>=1:../../devel/py-poetry-core
+
+PYTHON_VERSIONS_INCOMPATIBLE= 27
+
+post-install:
+ ${RM} -f ${DESTDIR}${PREFIX}/${PYSITELIB}/fido2/hid/*.orig
+
+do-test:
+ cd ${WRKSRC} && ${SETENV} ${TEST_ENV} pytest-${PYVERSSUFFIX}
+
+.include "../../lang/python/wheel.mk"
+.include "../../mk/bsd.pkg.mk"
--- /dev/null
+@comment $NetBSD$
+${PYSITELIB}/${WHEEL_INFODIR}/COPYING
+${PYSITELIB}/${WHEEL_INFODIR}/COPYING.APLv2
+${PYSITELIB}/${WHEEL_INFODIR}/COPYING.MPLv2
+${PYSITELIB}/${WHEEL_INFODIR}/INSTALLER
+${PYSITELIB}/${WHEEL_INFODIR}/METADATA
+${PYSITELIB}/${WHEEL_INFODIR}/RECORD
+${PYSITELIB}/${WHEEL_INFODIR}/REQUESTED
+${PYSITELIB}/${WHEEL_INFODIR}/WHEEL
+${PYSITELIB}/${WHEEL_INFODIR}/direct_url.json
+${PYSITELIB}/fido2/__init__.py
+${PYSITELIB}/fido2/__init__.pyc
+${PYSITELIB}/fido2/attestation/__init__.py
+${PYSITELIB}/fido2/attestation/__init__.pyc
+${PYSITELIB}/fido2/attestation/android.py
+${PYSITELIB}/fido2/attestation/android.pyc
+${PYSITELIB}/fido2/attestation/apple.py
+${PYSITELIB}/fido2/attestation/apple.pyc
+${PYSITELIB}/fido2/attestation/base.py
+${PYSITELIB}/fido2/attestation/base.pyc
+${PYSITELIB}/fido2/attestation/packed.py
+${PYSITELIB}/fido2/attestation/packed.pyc
+${PYSITELIB}/fido2/attestation/tpm.py
+${PYSITELIB}/fido2/attestation/tpm.pyc
+${PYSITELIB}/fido2/attestation/u2f.py
+${PYSITELIB}/fido2/attestation/u2f.pyc
+${PYSITELIB}/fido2/cbor.py
+${PYSITELIB}/fido2/cbor.pyc
+${PYSITELIB}/fido2/client.py
+${PYSITELIB}/fido2/client.pyc
+${PYSITELIB}/fido2/cose.py
+${PYSITELIB}/fido2/cose.pyc
+${PYSITELIB}/fido2/ctap.py
+${PYSITELIB}/fido2/ctap.pyc
+${PYSITELIB}/fido2/ctap1.py
+${PYSITELIB}/fido2/ctap1.pyc
+${PYSITELIB}/fido2/ctap2/__init__.py
+${PYSITELIB}/fido2/ctap2/__init__.pyc
+${PYSITELIB}/fido2/ctap2/base.py
+${PYSITELIB}/fido2/ctap2/base.pyc
+${PYSITELIB}/fido2/ctap2/bio.py
+${PYSITELIB}/fido2/ctap2/bio.pyc
+${PYSITELIB}/fido2/ctap2/blob.py
+${PYSITELIB}/fido2/ctap2/blob.pyc
+${PYSITELIB}/fido2/ctap2/config.py
+${PYSITELIB}/fido2/ctap2/config.pyc
+${PYSITELIB}/fido2/ctap2/credman.py
+${PYSITELIB}/fido2/ctap2/credman.pyc
+${PYSITELIB}/fido2/ctap2/extensions.py
+${PYSITELIB}/fido2/ctap2/extensions.pyc
+${PYSITELIB}/fido2/ctap2/pin.py
+${PYSITELIB}/fido2/ctap2/pin.pyc
+${PYSITELIB}/fido2/features.py
+${PYSITELIB}/fido2/features.pyc
+${PYSITELIB}/fido2/hid/__init__.py
+${PYSITELIB}/fido2/hid/__init__.pyc
+${PYSITELIB}/fido2/hid/base.py
+${PYSITELIB}/fido2/hid/base.pyc
+${PYSITELIB}/fido2/hid/freebsd.py
+${PYSITELIB}/fido2/hid/freebsd.pyc
+${PYSITELIB}/fido2/hid/linux.py
+${PYSITELIB}/fido2/hid/linux.pyc
+${PYSITELIB}/fido2/hid/macos.py
+${PYSITELIB}/fido2/hid/macos.pyc
+${PYSITELIB}/fido2/hid/netbsd.py
+${PYSITELIB}/fido2/hid/netbsd.pyc
+${PYSITELIB}/fido2/hid/openbsd.py
+${PYSITELIB}/fido2/hid/openbsd.pyc
+${PYSITELIB}/fido2/hid/windows.py
+${PYSITELIB}/fido2/hid/windows.pyc
+${PYSITELIB}/fido2/mds3.py
+${PYSITELIB}/fido2/mds3.pyc
+${PYSITELIB}/fido2/pcsc.py
+${PYSITELIB}/fido2/pcsc.pyc
+${PYSITELIB}/fido2/public_suffix_list.dat
+${PYSITELIB}/fido2/py.typed
+${PYSITELIB}/fido2/rpid.py
+${PYSITELIB}/fido2/rpid.pyc
+${PYSITELIB}/fido2/server.py
+${PYSITELIB}/fido2/server.pyc
+${PYSITELIB}/fido2/utils.py
+${PYSITELIB}/fido2/utils.pyc
+${PYSITELIB}/fido2/webauthn.py
+${PYSITELIB}/fido2/webauthn.pyc
+${PYSITELIB}/fido2/win_api.py
+${PYSITELIB}/fido2/win_api.pyc
--- /dev/null
+Needs re-porting to NetBSD.
--- /dev/null
+$NetBSD: distinfo,v 1.4 2021/10/26 11:17:45 nia Exp $
+
+BLAKE2s (fido2-1.1.0.tar.gz) = 92d590ca5ca32758eb40559447844a9eb53c1b22603cc91d5abddb940bfceb5a
+SHA512 (fido2-1.1.0.tar.gz) = 28446710cd2bf1d82ecc52a779cb535943c9ddf020958c6549167091cd8da72f8cd1ab2fd3a0aee0a6f34d61059bcd72ecc2f4504c9086b5c5815b63faaf5d17
+Size (fido2-1.1.0.tar.gz) = 243692 bytes
+SHA1 (patch-fido2_hid_____init____.py) = cbe9b8d3bcfb1852b64ae5cb430d42070255fafb
+SHA1 (patch-fido2_hid_netbsd.py) = 807957e0d7da024bebef68ddba8b3985af8a2057
--- /dev/null
+$NetBSD$
+
+--- fido2/hid/__init__.py.orig 2022-10-17 13:36:35.000000000 +0000
++++ fido2/hid/__init__.py
+@@ -49,6 +49,8 @@ elif sys.platform.startswith("darwin"):
+ from . import macos as backend
+ elif sys.platform.startswith("freebsd"):
+ from . import freebsd as backend
++elif sys.platform.startswith('netbsd'):
++ from . import netbsd as backend
+ elif sys.platform.startswith("openbsd"):
+ from . import openbsd as backend
+ else:
--- /dev/null
+$NetBSD$
+
+--- fido2/hid/netbsd.py.orig 2023-03-11 08:28:55.054680841 +0000
++++ fido2/hid/netbsd.py
+@@ -0,0 +1,151 @@
++# Copyright 2016 Google Inc. All Rights Reserved.
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++"""Implements raw HID interface on NetBSD."""
++
++from __future__ import absolute_import
++
++import errno
++import os
++import select
++import struct
++
++from ctypes import Structure
++from ctypes import c_char
++from ctypes import c_int
++from ctypes import c_ubyte
++from ctypes import c_uint16
++from ctypes import c_uint32
++from ctypes import c_uint8
++from ctypes import sizeof
++from fcntl import ioctl
++
++from . import base
++from . import linux
++
++
++USB_MAX_DEVNAMELEN = 16
++USB_MAX_DEVNAMES = 4
++USB_MAX_STRING_LEN = 128
++USB_MAX_ENCODED_STRING_LEN = USB_MAX_STRING_LEN * 3
++
++
++class usb_ctl_report_desc(Structure):
++ _fields_ = [
++ ('ucrd_size', c_int),
++ ('ucrd_data', c_ubyte * 1024),
++ ]
++
++
++class usb_device_info(Structure):
++ _fields_ = [
++ ('udi_bus', c_uint8),
++ ('udi_addr', c_uint8),
++ ('udi_pad0', c_uint8 * 2),
++ ('udi_cookie', c_uint32),
++ ('udi_product', c_char * USB_MAX_ENCODED_STRING_LEN),
++ ('udi_vendor', c_char * USB_MAX_ENCODED_STRING_LEN),
++ ('udi_release', c_char * 8),
++ ('udi_serial', c_char * USB_MAX_ENCODED_STRING_LEN),
++ ('udi_productNo', c_uint16),
++ ('udi_vendorNo', c_uint16),
++ ('udi_releaseNo', c_uint16),
++ ('udi_class', c_uint8),
++ ('udi_subclass', c_uint8),
++ ('udi_protocol', c_uint8),
++ ('udi_config', c_uint8),
++ ('udi_speed', c_uint8),
++ ('udi_pad1', c_uint8),
++ ('udi_power', c_int),
++ ('udi_nports', c_int),
++ ('udi_devnames', c_char * USB_MAX_DEVNAMES * USB_MAX_DEVNAMELEN),
++ ('udi_ports', c_uint8 * 16),
++ ]
++
++
++USB_GET_DEVICE_INFO = 0x44f45570 # _IOR('U', 112, struct usb_device_info)
++USB_GET_REPORT_DESC = 0x44045515 # _IOR('U', 21, struct usb_ctl_report_desc)
++USB_HID_SET_RAW = 0x80046802 # _IOW('h', 2, int)
++
++
++FIDO_USAGE_PAGE = 0xf1d0
++FIDO_USAGE_U2FHID = 0x01
++
++
++class NetBSDHidDevice(linux.LinuxHidDevice):
++ """Implementation of HID device for NetBSD.
++ """
++
++ @classmethod
++ def _setup(cls, fd, path):
++ devinfobuf = bytearray(sizeof(usb_device_info))
++ ioctl(fd, USB_GET_DEVICE_INFO, devinfobuf, True)
++ devinfo = usb_device_info.from_buffer(devinfobuf)
++ ucrdbuf = bytearray(sizeof(usb_ctl_report_desc))
++ ioctl(fd, USB_GET_REPORT_DESC, ucrdbuf, True)
++ ucrd = usb_ctl_report_desc.from_buffer(ucrdbuf)
++ descdata = bytearray(ucrd.ucrd_data[:ucrd.ucrd_size])
++ desc = base.DeviceDescriptor()
++ desc.path = path
++ desc.vendor_id = devinfo.udi_vendorNo
++ desc.vendor_string = devinfo.udi_vendor.decode('utf-8')
++ desc.product_id = devinfo.udi_productNo
++ desc.product_string = devinfo.udi_product.decode('utf-8')
++ desc.serial_number = devinfo.udi_serial.decode('utf-8')
++ linux.ParseReportDescriptor(descdata, desc)
++ if desc.usage_page != FIDO_USAGE_PAGE:
++ raise Exception('usage page != fido')
++ if desc.usage != FIDO_USAGE_U2FHID:
++ raise Exception('fido usage != u2fhid')
++ ioctl(fd, USB_HID_SET_RAW, struct.pack('@i', 1))
++ ping = bytearray(64)
++ ping[0:7] = bytearray([0xff,0xff,0xff,0xff,0x81,0,1])
++ for i in range(10):
++ os.write(fd, ping)
++ poll = select.poll()
++ poll.register(fd, select.POLLIN)
++ if poll.poll(100):
++ os.read(fd, 64 + 1)
++ break
++ else:
++ raise Exception('u2f ping timeout')
++ return desc
++
++ @classmethod
++ def Enumerate(cls):
++ for i in range(100):
++ path = '/dev/uhid{}'.format(i)
++ fd = None
++ try:
++ fd = os.open(path, os.O_RDWR|os.O_CLOEXEC)
++ desc = cls._setup(fd, path)
++ except OSError as e:
++ if e.errno == errno.ENOENT:
++ break
++ continue
++ finally:
++ if fd is not None:
++ os.close(fd)
++ yield desc.ToPublicDict()
++
++ def __init__(self, path):
++ base.HidDevice.__init__(self, path)
++ self.dev = os.open(path, os.O_RDWR)
++ self.desc = self._setup(self.dev, path)
++
++ def __del__(self):
++ os.close(self.dev)
++
++ def Write(self, packet):
++ os.write(self.dev, bytearray(packet))