Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
bcfd09a
docs: add composite device program plan
DennisDyallo Jun 9, 2026
1348627
refactor(core): promote read-only device metadata from management
DennisDyallo Jun 9, 2026
e2aa219
style: apply dotnet format across solution
DennisDyallo Jun 9, 2026
c36bec2
feat(core): add device-info reader and delegate management read
DennisDyallo Jun 9, 2026
63a12e6
chore(review): add interim cross-vendor review workflow; fix phase 35…
DennisDyallo Jun 9, 2026
ff32e31
feat(core)!: model IYubiKey as a physical device
DennisDyallo Jun 9, 2026
ac78b8f
feat(core): merge per-interface discoveries into composite physical d…
DennisDyallo Jun 10, 2026
28671df
docs(core): flag composite-merge limitations + add SKY/serial-less tests
DennisDyallo Jun 10, 2026
bcf57af
feat(core): merge composite devices by USB Product ID (Rust model)
DennisDyallo Jun 10, 2026
a1be65f
docs(core): add Rust parity comparison for composite device model
DennisDyallo Jun 10, 2026
72ac363
docs(core): re-verify Rust parity comparison against latest upstream
DennisDyallo Jun 10, 2026
6cec484
docs(core): split Phase 38 — carve held-transport fallback into Phase…
DennisDyallo Jun 10, 2026
2d29dfe
docs(core): add Phase 38 ISA (extension smart defaults + overrides)
DennisDyallo Jun 10, 2026
f1e1f4f
feat(core): Phase 38 — extension smart defaults + explicit transport …
DennisDyallo Jun 11, 2026
d3ed095
docs(core): mark master ISC-21..24 satisfied by Phase 38
DennisDyallo Jun 11, 2026
af6ec8c
docs(core): add Phase 38.5 ISA (held-transport fallback)
DennisDyallo Jun 11, 2026
a3cf0b4
feat(core): Phase 38.5 — held-transport fallback for multi-transport …
DennisDyallo Jun 11, 2026
d3194f9
docs(core): add Phase 39 ISA (integration, docs, final verification)
DennisDyallo Jun 12, 2026
7f866a7
docs(core): Phase 39 — composite-device program final verification + …
DennisDyallo Jun 12, 2026
59ca9a2
docs(core): Phase 39 — add Windows HID caveat + qualify composite mer…
DennisDyallo Jun 12, 2026
c31c01d
chore: remove old docs
DennisDyallo Jun 12, 2026
77e23ee
chore(workflow): update branch patterns for push and pull_request
DennisDyallo Jun 15, 2026
dbab4d3
fix(workflow): correct branch pattern syntax in build.yml
DennisDyallo Jun 15, 2026
f1fc8a7
fix(core): make composite transport fallback cover session init
DennisDyallo Jun 15, 2026
817603d
fix(core): avoid unsafe PID-only composite identity reuse
DennisDyallo Jun 15, 2026
add3a31
fix(management): run session creation through held-transport fallback
DennisDyallo Jun 15, 2026
1ccda32
fix(yubiotp): apply held-transport fallback to session creation
DennisDyallo Jun 15, 2026
cb7f33e
fix(fido2): route SCP sessions over SmartCard by default
DennisDyallo Jun 15, 2026
9546c9b
fix(cli-shared): format composite connection flags
DennisDyallo Jun 15, 2026
c8960af
fix(cli): propagate transport override into applet sessions
DennisDyallo Jun 15, 2026
7f62f8a
fix(fido-example): use concrete reset transport for composite devices
DennisDyallo Jun 15, 2026
752b34e
Reorganize Core source layout
DennisDyallo Jun 15, 2026
c197f25
test(perf): add YubiKit performance benchmarks
DennisDyallo Jun 15, 2026
4b0e958
perf(otp): reduce HID write polling latency
DennisDyallo Jun 16, 2026
0a741bd
fix(core): harden SmartCard listener recovery
DennisDyallo Jun 16, 2026
10c2c04
test(core): add OTP polling resilience guard
DennisDyallo Jun 16, 2026
eb2ac82
test(core): add runtime resilience static scanner
DennisDyallo Jun 16, 2026
21b8501
docs: document runtime resilience workflow
DennisDyallo Jun 16, 2026
dad4326
fix(core): dispose SmartCard listener contexts on stop
DennisDyallo Jun 16, 2026
52d4d11
test(core): add runtime resilience fast runner
DennisDyallo Jun 16, 2026
b24077c
docs: defer runtime diagnostics project
DennisDyallo Jun 16, 2026
0363a3d
docs: defer runtime audit skill
DennisDyallo Jun 16, 2026
58ad07c
ci: add runtime resilience check
DennisDyallo Jun 16, 2026
58c4ee9
docs: fold runtime resilience learnings forward
DennisDyallo Jun 16, 2026
2a4c67b
docs(core): require resilience runner for loop changes
DennisDyallo Jun 16, 2026
b933d2a
feat(core): add Windows HID transport
DennisDyallo Jun 23, 2026
db41b6a
fix(core): document Windows HID access failures
DennisDyallo Jun 23, 2026
bf1884d
fix(core): interpret device info more-data as page count
DennisDyallo Jun 23, 2026
32158c9
fix(fido2): align CTAP status values with CTAP 2.2
DennisDyallo Jun 23, 2026
931fd4b
fix(webauthn): retry operations when PIN UV token is required
DennisDyallo Jun 23, 2026
742d341
fix(core): always append APDU Le fields
DennisDyallo Jun 23, 2026
85d6f0b
fix(core): use full PIV application identifier
DennisDyallo Jun 23, 2026
e3dda1f
fix(core): validate CTAPHID continuation sequences
DennisDyallo Jun 23, 2026
ad10e1e
test(core): cover device info more-data counts
DennisDyallo Jun 23, 2026
23bdbfb
docs(fido2): clarify CTAP status coverage
DennisDyallo Jun 23, 2026
e9a1a2f
Merge branch 'yubikit-ctap-status-22-alignment' into yubikit-webauthn…
DennisDyallo Jun 23, 2026
d265372
chore: code style
DennisDyallo Jun 24, 2026
de5f0ed
fix(core): audit and fix Windows HID tests
DennisDyallo Jun 24, 2026
51ac5b2
refactor: code style and warnings
DennisDyallo Jun 24, 2026
d04b18a
fix(webauthn): consolidate PUAT retry cleanup
DennisDyallo Jun 24, 2026
5064eb0
fix(core): audit and fix SmartCard listener tests
DennisDyallo Jun 24, 2026
660567e
fix(core): validate CTAPHID response channels
DennisDyallo Jun 24, 2026
630c697
Delete src/Core/tests/Yubico.YubiKit.Core.UnitTests/Sessions/Applicat…
DennisDyallo Jun 24, 2026
d385a74
test: update APDU Le command vectors
DennisDyallo Jun 24, 2026
10c1661
Merge pull request #492 from Yubico/codex-core-layout-refactor
DennisDyallo Jun 25, 2026
e8141ce
Merge pull request #501 from Yubico/yubikit-piv-9-byte-aid
DennisDyallo Jun 26, 2026
a0b78a6
refactor(fido2): remove PuvathRequired backwards compat alias
github-actions[bot] Jun 26, 2026
f9f649e
Merge pull request #505 from Yubico/yubikit-ctap-status-22-alignment
DennisDyallo Jun 29, 2026
0ba38b2
Merge remote-tracking branch 'origin/yubikit-performance' into yubiki…
DennisDyallo Jun 29, 2026
0bbc526
Merge remote-tracking branch 'origin/yubikit-performance' into yubiki…
DennisDyallo Jun 29, 2026
b360196
Merge remote-tracking branch 'origin/yubikit-performance' into yubiki…
DennisDyallo Jun 29, 2026
9dd1ca4
fix(webauthn): preserve exclude list without preflight
DennisDyallo Jun 29, 2026
492171f
fix(core): require init bit for ctaphid keepalive
DennisDyallo Jun 29, 2026
b123546
refactor(fido2): keep only canonical puat status
DennisDyallo Jun 29, 2026
cc37571
refactor(fido2): keep only canonical puat status
DennisDyallo Jun 29, 2026
1293541
fix(core): reject duplicate device info more-data tags
DennisDyallo Jun 29, 2026
5eccc8f
test(core): observe smartcard listener dispose faults
DennisDyallo Jun 29, 2026
fd7d983
fix(core): use ArgumentException for HID report buffer length validation
github-actions[bot] Jun 29, 2026
c2cae84
Merge pull request #496 from Yubico/yubikit-hid-windows
DennisDyallo Jun 30, 2026
82b32a4
fix(core): preserve SmartCard context on stuck listener
DennisDyallo Jun 30, 2026
41c554e
Merge pull request #493 from Yubico/yubikit-performance
DennisDyallo Jul 1, 2026
e8bf5db
test(core): require started smartcard listener in integration tests
DennisDyallo Jul 1, 2026
356dab7
Merge pull request #506 from Yubico/yubikit-smartcard-improvements
DennisDyallo Jul 1, 2026
565697e
fix(core): validate ctaphid keepalive framing
DennisDyallo Jul 1, 2026
3239ecb
Merge pull request #500 from Yubico/yubikit-webauthn-puat-retry
DennisDyallo Jul 1, 2026
87bba11
docs: clarify YubiKey-returned data sensitivity
DennisDyallo Jul 1, 2026
036693b
refactor(core): simplify device info duplicate tag handling
DennisDyallo Jul 1, 2026
fb5835f
refactor(core): keep device info tlvs alive
DennisDyallo Jul 1, 2026
15a6445
Merge pull request #502 from Yubico/yubikit-device-info-more-data-count
DennisDyallo Jul 1, 2026
a91fe73
Merge pull request #504 from Yubico/yubikit-ctaphid-sequence-wrap
DennisDyallo Jul 1, 2026
caa8133
Merge pull request #503 from Yubico/yubikit-apdu-always-append-le
DennisDyallo Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ csharp_style_prefer_readonly_struct = true
csharp_style_prefer_readonly_struct_member = true

# Code-block preferences
csharp_prefer_braces = false:when_multiline
csharp_prefer_braces = when_multiline:none
csharp_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_diagnostic.IDE0046.severity = suggestion
dotnet_diagnostic.IDE0072.severity = suggestion
csharp_prefer_simple_using_statement = true
csharp_style_namespace_declarations = file_scoped
csharp_style_prefer_method_group_conversion = true
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Build and Test (2.0)

on:
push:
branches: [ yubikit, yubikit-applets ]
branches: [ yubikit*, yubikit/** ]
pull_request:
branches: [ yubikit, yubikit-applets ]
branches: [ yubikit*, yubikit/** ]

jobs:
build-and-test:
Expand Down Expand Up @@ -55,6 +55,9 @@ jobs:
- name: Run unit tests
run: dotnet toolchain.cs test

- name: Run runtime resilience checks
run: dotnet toolchain.cs -- resilience --fast

- name: Pack NuGet packages
run: dotnet toolchain.cs pack --package-version 2.0.0-preview.${{ github.run_number }}

Expand Down
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Do not run `dotnet build` directly. Use `dotnet toolchain.cs build` or `dotnet toolchain.cs build --project Piv`.
- Do not run `dotnet test` directly. Unit tests mix xUnit v3/Microsoft Testing Platform and xUnit v2; `dotnet toolchain.cs test` detects and invokes the right runner.
- Focus tests with both module and filter when possible: `dotnet toolchain.cs test --project Fido2 --filter "Method~Sign"`.
- When touching Core runtime loops, polling paths, recovery logic, or listener lifecycle cleanup, also run `dotnet toolchain.cs -- resilience --fast`.
- `--integration` requires `--project`: `dotnet toolchain.cs -- test --integration --project Piv --smoke`.
- `--smoke` skips `Slow` and `RequiresUserPresence`; agents should not run touch/insert/remove tests unless a human explicitly coordinates hardware.
- Use `dotnet toolchain.cs -- --help` when arguments act strangely; `--help` and some options need the `--` separator.
Expand All @@ -30,6 +31,7 @@
- Platform interop belongs under `src/Core/src/PlatformInterop/{Windows,MacOS,Linux,Desktop}` with safe handles and `SdkPlatformInfo` platform selection.
- FIDO2 over USB primarily uses HID FIDO. SmartCard/CCID FIDO2 is supported over NFC and over USB when the FIDO2 AID is exposed; USB SmartCard FIDO2 requires firmware 5.8.0+.
- `TlvBuilder` and `DisposableTlvList` must be disposed.
- Listener/native retry loops must block, back off, exit, or throttle on every failure path; add no-hardware fault-injection tests for persistent native errors.

## Hardware And Integration Tests
- Integration tests require authorized YubiKey hardware. The shared test infrastructure reads `YubiKeyTests:AllowedSerialNumbers` from `appsettings.json`; an empty/missing allow list can hard-fail with `Environment.Exit(-1)`, and unauthorized devices are filtered out.
Expand All @@ -43,6 +45,7 @@
- Async byte data crossing awaits should use `Memory<byte>`, `ReadOnlyMemory<byte>`, or `IMemoryOwner<byte>`, not `Span<byte>`.
- Avoid `.ToArray()` and LINQ on byte data unless data must escape the current scope.
- Always zero PINs, PUKs, keys, SCP material, and secret-derived buffers with `CryptographicOperations.ZeroMemory()`.
- Classify YubiKey-returned data by semantics: device metadata/status does not need special zeroing; authentication material, token material, decrypted plaintext, and secret-derived output does.
- Use `CryptographicOperations.FixedTimeEquals` for secret-derived comparisons; do not use `SequenceEqual` on secrets.
- Never store a privately cloned sensitive `byte[]` in a struct; struct copies keep references you cannot reliably zero. Use a sealed disposable class for owned sensitive buffers.
- Logging is static via `YubiKitLogging.CreateLogger<T>()`; do not add SDK constructors that require `ILogger`/`ILoggerFactory`.
Expand All @@ -52,6 +55,7 @@
- Do not add validation-only tests that just prove `ArgumentNullException.ThrowIfNull` or framework type checks work.
- Do not add skipped placeholder tests. If behavior cannot be unit-tested, document the limitation and point to an integration path.
- Use fake connections, queued APDU responses, and byte/vector assertions for protocol behavior; use integration tests only for real hardware behavior.
- Runtime resilience tests should use fakes/seams and must not self-skip because PC/SC, HID, or YubiKey hardware is unavailable.

## Git And Release Notes
- The workflow file currently triggers on `yubikit` and `yubikit-applets`; verify the active plan/branch before assuming a PR base.
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ These are the always-loaded mandates. Each section ends with a JIT pointer to de

**Security:**
- ✅ ALWAYS zero sensitive data: `CryptographicOperations.ZeroMemory()`
- ✅ Classify byte data by semantic meaning, not by direction. YubiKey-returned device metadata/status (device info TLVs, firmware version, capabilities, form factor, public status) does not require special zeroing beyond normal ownership/disposal. YubiKey-returned authentication material, token material, decrypted plaintext, or secret-derived output does.
- ✅ ALWAYS dispose crypto objects: `using var aes = Aes.Create()`
- ✅ ALWAYS use `CryptographicOperations.FixedTimeEquals` for secret-derived comparisons
- ❌ NEVER log PINs, keys, or sensitive payloads
Expand Down
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@
<PackageVersion Include="Spectre.Console" Version="0.49.1" />
<PackageVersion Include="Spectre.Console.Cli" Version="0.49.1" />
<!-- Build Tools -->
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
<PackageVersion Include="Bullseye" Version="5.0.0" />
<PackageVersion Include="SimpleExec" Version="12.0.0" />
</ItemGroup>
</Project>
</Project>
241 changes: 241 additions & 0 deletions benchmarks/Yubico.YubiKit.PerformanceBenchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Exporters.Csv;
using BenchmarkDotNet.Exporters.Json;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
using Yubico.YubiKit.Core.Abstractions;
using Yubico.YubiKit.Core.Devices;
using Yubico.YubiKit.Core.Protocols.Fido.Hid;
using Yubico.YubiKit.Core.Protocols.SmartCard.Apdu;
using Yubico.YubiKit.Core.Sessions;
using Yubico.YubiKit.Core.Transports.Hid;
using Yubico.YubiKit.Core.Transports.SmartCard;
using Yubico.YubiKit.Management;

var config = YubiKitBenchmarkConfig.Create();
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);

internal sealed class YubiKitBenchmarkConfig : ManualConfig
{
private YubiKitBenchmarkConfig()
{
var runId = DateTimeOffset.UtcNow.ToString("yyyyMMdd-HHmmss");
ArtifactsPath = Path.Combine(FindRepoRoot(), "artifacts", "benchmarks", runId);

AddJob(Job.ShortRun
.WithRuntime(CoreRuntime.Core10_0)
.WithId("net10-short"));

AddColumnProvider(DefaultColumnProviders.Instance);
AddDiagnoser(MemoryDiagnoser.Default);
AddDiagnoser(ThreadingDiagnoser.Default);
AddDiagnoser(ExceptionDiagnoser.Default);
AddDiagnoser(new EventPipeProfiler(EventPipeProfile.CpuSampling));
AddExporter(MarkdownExporter.GitHub);
AddExporter(HtmlExporter.Default);
AddExporter(CsvExporter.Default);
AddExporter(CsvMeasurementsExporter.Default);
AddExporter(JsonExporter.Full);
AddExporter(RPlotExporter.Default);
AddValidator(JitOptimizationsValidator.FailOnError);
AddLogger(DefaultConfig.Instance.GetLoggers().ToArray());
}

public static IConfig Create() => new YubiKitBenchmarkConfig();

private static string FindRepoRoot()
{
var current = AppContext.BaseDirectory;
while (!string.IsNullOrEmpty(current))
{
if (Directory.Exists(Path.Combine(current, ".git")))
return current;

current = Directory.GetParent(current)?.FullName;
}

return Directory.GetCurrentDirectory();
}
}

public abstract class YubiKeyHardwareBenchmarkBase
{
protected IYubiKey Device { get; private set; } = null!;

protected void SetupDevice(ConnectionType requiredConnection)
{
Device = FindDevice(requiredConnection).GetAwaiter().GetResult();
}

[GlobalCleanup]
public void Cleanup() => YubiKeyManager.Shutdown();

private static async Task<IYubiKey> FindDevice(ConnectionType requiredConnection)
{
var devices = await YubiKeyManager.FindAllAsync(ConnectionType.All, forceRescan: true)
.ConfigureAwait(false);

return devices.FirstOrDefault(device => device.SupportsConnection(requiredConnection))
?? throw new InvalidOperationException(
$"No connected YubiKey exposes {requiredConnection}. Connect the YubiKey 5.8 device before running benchmarks.");
}
}

[MemoryDiagnoser]
[ThreadingDiagnoser]
[ExceptionDiagnoser]
public class YubiKeyDiscoveryBenchmarks
{
[GlobalSetup]
public void Setup()
{
_ = YubiKeyManager.FindAllAsync(ConnectionType.All, forceRescan: true)
.GetAwaiter()
.GetResult();
}

[GlobalCleanup]
public void Cleanup() => YubiKeyManager.Shutdown();

[Benchmark(Baseline = true)]
public async Task<int> CachedFindAll()
{
var devices = await YubiKeyManager.FindAllAsync(ConnectionType.All, forceRescan: false)
.ConfigureAwait(false);
return devices.Count;
}

[Benchmark]
public async Task<int> ForcedRescanFindAll()
{
var devices = await YubiKeyManager.FindAllAsync(ConnectionType.All, forceRescan: true)
.ConfigureAwait(false);
return devices.Count;
}

[Benchmark]
public async Task<int> ColdFindAll()
{
await YubiKeyManager.ShutdownAsync().ConfigureAwait(false);
var devices = await YubiKeyManager.FindAllAsync(ConnectionType.All, forceRescan: false)
.ConfigureAwait(false);
return devices.Count;
}
}

[MemoryDiagnoser]
[ThreadingDiagnoser]
[ExceptionDiagnoser]
public class SmartCardManagementBenchmarks : YubiKeyHardwareBenchmarkBase
{
[GlobalSetup]
public void Setup() => SetupDevice(ConnectionType.SmartCard);

[Benchmark(Baseline = true)]
public async Task<bool> ConnectSmartCard()
{
await using var connection = await Device.ConnectAsync<ISmartCardConnection>().ConfigureAwait(false);
return connection.SupportsExtendedApdu();
}

[Benchmark]
public async Task<int> SelectManagementOverSmartCard()
{
var connection = await Device.ConnectAsync<ISmartCardConnection>().ConfigureAwait(false);
using var protocol = PcscProtocolFactory<ISmartCardConnection>.Create().Create(connection);
var response = await protocol.SelectAsync(ApplicationIds.Management).ConfigureAwait(false);
return response.Length;
}

[Benchmark]
public async Task<int> GetDeviceInfoOverSmartCard()
{
await using var session = await Device.CreateManagementSessionAsync(
preferredConnection: ConnectionType.SmartCard)
.ConfigureAwait(false);

var info = await session.GetDeviceInfoAsync().ConfigureAwait(false);
return info.SerialNumber ?? 0;
}
}

[MemoryDiagnoser]
[ThreadingDiagnoser]
[ExceptionDiagnoser]
public class FidoHidManagementBenchmarks : YubiKeyHardwareBenchmarkBase
{
[GlobalSetup]
public void Setup() => SetupDevice(ConnectionType.HidFido);

[Benchmark(Baseline = true)]
public async Task<int> ConnectFidoHid()
{
await using var connection = await Device.ConnectAsync<IFidoHidConnection>().ConfigureAwait(false);
return connection.PacketSize;
}

[Benchmark]
public async Task<int> CreateManagementSessionOverFidoHid()
{
await using var session = await Device.CreateManagementSessionAsync(
preferredConnection: ConnectionType.HidFido)
.ConfigureAwait(false);

return session.FirmwareVersion.Major;
}

[Benchmark]
public async Task<int> GetDeviceInfoOverFidoHid()
{
await using var session = await Device.CreateManagementSessionAsync(
preferredConnection: ConnectionType.HidFido)
.ConfigureAwait(false);

var info = await session.GetDeviceInfoAsync().ConfigureAwait(false);
return info.SerialNumber ?? 0;
}
}

[MemoryDiagnoser]
[ThreadingDiagnoser]
[ExceptionDiagnoser]
public class OtpHidManagementBenchmarks : YubiKeyHardwareBenchmarkBase
{
[GlobalSetup]
public void Setup() => SetupDevice(ConnectionType.HidOtp);

[Benchmark(Baseline = true)]
public async Task<int> ConnectOtpHid()
{
await using var connection = await Device.ConnectAsync<IOtpHidConnection>().ConfigureAwait(false);
return connection.FeatureReportSize;
}

[Benchmark]
public async Task<int> CreateManagementSessionOverOtpHid()
{
await using var session = await Device.CreateManagementSessionAsync(
preferredConnection: ConnectionType.HidOtp)
.ConfigureAwait(false);

return session.FirmwareVersion.Major;
}

[Benchmark]
public async Task<int> GetDeviceInfoOverOtpHid()
{
await using var session = await Device.CreateManagementSessionAsync(
preferredConnection: ConnectionType.HidOtp)
.ConfigureAwait(false);

var info = await session.GetDeviceInfoAsync().ConfigureAwait(false);
return info.SerialNumber ?? 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>Yubico.YubiKit.PerformanceBenchmarks</RootNamespace>
<AssemblyName>Yubico.YubiKit.PerformanceBenchmarks</AssemblyName>
<IsPackable>false</IsPackable>
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../../src/Core/src/Yubico.YubiKit.Core.csproj" />
<ProjectReference Include="../../src/Management/src/Yubico.YubiKit.Management.csproj" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions docs/FIDO2-INTEGRATION-TEST-PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Successfully debugged and fixed the FIDO2 integration tests. All 42 tests now pa
## Fixes Applied

### 1. Linux HID Report ID Bug
**File:** `Yubico.YubiKit.Core/src/Hid/Linux/LinuxHidIOReportConnection.cs`
**File:** `Yubico.YubiKit.Core/src/Transports/Hid/Linux/LinuxHidIOReportConnection.cs`

**Problem:** Linux hidraw requires prepending a report ID byte (0x00) on writes, but the code was writing the 64-byte packet directly.

Expand Down Expand Up @@ -91,7 +91,7 @@ data.CopyTo(writeBuffer[1..]);

## Files Modified

1. `Yubico.YubiKit.Core/src/Hid/Linux/LinuxHidIOReportConnection.cs` - HID report ID fix
1. `Yubico.YubiKit.Core/src/Transports/Hid/Linux/LinuxHidIOReportConnection.cs` - HID report ID fix
2. `Yubico.YubiKit.Fido2/src/Pin/PinUvAuthProtocolV2.cs` - Token length fix
3. `Yubico.YubiKit.Fido2/src/Pin/PinUvAuthProtocolV1.cs` - Token length fix
4. `Yubico.YubiKit.Fido2/src/Credentials/PublicKeyCredentialTypes.cs` - Optional user fields
Expand Down
8 changes: 4 additions & 4 deletions docs/LOGGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ YubiKit uses the following log categories (class names):

| Category | Description |
|----------|-------------|
| `Yubico.YubiKit.Core.DeviceMonitorService` | Device arrival/removal events |
| `Yubico.YubiKit.Core.DeviceListenerService` | Background device cache updates |
| `Yubico.YubiKit.Core.DeviceRepositoryCached` | Device cache operations |
| `Yubico.YubiKit.Core.SmartCard.*` | Smart card/PCSC operations |
| `Yubico.YubiKit.Core.Devices.*` | Device discovery, metadata, and cache operations |
| `Yubico.YubiKit.Core.Transports.SmartCard.*` | Smart card/PC/SC transport operations |
| `Yubico.YubiKit.Core.Protocols.SmartCard.*` | APDU and SCP protocol operations |
| `Yubico.YubiKit.Core.Transports.Hid.*` | HID device and transport operations |
| `Yubico.YubiKit.Management.ManagementSession` | Management application commands |
| `Yubico.YubiKit.Piv.PivSession` | PIV application commands |
| `Yubico.YubiKit.Fido2.Fido2Session` | FIDO2 application commands |
Expand Down
Loading
Loading