feat(applets): merge yubikit-applets into yubikit#446
feat(applets): merge yubikit-applets into yubikit#446DennisDyallo wants to merge 83 commits intoyubikitfrom
Conversation
Adds complete FIDO2/CTAP2 support: - Authenticator info and capabilities - MakeCredential and GetAssertion operations - PIN/UV auth protocols (v1 and v2) - Credential management - Bio enrollment - Large blob storage - Extensions support
Adds complete PIV smart card support: - Session management and authentication - PIN/PUK/Management key operations - Key generation and certificate management - Signing and decryption operations - Slot metadata and touch policies
Adds complete example CLI demonstrating PIV operations: - Device selection and info display - PIN/PUK management - Key generation across slots - Certificate operations - Signing and decryption examples - Attestation verification
… test Discovered and fixed by running all 20 CLI commands against YubiKey 5.8.0: - PivDataObject.Attestation: wrong tag 0x5FC121 (PIV Iris Images) → 0x5FFF01 (Yubico-specific attestation cert object); was returning SW=0x6982 on read - PivSlotMetadataExtensions: parse raw PIV TLV format (0x86+point for ECC, 0x81/0x82 for RSA) instead of SPKI; fixed "ASN1 corrupted data" errors - YubiKeyEcdsaSignatureGenerator: YubiKey returns DER (RFC 3279), not P1363; removed ConvertIeeeP1363ToDer that was corrupting CSR signatures - Signing/Decryption: use explicit algorithm from slot metadata to avoid auto-detect overload that checks PIV app version (0.0.1) not device firmware - Verification: add DSASignatureFormat.Rfc3279DerSequence to ECDsa.VerifyData; YubiKey ECDSA signatures are DER-encoded, not IEEE P1363 Also adds the CLI Commands layer (CliRunner, DeviceHelper, JsonOutput) enabling autonomous end-to-end testing of all PIV session APIs without human interaction. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added missing newlines at the end of multiple files in the PivTool example.
…ey-manager Moves RSA padding removal into PivSession.DecryptAsync, matching the Python yubikey-manager PivSession.decrypt() API where the session owns the full decrypt-and-unpad operation rather than exposing raw RSA output. Implementation uses dummy RSA key + BigInteger.ModPow re-wrap technique (identical to Python's _unpad_message) so .NET's padding-aware RSA.Decrypt can safely unpad PKCS#1 v1.5 or OAEP output from the raw YubiKey response. Security: - rawBytes and reEncrypted intermediates zeroed in finally blocks - try scope starts before ModPow allocation to guarantee cleanup - Added b >= mod guard and output length bounds check in ModPow helper Refactors: - IAsyncDisposable moved up to ApplicationSession base class; redundant overrides removed from PivSession and ManagementSession - Decryption.cs delegates entirely to session.DecryptAsync (no manual PKCS#1 stripping); padding parameter threaded through to call sites Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ding Covers the 4 key scenarios for IPivSession.DecryptAsync: - RSA 2048 PKCS#1 v1.5 round-trip: encrypt with host RSA, decrypt via YubiKey, assert exact plaintext - RSA 2048 OAEP SHA-256 round-trip: same pattern with modern padding - RSA 4096 PKCS#1 round-trip: exercises the keyBits switch in the session-layer ModPow path - ECC slot rejection: ArgumentException thrown before any APDU (session checks metadata first) - Wrong ciphertext length: ArgumentException thrown before any APDU (length vs key size check) Modelled after Python yubikey-manager's test_piv.py. Engineer extracted ResetAndAuthenticate and EncryptThenDecryptRoundTrip helpers to eliminate setup duplication across tests. Reviewer passed clean (no HIGH issues). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements TOTP/HOTP one-time password management for YubiKey devices. Includes session, models, CLI tool, unit tests, and integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements Yubico OTP, HOTP, static password, and HMAC-SHA1 challenge-response. Includes dual-transport backend (SmartCard + OTP HID), slot configurations, CLI tool, unit tests, and integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements credential-based authentication for YubiHSM 2 devices. Supports symmetric (AES-128) and asymmetric (EC P256) credentials. Includes session, models, CLI tool, unit tests, and integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements OpenPGP card v3.4 with partial class organization. Supports RSA/EC key generation, sign/decrypt/authenticate, PIN management, KDF, certificates, and UIF. Includes CLI tool, unit tests, and integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds Spectre.Console TUI/CLI tool for FIDO2 operations including authenticator info, PIN management, credential operations, bio enrollment, and reset. Supports command-line parameters for automated testing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # Yubico.YubiKit.sln
FIDO2 integration tests depend on Core types (IYubiKeyManager, DeviceListenerService, etc.) that exist on the yubikit-fido branch but not on the yubikit base. Excluded until those Core changes are merged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Zero sensitive data (keyValue, secret, deviceResponse) with CryptographicOperations.ZeroMemory() - Replace List<byte>.AddRange(span.ToArray()) with direct byte array construction using CopyTo - Replace List<byte> with MemoryStream in CollectResponseData to avoid repeated ToArray() calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace bare catch with Enum.IsDefined in PwStatus.Parse (no exceptions for control flow) - Use generic Enum.IsDefined<T> in DiscretionaryDataObjects ParseKeyInformation - Fix undisposed Tlv objects in Crt static property initializers by extracting BuildCrt helper with using statement - Run dotnet format to fix trailing newlines across all 37 source files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove dead _logger field and unused Microsoft.Extensions.Logging import from HsmAuthSession (base class Logger property is used instead). Add security warning comments to example tool files that display key material. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rastructure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace injected ILogger with static LoggingFactory pattern in SmartCardBackend and OtpHidBackend (matches CLAUDE.md guidelines) - Use ArgumentNullException.ThrowIfNull instead of ?? throw pattern - Add IDisposable to IYubiOtpBackend to match IManagementBackend style - Add no-op Dispose() to both backend implementations - Remove unnecessary .ToArray() on "en"u8 in BuildNdefText, use ReadOnlySpan<byte> with Span.CopyTo instead of Array.Copy - Zero sensitive scanCodes (password bytes) in ProgramCommand static password methods with CryptographicOperations.ZeroMemory in finally - Remove logger parameter from SmartCardBackend constructor calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Spectre.Console interactive menus with ykman-compatible command tree (info, reset, access change, accounts list/add/code/delete/rename/uri). Auto-selects device when one YubiKey connected, --force/-f skips prompts, all output is pipe-friendly with errors on stderr. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the FidoTool CLI to mirror ykman's fido command tree: - info, reset [-f], access (change-pin, verify-pin), config (toggle-always-uv, enable-ep-attestation), credentials (list, delete), fingerprints (list, add, delete, rename) - PIN provided via --pin option, prompted interactively if omitted - -f/--force flag skips confirmation prompts on destructive ops - Positional args for credential/fingerprint IDs (ykman style) - Rename PinMenu->AccessMenu, BioMenu->FingerprintsMenu, CredentialMgmtMenu->CredentialsMenu to match ykman naming - Add VerifyPinAsync to PinManagement, PromptForPin to OutputHelpers - Keep MakeCredential, GetAssertion, and extended operations in interactive mode only (not part of ykman's fido command tree) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Spectre.Console interactive menus with ykman-compatible command tree (info, reset, access change, accounts list/add/code/delete/rename/uri). Auto-selects device when one YubiKey connected, --force/-f skips prompts, all output is pipe-friendly with errors on stderr. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace interactive Spectre.Console menu system with Spectre.Console.Cli command tree matching ykman's openpgp subcommand hierarchy: - info: display general status - reset [-f]: factory reset - access: set-retries, change-pin, change-admin-pin, set-reset-code, unblock-pin - keys: set-touch, import, generate, attest - certificates: export, import, delete All commands support non-interactive use via CLI options (--pin, --admin-pin, --force) while prompting when options are omitted. Device auto-selected when only one YubiKey is connected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A single YubiKey appears on both SmartCard and HidOtp transports. Select the first available device, preferring SmartCard transport. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Shared (Phase 4) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The test used a 32-byte key expecting ArgumentException, but Authenticate now accepts both 32-byte (PIN token) and 64-byte (shared secret) keys. Changed to 16 bytes which is genuinely invalid. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Cross-referenced with ykman 5.8.0 FIDO reset flow: - Query LongTouchForReset from AuthenticatorInfo to show correct touch message (10s hold for 5.8+/0.0.0 keys, tap for older) - Add TransportsForReset pre-check in interactive menu - Fix --force to skip reinsertion flow entirely (matching ykman) - Add ResetPreflightInfo record and GetPreflightInfoAsync method - Add PinAuthBlocked error mapping, align error messages with ykman Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
clean target must now be specified explicitly; dotnet build.cs clean build for full clean build
OATH: Fix touch property encoding to use raw bytes [tag, value] instead of TLV encoding [tag, length, value], matching ykman's struct.pack. YubiOTP: Fix ConfigFlag values (StrongPw1, StrongPw2, ManUpdate) to match ykman constants. Add missing ChalHmac, ChalYubico, OathHotp8 flags. Add default ext flags (SerialApiVisible, AllowUpdate) to base SlotConfiguration. Add default tkt/ext flags (AppendCr, FastTrigger) to KeyboardSlotConfiguration. Add ChalHmac|HmacLt64 to HMAC-SHA1 config. Add OathFixedModhex2 to HOTP config. Fix Use8Digits to use OathHotp8 instead of OathFixedModhex1. Remove incorrect StaticTicket from StaticPassword config. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ation
Remove DependsOn("build") from test and coverage targets and remove
--no-build flags so dotnet handles incremental building naturally.
Running `dotnet build.cs test` no longer forces a full rebuild — it
only recompiles if sources changed, matching dotnet.exe behavior.
Explicit rebuild via `dotnet build.cs clean build test`.
Add TranslateToMtpFilter() to convert VSTest --filter expressions to
xUnit v3 MTP native options (--filter-method, --filter-trait, etc.).
Add --minimum-expected-tests 0 to prevent failure when no tests match.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Replace == null / != null with is null / is not null across all modules - Remove all #region / #endregion directives (91 files, 399 lines removed) - Replace SequenceEqual with CryptographicOperations.FixedTimeEquals in security-sensitive contexts (ATR, FIDO nonce, RP ID hash, large blob hash, OATH credential ID, OpenPGP OID) - Replace Array.Empty<byte>() with [] where target type supports it Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --smoke flag to skip Slow and RequiresUserPresence tests for fast integration runs. Extract DiscoverProjects() and FilterProjectsByName() to eliminate repeated project discovery logic. Add --project support to coverage target. Update BUILD.md, CLAUDE.md, and TESTING.md with integration test strategy. Mark RSA 3072/4096 PIV tests as [Slow]. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Convert `new byte[] { ... }` to `[...]` and `Array.Empty<T>()` to `[]`
where C# 14 collection expressions are supported by the target type.
Skipped instances where `var` inference, `Memory<byte>`, attribute args,
or method chaining prevent collection expression usage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The stub class in Core was unreferenced — no code in Core throws, catches, or uses it. The full implementation lives in Fido2/Ctap/CtapException.cs where it belongs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The extended parameter's mapping to P2 values was reversed vs ykman canonical. extended=false should send P2=0x81 (signature-only) and extended=true should send P2=0x82 (decrypt/authenticate/attest). Fix tests to use correct extended values for each operation type. Integration: 27/28 pass (AttestKey remains alpha firmware gap). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Convert.ToHexString accepts ReadOnlySpan<byte> natively on net10 - Collection expression spread operator supports ReadOnlySpan<byte> - Tlv.ToString: replace BitConverter.ToString().Replace() with Convert.ToHexString() (cleaner + zero-alloc) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AttestKeyAsync incorrectly parsed the GET_ATTESTATION APDU response as a certificate. Per ykman canonical, GET_ATTESTATION writes the cert to the slot — read it back with GetCertificateAsync. Also fix SelectCertificateSlotAsync index mapping (should be 3-keyRef: SIG=2, DEC=1, AUT=0) and non-standard FW<=5.4.3 byte placement (prepend before TLV, not inside). Integration: 28/28 pass. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Alpha/beta firmware reports 0.0.1 sentinel from applet SELECT, causing raw FirmwareVersion comparisons to fail. IsSupported() handles Major==0 by assuming all features available. Fixes PIV GetPinAttemptsAsync returning wrong retry count and several other feature gates across OATH, OpenPGP, and PIV modules. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
HMAC-SHA1 challenge-response is not supported over USB CCID (SmartCard), matching ykman's not_usb_ccid condition. Changed ConnectionType from SmartCard to HidOtp and removed incorrect RequiresUserPresence trait since the test doesn't enable touch-triggered mode. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… key .NET's TripleDES rejects the default PIV management key (0102030405060708 repeated) as a "known weak key" because all three DES subkeys are identical. This is mandated by the PIV spec and cannot be avoided. Replace TripleDES.Create() with manual 3DES using individual DES block operations (encrypt-decrypt-encrypt / decrypt-encrypt-decrypt). The subkey 0102030405060708 is not a DES weak key, so this works correctly. Also adds YubiKey 5C NFC (5.4.3, SN:20260533) to the test allowlist and updates the handoff document with investigation findings for all blockers. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…field ordering - core: reject BER-TLV 0x80 indefinite length encoding (was silently misread as 128) - openpgp: add try-catch fallback in GetAlgorithmInformationAsync for malformed TLV from older firmware (5.4.3), matching ykman's padding approach (Tlv.unpack + b"\0\0") - openpgp: relax reset-state test assertions to verify structure not firmware-specific zero values (5.4.3 does not clear fingerprint/generation-time DOs on TERMINATE+ACTIVATE) - hsmauth: swap ChangeCredentialPasswordAdmin TLV field order to [Label, MgmtKey, NewPw] matching ykman reference implementation Integration tests on 5C NFC 5.4.3 (SN:20260533): OpenPGP 28/28 (was 25/28) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Merges the previously separate yubikit-applets work into the yubikit integration branch, expanding the SDK with additional applet/CLI functionality and a set of integration-test-driven fixes (notably around firmware sentinel versions and TLV parsing).
Changes:
- Added FIDO2 module documentation and module-specific agent guidance (
README.md,CLAUDE.md). - Hardened Core behavior (e.g., BER-TLV indefinite-length rejection, sentinel firmware handling, constant-time comparisons) and updated related tests.
- Introduced shared CLI infrastructure (
Yubico.YubiKit.Cli.Shared) and updated project references/docs accordingly.
Reviewed changes
Copilot reviewed 108 out of 807 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Fido2/README.md | Adds end-user FIDO2 module overview and usage examples. |
| src/Fido2/CLAUDE.md | Adds module-specific contributor/agent guidance and architecture notes for FIDO2. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/YubiKeyDeviceRepositoryTests.cs | Removes region markers and keeps unit tests aligned with current repository patterns. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/YubiKeyDeviceMonitorServiceTests.cs | Removes region markers and keeps unit tests aligned with current repository patterns. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/YubiKeyDeviceManagerTests.cs | Adjusts monitoring expectations and removes region markers for updated behavior. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/Utils/TlvTests.cs | Updates tests to use collection expressions and adds coverage for BER-TLV 0x80 rejection. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/Utils/TlvHelperTests.cs | Updates test data initialization to collection expressions. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/Utils/DisposableTlvListTests.cs | Updates test data initialization to collection expressions. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/Scp/X963KdfTests.cs | Normalizes empty-buffer creation patterns and removes region markers. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/Scp/Scp11Tests.cs | Removes region markers around helpers. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/PcscProtocolTests.cs | Removes region markers to simplify test files. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/Fakes/FakeSmartCardConnection.cs | Removes region markers in fake connection implementation. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/Fakes/FakeApduProcessor.cs | Removes region markers in fakes and keeps formatting consistent. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/SmartCard/DesktopSmartCardDeviceListenerDisposalTests.cs | Removes region markers in disposal tests. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/Hid/Otp/OtpHidProtocolTests.cs | Fixes expected-length assertion for status-only OTP HID responses. |
| src/Core/tests/Yubico.YubiKit.Core.UnitTests/Hid/HidDeviceListenerDisposalTests.cs | Removes region markers in disposal tests. |
| src/Core/tests/Yubico.YubiKit.Core.IntegrationTests/Yubico.YubiKit.Core.IntegrationTests.csproj | Updates shared test project reference path. |
| src/Core/src/YubiKey/PcscYubiKey.cs | Removes region markers and preserves IYubiKey implementation behavior. |
| src/Core/src/YubiKey/FirmwareVersion.cs | Removes region markers and keeps version constants accessible. |
| src/Core/src/YubiKey/FindYubiKeys.cs | Removes region markers and keeps device discovery logic intact. |
| src/Core/src/YubiKey/ApplicationSession.cs | Adjusts feature support checks for sentinel firmware versions and adds IAsyncDisposable. |
| src/Core/src/Utils/TlvHelper.cs | Returns Memory<byte>.Empty for empty dictionary encoding. |
| src/Core/src/Utils/Tlv.cs | Rejects BER-TLV indefinite length 0x80 and updates ToString hex formatting. |
| src/Core/src/Utils/DisposableTlvList.cs | Removes region markers and keeps disposal semantics. |
| src/Core/src/Utils/DisposableTlvDictionary.cs | Removes region markers in commented legacy implementation. |
| src/Core/src/SmartCard/UsbSmartCardConnection.cs | Removes region markers in smart card connection and nested scopes. |
| src/Core/src/SmartCard/SmartCardConnectionFactory.cs | Removes region markers, preserving factory behavior. |
| src/Core/src/SmartCard/Scp/SessionKeys.cs | Normalizes null checks while preserving secure zeroing. |
| src/Core/src/SmartCard/Scp/ScpState.cs | Normalizes null checks and ensures buffers are zeroed in finally blocks. |
| src/Core/src/SmartCard/Scp/ScpProcessor.cs | Normalizes null checks for pooled buffers and removes regions. |
| src/Core/src/SmartCard/Scp/ScpExtensions.cs | Removes region markers around extension block. |
| src/Core/src/SmartCard/Scp/Scp11KeyParameters.cs | Normalizes null-check syntax. |
| src/Core/src/SmartCard/Scp/PcscProtocolScp.cs | Removes region markers in wrapper protocol implementation. |
| src/Core/src/SmartCard/Scp/AesCmac.cs | Removes region markers and keeps disposal behavior. |
| src/Core/src/SmartCard/SWConstants.cs | Removes region markers in SW constant definitions. |
| src/Core/src/SmartCard/PcscProtocolFactory.cs | Removes region markers around factory implementation. |
| src/Core/src/SmartCard/PcscProtocol.cs | Avoids allocation in logging and adds sentinel firmware handling in Configure(). |
| src/Core/src/SmartCard/FindPcscDevices.cs | Removes region markers around device finder. |
| src/Core/src/SmartCard/ChainedResponseReceiver.cs | Removes region markers around APDU processor members. |
| src/Core/src/SmartCard/ApduTransmitter.cs | Removes region markers around APDU processor members. |
| src/Core/src/SmartCard/ApduFormatterShort.cs | Removes region markers around formatter members. |
| src/Core/src/SmartCard/ApduFormatterExtended.cs | Removes region markers around formatter members. |
| src/Core/src/SmartCard/AnswerToReset.cs | Uses constant-time equality for ATR comparisons and adds required using. |
| src/Core/src/ServiceLocator.cs | Normalizes null-check pattern. |
| src/Core/src/PlatformInterop/Windows/Kernel32/Kernel32.Interop.cs | Removes region markers in interop declarations. |
| src/Core/src/PlatformInterop/Windows/HidD/HidDDevice.cs | Removes region markers and retains disposal logic. |
| src/Core/src/PlatformInterop/Windows/HidD/HidD.Interop.cs | Removes region markers in interop declarations. |
| src/Core/src/PlatformInterop/Windows/Cfgmgr32/CmPropertyAccessHelper.cs | Removes region markers around nested delegate. |
| src/Core/src/PlatformInterop/Windows/Cfgmgr32/CmDevice.cs | Normalizes null-check pattern. |
| src/Core/src/PlatformInterop/Windows/Cfgmgr32/Cfgmgr32.Interop.cs | Removes region markers in interop file. |
| src/Core/src/PlatformInterop/Windows/Cfgmgr32/Cfgmgr32.DeviceProperties.cs | Removes region markers around DEVPROP definitions. |
| src/Core/src/PlatformInterop/UnmanagedDynamicLibrary.cs | Removes region markers around IDisposable implementation. |
| src/Core/src/PlatformInterop/NativeMethods.cs | Removes region markers around enum definitions. |
| src/Core/src/PlatformInterop/MacOS/IOKitFramework/IOKitHid.Interop.cs | Removes region markers around delegates. |
| src/Core/src/PlatformInterop/Linux/Udev/LinuxUdev.cs | Removes region markers around IDisposable implementation. |
| src/Core/src/PlatformInterop/Linux/Libc/Libc.Interop.cs | Removes region markers and reorganizes interop sections. |
| src/Core/src/Hid/Windows/WindowsHidIOReportConnection.cs | Removes region markers in commented implementation. |
| src/Core/src/Hid/Windows/WindowsHidFeatureReportConnection.cs | Removes region markers in commented implementation. |
| src/Core/src/Hid/Translators/HidCodeTranslator.cs | Removes region markers for readability. |
| src/Core/src/Hid/Fido/FidoHidProtocol.cs | Uses constant-time nonce compare and avoids allocations in logging. |
| src/Core/src/Exceptions.cs | Removes placeholder exception type from Core exceptions file. |
| src/Core/src/Cryptography/RsaFormat.cs | Updates commented code to use collection expressions for consistency. |
| src/Core/src/Cryptography/RSAPublicKey.cs | Normalizes null-checks for RSA parameters. |
| src/Core/src/Cryptography/RSAParametersExtensions.cs | Normalizes null-checks in normalization logic. |
| src/Core/src/Cryptography/KeyTypeExtensions.cs | Normalizes null-check usage in key definition helpers. |
| src/Core/src/Cryptography/KeyDefinitions.cs | Normalizes null-check usage for COSE key definition filtering. |
| src/Core/src/Cryptography/EcdsaVerify.cs | Updates commented code to use collection expressions for consistency. |
| src/Core/src/Cryptography/ECParametersExtensions.cs | Removes region markers around extension block. |
| src/Core/src/Cryptography/Cose/CoseEdDsaPublicKey.cs | Updates commented code to use collection expressions for consistency. |
| src/Core/src/Cryptography/Cose/CoseEcPublicKey.cs | Normalizes null-check usage in commented code paths. |
| src/Core/src/Cryptography/CmacPrimitivesOpenSsl.cs | Removes region markers around IDisposable implementation. |
| src/Core/src/Cryptography/AsnUtilities.cs | Normalizes null-check patterns. |
| src/Core/src/Cryptography/AsnPublicKeyEncoder.cs | Normalizes null-check patterns and keeps validation consistent. |
| src/Core/src/Cryptography/AsnPrivateKeyEncoder.cs | Normalizes null-check patterns for private key encoding. |
| src/Cli.Shared/src/Yubico.YubiKit.Cli.Shared.csproj | Introduces new shared CLI project with Spectre.Console dependency. |
| src/Cli.Shared/src/Output/PinPrompt.cs | Adds a reusable masked PIN prompt helper for CLIs. |
| src/Cli.Shared/src/Output/OutputHelpers.cs | Adds shared Spectre.Console formatting/output utilities. |
| src/Cli.Shared/src/Output/ConfirmationPrompts.cs | Adds reusable dangerous/destructive confirmation flows. |
| src/Cli.Shared/src/Device/FormFactorFormatter.cs | Adds shared formatter for device form factors. |
| src/Cli.Shared/src/Device/DeviceSelectorBase.cs | Adds shared device discovery/selection flow for CLIs. |
| src/Cli.Shared/src/Device/DeviceSelection.cs | Adds shared device selection record. |
| src/Cli.Shared/src/Device/ConnectionTypeFormatter.cs | Adds shared formatter for connection types. |
| src/Cli.Shared/src/Cli/SessionHelper.cs | Adds shared session lifecycle helpers for CLIs. |
| src/Cli.Shared/src/Cli/InteractiveMenuBuilder.cs | Adds reusable interactive menu loop builder. |
| src/Cli.Shared/src/Cli/CommandHelper.cs | Adds shared CTS + YubiKeyManager lifecycle helpers. |
| src/Cli.Shared/src/Cli/ArgumentParser.cs | Adds shared CLI argument parsing utilities. |
| experiments/DeviceMonitor/DeviceMonitor.csproj | Updates experiment project references to new src/ layout. |
| experiments/DebugSlotMetadata/DebugSlotMetadata.csproj | Updates experiment project references to new src/ layout. |
| docs/TESTING.md | Documents a tiered integration testing strategy and smoke-test behavior. |
| Yubico.YubiKit.YubiOtp/tests/Yubico.YubiKit.YubiOtp.UnitTests/PlaceholderTests.cs | Removes placeholder unit test file. |
| Yubico.YubiKit.Tests.Shared/appsettings.json | Removes allowlist configuration from old location. |
| Yubico.YubiKit.OpenPgp/tests/Yubico.YubiKit.OpenPgp.UnitTests/PlaceholderTests.cs | Removes placeholder unit test file. |
| Yubico.YubiKit.Oath/tests/Yubico.YubiKit.Oath.UnitTests/PlaceholderTests.cs | Removes placeholder unit test file. |
| Yubico.YubiKit.Management/examples/ManagementTool/Program.cs | Removes old ManagementTool program entry (likely migrated to shared infra). |
| Plans/yubikit-applets-final-state.md | Adds final-state handover notes and integration-test findings. |
| Plans/streamed-meandering-adleman.md | Adds implementation plan/historical context for applet rollout. |
| Plans/handoff.md | Adds branch handoff summary and next steps. |
| Plans/goals/goal-yubiotp.md | Adds detailed YubiOTP implementation goal/spec. |
| Plans/goals/goal-openpgp.md | Adds detailed OpenPGP implementation goal/spec. |
| Plans/goals/goal-oath.md | Adds detailed OATH implementation goal/spec. |
| Plans/goals/goal-hsmauth.md | Adds detailed HsmAuth implementation goal/spec. |
| Plans/goals/goal-fido2-cli.md | Adds CLI-only goal/spec for FIDO2 tooling. |
| Plans/cli-shared-infrastructure.md | Documents plan and completion notes for CLI shared infrastructure extraction. |
| Directory.Packages.props | Adds centralized Spectre.Console.Cli version pin. |
| CLAUDE.md | Updates repository path conventions and expands testing guidance. |
| BUILD.md | Updates script target dependencies, integration/smoke options, and examples. |
Comments suppressed due to low confidence (1)
src/Core/src/Exceptions.cs:20
- Removing the public
CtapExceptiontype fromYubico.YubiKit.Coreis a breaking API change for any consumers that referenced it (even if it was previously a placeholder). If the intent is to relocate CTAP exceptions into the FIDO2 module, consider keeping a compat type in Core (e.g.,[Obsolete]forwarding wrapper) or reintroducingCtapExceptionin Core as a thin derived type to preserve binary/source compatibility.
public class BadResponseException(string message) : Exception(message)
{
//The data contained in a YubiKey response was invalid
}
| // Create indexed choices and sort by name, keeping original index | ||
| var indexedChoices = deviceInfos | ||
| .Select((d, index) => (Choice: FormatDeviceChoice(d.Device, d.Info), OriginalIndex: index)) | ||
| .OrderBy(x => x.Choice) | ||
| .ToList(); | ||
|
|
||
| var choices = indexedChoices.Select(x => x.Choice).ToList(); | ||
| choices.Add("Cancel"); | ||
|
|
||
| var selection = AnsiConsole.Prompt( | ||
| new SelectionPrompt<string>() | ||
| .Title("Multiple YubiKeys detected. Select one:") | ||
| .PageSize(10) | ||
| .AddChoices(choices)); | ||
|
|
||
| if (selection == "Cancel") | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| // Find the original index from the sorted list | ||
| var selectedSortedIndex = choices.IndexOf(selection); | ||
| var originalIndex = indexedChoices[selectedSortedIndex].OriginalIndex; | ||
| var selected = deviceInfos[originalIndex]; |
There was a problem hiding this comment.
Device selection uses a string label as the prompt key and then maps back via IndexOf(selection). If two devices end up with identical formatted strings (e.g., missing serial numbers, same form factor/firmware/transport), IndexOf will resolve to the first match and can select the wrong device. Prefer prompting over a strongly-typed choice (e.g., SelectionPrompt<(IYubiKey Device, DeviceInfo? Info)> with a converter) or embed a unique disambiguator in the label (like a stable index or DeviceId) and parse it back.
| Extensions = new ExtensionBuilder() | ||
| .AddCredProtect(CredProtectPolicy.UserVerificationRequired) | ||
| .Build() |
There was a problem hiding this comment.
The extension-builder API shown here appears inconsistent with the module guidance in src/Fido2/CLAUDE.md (which describes ExtensionBuilder.Create() and .WithCredProtect(...) / .WithHmacSecret(...)). Please align the README examples with the actual public API surface and keep naming consistent across docs to avoid copy/paste failures.
| /// Waits for the user to press any key. | ||
| /// </summary> | ||
| public static void WaitForKey() | ||
| { |
There was a problem hiding this comment.
Console.ReadKey can throw in non-interactive contexts (e.g., when input is redirected or no console is attached), which can break scripting/CI usage of the CLI tools. Consider guarding with Console.IsInputRedirected (and/or AnsiConsole.Profile.Capabilities.Interactive) and turning this into a no-op in non-interactive mode.
| { | |
| { | |
| if (!AnsiConsole.Profile.Capabilities.Interactive || Console.IsInputRedirected) | |
| { | |
| return; | |
| } |
- Add 'Install PC/SC dependencies' step to install pcscd and libpcsclite-dev before building. libYubico.NativeShims.so (from NuGet Yubico.NativeShims 1.14.0) links against libpcsclite.so.1 at runtime; without it, unit tests that call YubiKeyManager.FindAllAsync() throw DllNotFoundException instead of returning an empty list. - Start pcscd so SCardEstablishContext() succeeds; with no hardware attached, SCardListReaders returns no readers and FindAll() returns [] as expected. - Fix NuGet cache key: packages.lock.json files don't exist in this repo, so the previous key hash was always empty. Use Directory.Packages.props instead (central version management file that changes with every dependency update). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…iveShims 1.16.0
**CI (build.yml):**
- Replace 'service pcscd start' with 'pcscd --foreground &' + chmod 777 socket.
On GitHub Actions ubuntu-latest, pcscd installs and auto-starts but the
runner user gets SCARD_W_SECURITY_VIOLATION (0x8010006A = socket permission
denied) rather than SCARD_E_NO_SERVICE. Running pcscd directly and opening
socket permissions gives the test user access so FindAllAsync() returns [].
- Fix NuGet cache key: use Directory.Packages.props hash (packages.lock.json
files don't exist in this repo, so the previous key was always empty).
**SDK (FindPcscDevices.cs):**
- Catch DllNotFoundException from SCardEstablishContext (native lib missing):
return [] with a warning log instead of letting the exception propagate.
- Treat any non-success SCardEstablishContext result as "no devices accessible"
(return []) rather than throwing PlatformInteropException. This aligns with:
1. DesktopSmartCardDeviceListener.Start() which already logs and sets
Status.Error on SCardEstablishContext failure without throwing
2. SCardListReaders failure already returning [] silently
3. Test design intent: YubiKeyManager_FindAllAsync_NoDevices_ReturnsEmptyList
documents the expected behavior as empty list in no-hardware environments
**Dependencies (Directory.Packages.props):**
- Bump Yubico.NativeShims 1.14.0 → 1.16.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…enumeration FindHidDevices.FindAllLinux() now catches DllNotFoundException and returns empty list when libudev.so is not available — same graceful degradation pattern established in FindPcscDevices.FindAll(). Also adds libudev-dev to the CI apt-get install so the unversioned libudev.so symlink is present, matching how libpcsclite-dev provides libpcsclite.so. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| namespace Yubico.YubiKit.Core; | ||
|
|
||
| public class CtapException : Exception | ||
| { | ||
| //An error response from a YubiKey | ||
| } | ||
|
|
||
| public class BadResponseException(string message) : Exception(message) | ||
| { | ||
| //The data contained in a YubiKey response was invalid |
There was a problem hiding this comment.
Removing the public CtapException type from Yubico.YubiKit.Core is a breaking API change for any consumers catching that exception (even if it was previously a placeholder). If the intent is to move CTAP exceptions into the FIDO2 module, consider keeping a compatibility shim in Core (e.g., an obsolete type that derives from/forwards to the new exception), or leave the placeholder in place until a major-version breaking-change window.
| // BER-TLV: 0x80 = indefinite length (not supported in determinate-length encoding) | ||
| if (length == 0x80) | ||
| { | ||
| throw new ArgumentException("Indefinite length encoding (0x80) is not supported"); |
There was a problem hiding this comment.
This introduces a new user-facing exception string inline. In this repo, exception strings are expected to come from the centralized resources (e.g., Resources/ExceptionMessages.resx + generated accessor) to keep messaging consistent and localizable. Consider moving this string to the standard exception message resources and referencing it here.
| throw new ArgumentException("Indefinite length encoding (0x80) is not supported"); | |
| throw new ArgumentException(ExceptionMessages.IndefiniteLengthEncodingNotSupported); |
| // Create indexed choices and sort by name, keeping original index | ||
| var indexedChoices = deviceInfos | ||
| .Select((d, index) => (Choice: FormatDeviceChoice(d.Device, d.Info), OriginalIndex: index)) | ||
| .OrderBy(x => x.Choice) | ||
| .ToList(); | ||
|
|
||
| var choices = indexedChoices.Select(x => x.Choice).ToList(); | ||
| choices.Add("Cancel"); | ||
|
|
||
| var selection = AnsiConsole.Prompt( | ||
| new SelectionPrompt<string>() | ||
| .Title("Multiple YubiKeys detected. Select one:") | ||
| .PageSize(10) | ||
| .AddChoices(choices)); |
There was a problem hiding this comment.
Device selection can return the wrong device when two entries produce identical FormatDeviceChoice(...) strings (e.g., when DeviceInfo is null for multiple devices, or same serial/form-factor/firmware across transports). Because selection is a string and IndexOf returns the first match, duplicates will mis-map. Prefer using a selection prompt over a unique object/key (e.g., store a unique DeviceId in the choice mapping or use SelectionPrompt<T> with a converter), and map selection via a dictionary keyed by that unique value.
Summary
yubikitintegration branchKey fixes in this branch (recent sessions)
0x80indefinite length encodingGetAlgorithmInformationTLV from FW 5.4.3 (matches ykman padding approach)ChangeCredentialPasswordAdminTLV field ordering to[Label, MgmtKey, NewPw]IsSupported()handles0.0.1sentinel firmware correctlyKnown limitations
OtpHidProtocol.cs:211(works on alpha firmware)ChangeCredentialPasswordnot testable on alpha (INS0x0Bnot implemented,SW=0x6D00)Test plan
dotnet build Yubico.YubiKit.sln🤖 Generated with Claude Code