Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,21 @@ public ConfigureChallengeResponse SetAllowUpdate(bool setConfig = true) =>
/// <returns>The current <see cref="ConfigureChallengeResponse"/> instance.</returns>
public ConfigureChallengeResponse UseButton(bool setConfig = true) =>
Settings.UseButtonTrigger(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberApiVisible(bool)"/>
/// <returns>The current <see cref="ConfigureChallengeResponse"/> instance.</returns>
public ConfigureChallengeResponse SetSerialNumberApiVisible(bool setConfig = true) =>
Settings.SetSerialNumberApiVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberButtonVisible(bool)"/>
/// <returns>The current <see cref="ConfigureChallengeResponse"/> instance.</returns>
public ConfigureChallengeResponse SetSerialNumberButtonVisible(bool setConfig = true) =>
Settings.SetSerialNumberButtonVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberUsbVisible(bool)"/>
/// <returns>The current <see cref="ConfigureChallengeResponse"/> instance.</returns>
public ConfigureChallengeResponse SetSerialNumberUsbVisible(bool setConfig = true) =>
Settings.SetSerialNumberUsbVisible(setConfig);
#endregion
#endregion
}
Expand Down
15 changes: 15 additions & 0 deletions Yubico.YubiKey/src/Yubico/YubiKey/Otp/Operations/ConfigureHotp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,21 @@ public ConfigureHotp UseFastTrigger(bool setConfig = true) =>
/// <returns>The current <see cref="ConfigureHotp"/> instance.</returns>
public ConfigureHotp SendReferenceString(bool setConfig = true) =>
Settings.SendReferenceString(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberApiVisible(bool)"/>
/// <returns>The current <see cref="ConfigureHotp"/> instance.</returns>
public ConfigureHotp SetSerialNumberApiVisible(bool setConfig = true) =>
Settings.SetSerialNumberApiVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberButtonVisible(bool)"/>
/// <returns>The current <see cref="ConfigureHotp"/> instance.</returns>
public ConfigureHotp SetSerialNumberButtonVisible(bool setConfig = true) =>
Settings.SetSerialNumberButtonVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberUsbVisible(bool)"/>
/// <returns>The current <see cref="ConfigureHotp"/> instance.</returns>
public ConfigureHotp SetSerialNumberUsbVisible(bool setConfig = true) =>
Settings.SetSerialNumberUsbVisible(setConfig);
#endregion
#endregion

Expand Down
17 changes: 17 additions & 0 deletions Yubico.YubiKey/src/Yubico/YubiKey/Otp/Operations/ConfigureNdef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,22 @@ public ConfigureNdef WithLanguage(string languageCode)
_languageCode = languageCode;
return this;
}

#region Flags to Relay
/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberApiVisible(bool)"/>
/// <returns>The current <see cref="ConfigureNdef"/> instance.</returns>
public ConfigureNdef SetSerialNumberApiVisible(bool setConfig = true) =>
Settings.SetSerialNumberApiVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberButtonVisible(bool)"/>
/// <returns>The current <see cref="ConfigureNdef"/> instance.</returns>
public ConfigureNdef SetSerialNumberButtonVisible(bool setConfig = true) =>
Settings.SetSerialNumberButtonVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberUsbVisible(bool)"/>
/// <returns>The current <see cref="ConfigureNdef"/> instance.</returns>
public ConfigureNdef SetSerialNumberUsbVisible(bool setConfig = true) =>
Settings.SetSerialNumberUsbVisible(setConfig);
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,21 @@ public ConfigureStaticPassword SetAllowUpdate(bool setConfig = true) =>
/// <inheritdoc cref="OtpSettings{T}.AllowManualUpdate(bool)"/>
public ConfigureStaticPassword AllowManualUpdate(bool setConfig = true) =>
Settings.AllowManualUpdate(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberApiVisible(bool)"/>
/// <returns>The current <see cref="ConfigureStaticPassword"/> instance.</returns>
public ConfigureStaticPassword SetSerialNumberApiVisible(bool setConfig = true) =>
Settings.SetSerialNumberApiVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberButtonVisible(bool)"/>
/// <returns>The current <see cref="ConfigureStaticPassword"/> instance.</returns>
public ConfigureStaticPassword SetSerialNumberButtonVisible(bool setConfig = true) =>
Settings.SetSerialNumberButtonVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberUsbVisible(bool)"/>
/// <returns>The current <see cref="ConfigureStaticPassword"/> instance.</returns>
public ConfigureStaticPassword SetSerialNumberUsbVisible(bool setConfig = true) =>
Settings.SetSerialNumberUsbVisible(setConfig);
#endregion
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,21 @@ public ConfigureYubicoOtp SetAllowUpdate(bool setConfig = true) =>
/// <returns>The current <see cref="ConfigureYubicoOtp"/> instance.</returns>
public ConfigureYubicoOtp SendReferenceString(bool setConfig = true) =>
Settings.SendReferenceString(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberApiVisible(bool)"/>
/// <returns>The current <see cref="ConfigureYubicoOtp"/> instance.</returns>
public ConfigureYubicoOtp SetSerialNumberApiVisible(bool setConfig = true) =>
Settings.SetSerialNumberApiVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberButtonVisible(bool)"/>
/// <returns>The current <see cref="ConfigureYubicoOtp"/> instance.</returns>
public ConfigureYubicoOtp SetSerialNumberButtonVisible(bool setConfig = true) =>
Settings.SetSerialNumberButtonVisible(setConfig);

/// <inheritdoc cref="OtpSettings{T}.SetSerialNumberUsbVisible(bool)"/>
/// <returns>The current <see cref="ConfigureYubicoOtp"/> instance.</returns>
public ConfigureYubicoOtp SetSerialNumberUsbVisible(bool setConfig = true) =>
Settings.SetSerialNumberUsbVisible(setConfig);
#endregion
#endregion
}
Expand Down
188 changes: 188 additions & 0 deletions Yubico.YubiKey/tests/integration/Yubico/YubiKey/Otp/OtpSessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,193 @@ public void ConfigureStaticPassword_WithWScp_Succeeds(StandardTestDevice testDev
configObj = configObj.GeneratePassword(generatedPassword);
configObj.Execute();
}

[Trait(TraitTypes.Category, TestCategories.Simple)]
[SkippableTheory(typeof(DeviceNotFoundException))]
[InlineData(StandardTestDevice.Fw5)]
[InlineData(StandardTestDevice.Fw5Fips)]
public void ConfigureYubicoOtp_WithSerialNumberVisibility_Succeeds(StandardTestDevice testDeviceType)
{
IYubiKeyDevice testDevice = IntegrationTestDeviceEnumeration.GetTestDevice(testDeviceType);

using (var otpSession = new OtpSession(testDevice))
{
if (otpSession.IsLongPressConfigured)
{
otpSession.DeleteSlot(Slot.LongPress);
}
}

using (var otpSession = new OtpSession(testDevice))
{
Memory<byte> privateId = new byte[ConfigureYubicoOtp.PrivateIdentifierSize];
Memory<byte> aesKey = new byte[ConfigureYubicoOtp.KeySize];

otpSession.ConfigureYubicoOtp(Slot.LongPress)
.SetSerialNumberApiVisible()
.SetSerialNumberButtonVisible()
.SetSerialNumberUsbVisible()
.UseSerialNumberAsPublicId()
.GeneratePrivateId(privateId)
.GenerateKey(aesKey)
.Execute();
}

using (var otpSession = new OtpSession(testDevice))
{
Assert.True(otpSession.IsLongPressConfigured, "Slot should be configured after Execute()");
}
}

[Trait(TraitTypes.Category, TestCategories.Simple)]
[SkippableTheory(typeof(DeviceNotFoundException))]
[InlineData(StandardTestDevice.Fw5)]
[InlineData(StandardTestDevice.Fw5Fips)]
public void ConfigureStaticPassword_WithSerialNumberVisibility_Succeeds(StandardTestDevice testDeviceType)
{
IYubiKeyDevice testDevice = IntegrationTestDeviceEnumeration.GetTestDevice(testDeviceType);

using (var otpSession = new OtpSession(testDevice))
{
if (otpSession.IsLongPressConfigured)
{
otpSession.DeleteSlot(Slot.LongPress);
}
}

using (var otpSession = new OtpSession(testDevice))
{
Memory<char> generatedPassword = new char[16];

otpSession.ConfigureStaticPassword(Slot.LongPress)
.WithKeyboard(KeyboardLayout.en_US)
.SetSerialNumberApiVisible()
.SetSerialNumberButtonVisible()
.SetSerialNumberUsbVisible()
.GeneratePassword(generatedPassword)
.Execute();
}

using (var otpSession = new OtpSession(testDevice))
{
Assert.True(otpSession.IsLongPressConfigured, "Slot should be configured after Execute()");
}
}

[Trait(TraitTypes.Category, TestCategories.Simple)]
[SkippableTheory(typeof(DeviceNotFoundException))]
[InlineData(StandardTestDevice.Fw5)]
[InlineData(StandardTestDevice.Fw5Fips)]
public void ConfigureHotp_WithSerialNumberVisibility_Succeeds(StandardTestDevice testDeviceType)
{
IYubiKeyDevice testDevice = IntegrationTestDeviceEnumeration.GetTestDevice(testDeviceType);

using (var otpSession = new OtpSession(testDevice))
{
if (otpSession.IsLongPressConfigured)
{
otpSession.DeleteSlot(Slot.LongPress);
}
}

using (var otpSession = new OtpSession(testDevice))
{
Memory<byte> hmacKey = new byte[ConfigureHotp.HmacKeySize];

otpSession.ConfigureHotp(Slot.LongPress)
.SetSerialNumberApiVisible()
.SetSerialNumberButtonVisible()
.SetSerialNumberUsbVisible()
.GenerateKey(hmacKey)
.Execute();
}

using (var otpSession = new OtpSession(testDevice))
{
Assert.True(otpSession.IsLongPressConfigured, "Slot should be configured after Execute()");
}
}

[Trait(TraitTypes.Category, TestCategories.Simple)]
[SkippableTheory(typeof(DeviceNotFoundException))]
[InlineData(StandardTestDevice.Fw5)]
[InlineData(StandardTestDevice.Fw5Fips)]
public void ConfigureChallengeResponse_WithSerialNumberVisibility_Succeeds(StandardTestDevice testDeviceType)
{
IYubiKeyDevice testDevice = IntegrationTestDeviceEnumeration.GetTestDevice(testDeviceType);

using (var otpSession = new OtpSession(testDevice))
{
if (otpSession.IsLongPressConfigured)
{
otpSession.DeleteSlot(Slot.LongPress);
}
}

using (var otpSession = new OtpSession(testDevice))
{
Memory<byte> hmacKey = new byte[ConfigureChallengeResponse.HmacSha1KeySize];

otpSession.ConfigureChallengeResponse(Slot.LongPress)
.SetSerialNumberApiVisible()
.SetSerialNumberButtonVisible()
.SetSerialNumberUsbVisible()
.UseHmacSha1()
.GenerateKey(hmacKey)
.Execute();
}

using (var otpSession = new OtpSession(testDevice))
{
Assert.True(otpSession.IsLongPressConfigured, "Slot should be configured after Execute()");
}
}

[Trait(TraitTypes.Category, TestCategories.Simple)]
[SkippableTheory(typeof(DeviceNotFoundException))]
[InlineData(StandardTestDevice.Fw5)]
[InlineData(StandardTestDevice.Fw5Fips)]
public void ConfigureNdef_WithSerialNumberVisibility_Succeeds(StandardTestDevice testDeviceType)
{
IYubiKeyDevice testDevice = IntegrationTestDeviceEnumeration.GetTestDevice(testDeviceType);

using (var otpSession = new OtpSession(testDevice))
{
if (otpSession.IsLongPressConfigured)
{
otpSession.DeleteSlot(Slot.LongPress);
}
}

// NDEF requires an already configured slot - configure with HOTP first
using (var otpSession = new OtpSession(testDevice))
{
Memory<byte> hmacKey = new byte[ConfigureHotp.HmacKeySize];

otpSession.ConfigureHotp(Slot.LongPress)
.GenerateKey(hmacKey)
.Execute();
}

// Configure NDEF to use that slot with serial number visibility settings
// Note: NDEF configuration does not alter slot state, it only sets NDEF to use the slot.
// Verification would require NFC hardware to read the NDEF tag, so we verify
// that Execute() succeeds without throwing an exception.
using (var otpSession = new OtpSession(testDevice))
{
otpSession.ConfigureNdef(Slot.LongPress)
.SetSerialNumberApiVisible()
.SetSerialNumberButtonVisible()
.SetSerialNumberUsbVisible()
.AsUri(new Uri("https://example.com"))
.Execute();
}

// Verify the slot is still configured (NDEF doesn't change slot configuration)
using (var otpSession = new OtpSession(testDevice))
{
Assert.True(otpSession.IsLongPressConfigured, "Slot should remain configured");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,27 @@ public void TestSpecifiedAndGeneratedKey()
Assert.Equal(ExceptionMessages.CantSpecifyKeyAndGenerate, ex.Message);
}

[Fact]
public void TestSetSerialNumberApiVisible_ReturnsInstance()
{
ConfigureYubicoOtp result = _op.SetSerialNumberApiVisible(true);
Assert.Same(_op, result);
}

[Fact]
public void TestSetSerialNumberButtonVisible_ReturnsInstance()
{
ConfigureYubicoOtp result = _op.SetSerialNumberButtonVisible(true);
Assert.Same(_op, result);
}

[Fact]
public void TestSetSerialNumberUsbVisible_ReturnsInstance()
{
ConfigureYubicoOtp result = _op.SetSerialNumberUsbVisible(true);
Assert.Same(_op, result);
}

protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
Expand Down
26 changes: 26 additions & 0 deletions work/feature-764.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Feature 764

## User Story: I should be able to set serial number visibility when configuring an OTP slot

## Description:
This seems to have been a design oversight:

In the Configure* operation classes in the OTP.Operations namespace, one should be able to set the serial number visibility (i.e. API, USB, and Button visible). But the methods for adding these flags are not present.

See Class (ConfigureYubicoOtp)[https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html] for an example of a configuration missing these methods.

See Class (UpdateSlot)[https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html] to see that they are present for updating a slot.

## How it's implemented in the corresponding Java SDK
See these resources to learn how it was effectively implemented in the Java SDK
https://github.com/Yubico/yubikit-android/tree/main/oath
https://github.com/Yubico/yubikit-android/tree/main/yubiotp

## Definition of Done
- Adjusted implementation of the Configure* (e.g. ConfigureYubicoOtp) operation classes that supports setting the serial number visibility, as it is for UpdateSlot
- Simple Unit Tests. Append tests to existing relevant test classes
- Simple integration test (will be tested manually by user in PR)
- The implementation should follow, where applicable, the implementation in Java
- No breaking changes are allowed
- Follow .editorConfig code formatting

Loading