Skip to content

Commit 3f4f29a

Browse files
committed
Add tests for CTAP 2.2/2.3 EncCredStoreState and AuthenticatorConfigCommands
This commit adds comprehensive test coverage for the new CTAP 2.2/2.3 properties and methods: Unit Tests (Fido2InfoTests.cs): - Updated Decode_AuthenticatorInfo() to verify both new properties - Added GetSampleEncoded() entries for EncCredStoreState (key 0x1E) and AuthenticatorConfigCommands (key 0x1F) - Added Decode_AuthenticatorConfigCommands_Correct() to validate parsing of authenticator config command list - Added Decode_NoAuthenticatorConfigCommands_Null() to verify null handling when field is absent - Added Decode_EncCredStoreState_Correct() to validate parsing of encrypted credential store state - Added Decode_NoEncCredStoreState_Null() to verify null handling when field is absent - Added CompareIntLists() helper method for integer list comparison Integration Tests (Fido2Tests.cs): - Added AuthenticatorInfo_GetCredStoreState_BothRuns_Returns_SameCredStoreState() test that mirrors the GetIdentifier test pattern - Verifies GetCredStoreState() decrypts credential store state correctly using persistent PIN/UV auth token - Tests that credential store state remains consistent across multiple sessions with the same persistent token - Requires YubiKey firmware 5.8.0+ and physical device for execution The tests follow the same patterns as existing EncIdentifier tests, ensuring consistency with the codebase testing standards.
1 parent 2e96bf2 commit 3f4f29a

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/Fido2Tests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,41 @@ public void AuthenticatorInfo_GetIdentifier_BothRuns_Returns_SameIdentifier()
7272
Assert.True(identifier1.Value.Span.SequenceEqual(identifier2.Value.Span));
7373
}
7474

75+
[SkippableFact(typeof(DeviceNotFoundException))]
76+
public void AuthenticatorInfo_GetCredStoreState_BothRuns_Returns_SameCredStoreState()
77+
{
78+
ReadOnlyMemory<byte>? credStoreState1;
79+
ReadOnlyMemory<byte>? credStoreState2;
80+
ReadOnlyMemory<byte>? ppuat;
81+
82+
// First run
83+
using (var session = GetSession(minFw: FirmwareVersion.V5_8_0))
84+
{
85+
session.VerifyPin(PinUvAuthTokenPermissions.PersistentCredentialManagementReadOnly);
86+
Assert.NotNull(session.AuthTokenPersistent);
87+
88+
ppuat = session.AuthTokenPersistent.Value.ToArray();
89+
credStoreState1 = session.AuthenticatorInfo.GetCredStoreState(ppuat.Value);
90+
91+
Assert.NotNull(credStoreState1);
92+
Assert.NotEmpty(credStoreState1.Value.ToArray());
93+
}
94+
95+
// Second run, reuse ppuat
96+
using (var session = GetSession(persistentPinUvAuthToken: ppuat.Value))
97+
{
98+
session.VerifyPin(PinUvAuthTokenPermissions.PersistentCredentialManagementReadOnly);
99+
Assert.NotNull(session.AuthTokenPersistent);
100+
101+
credStoreState2 = session.AuthenticatorInfo.GetCredStoreState(ppuat.Value);
102+
103+
Assert.NotNull(credStoreState2);
104+
Assert.NotEmpty(credStoreState2.Value.ToArray());
105+
}
106+
107+
Assert.True(credStoreState1.Value.Span.SequenceEqual(credStoreState2.Value.Span));
108+
}
109+
75110
#endregion
76111

77112
#region CredentialManagement

Yubico.YubiKey/tests/unit/Yubico/YubiKey/Fido2/Fido2InfoTests.cs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public void Decode_AuthenticatorInfo()
3131
var fido2Info = new AuthenticatorInfo(GetSampleEncoded());
3232
Assert.NotNull(fido2Info);
3333
Assert.NotNull(fido2Info.EncIdentifier);
34+
Assert.NotNull(fido2Info.EncCredStoreState);
35+
Assert.NotNull(fido2Info.AuthenticatorConfigCommands);
3436
}
3537

3638
[Fact]
@@ -625,6 +627,87 @@ public void Extensions_IsSupported_Correct(
625627
Assert.Equal(expectedValue, isSupported);
626628
}
627629

630+
[Fact]
631+
public void Decode_AuthenticatorConfigCommands_Correct()
632+
{
633+
int[] correctInts = new int[] { 1, 2, 3 };
634+
635+
byte[] encodedData = GetSampleEncoded();
636+
637+
var fido2Info = new AuthenticatorInfo(encodedData);
638+
Assert.NotNull(fido2Info.AuthenticatorConfigCommands);
639+
if (fido2Info.AuthenticatorConfigCommands is null)
640+
{
641+
return;
642+
}
643+
644+
bool isValid = CompareIntLists(correctInts, fido2Info.AuthenticatorConfigCommands);
645+
646+
Assert.True(isValid);
647+
}
648+
649+
[Fact]
650+
public void Decode_NoAuthenticatorConfigCommands_Null()
651+
{
652+
byte[] encodedData = GetMinimumEncoded();
653+
654+
var fido2Info = new AuthenticatorInfo(encodedData);
655+
Assert.Null(fido2Info.AuthenticatorConfigCommands);
656+
}
657+
658+
[Fact]
659+
public void Decode_EncCredStoreState_Correct()
660+
{
661+
byte[] correctValue = "encCredStoreStateByte"u8.ToArray();
662+
663+
byte[] encodedData = GetSampleEncoded();
664+
665+
var fido2Info = new AuthenticatorInfo(encodedData);
666+
Assert.NotNull(fido2Info.EncCredStoreState);
667+
if (fido2Info.EncCredStoreState is null)
668+
{
669+
return;
670+
}
671+
672+
bool isValid = MemoryExtensions.SequenceEqual(correctValue, fido2Info.EncCredStoreState.Value.Span);
673+
674+
Assert.True(isValid);
675+
}
676+
677+
[Fact]
678+
public void Decode_NoEncCredStoreState_Null()
679+
{
680+
byte[] encodedData = GetMinimumEncoded();
681+
682+
var fido2Info = new AuthenticatorInfo(encodedData);
683+
Assert.Null(fido2Info.EncCredStoreState);
684+
}
685+
686+
private static bool CompareIntLists(
687+
int[] correctInts,
688+
IReadOnlyList<int>? candidate)
689+
{
690+
if (candidate is null)
691+
{
692+
return false;
693+
}
694+
695+
if (correctInts.Length != candidate.Count)
696+
{
697+
return false;
698+
}
699+
700+
for (int index = 0; index < correctInts.Length; index++)
701+
{
702+
if (!candidate.Contains(correctInts[index]))
703+
{
704+
return false;
705+
}
706+
}
707+
708+
return true;
709+
}
710+
628711
private static bool CompareLongLists(
629712
long[] correctInts,
630713
IReadOnlyList<long>? candidate)
@@ -744,7 +827,9 @@ internal static byte[] GetSampleEncoded()
744827
.Entry(26, new[] { AuthenticatorTransports.Usb }) // TransportsForReset
745828
.Entry(27, true) // PinComplexityPolicy
746829
.Entry(28, "Example.com"u8.ToArray()) // PinComplexityPolicyUrl
747-
.Entry(29, 33); // MaxPinLength
830+
.Entry(29, 33) // MaxPinLength
831+
.Entry(30, "encCredStoreStateByte"u8.ToArray()) // EncCredStoreState
832+
.Entry(31, new[] { 1, 2, 3 }); // AuthenticatorConfigCommands
748833

749834
var encoded = cborMapWriter.Encode();
750835
return encoded;

0 commit comments

Comments
 (0)