Skip to content

Commit

Permalink
Fixed issues with HMAC secret processing
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelGrafnetter committed Aug 16, 2024
1 parent 096f44c commit cdb8228
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 77 deletions.
9 changes: 8 additions & 1 deletion Documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [1.0.3] - 2024-08-16

### Fixed

- Resolved issues with HMAC secret and linked device information processing.

## [1.0.2] - 2024-08-13

### Fixed
Expand All @@ -18,6 +24,7 @@ All notable changes to this project will be documented in this file. The format

- Initial version

[Unreleased]: https://github.com/MichaelGrafnetter/webauthn-interop/compare/v1.0.2...HEAD
[Unreleased]: https://github.com/MichaelGrafnetter/webauthn-interop/compare/v1.0.3...HEAD
[1.0.3]: https://github.com/MichaelGrafnetter/webauthn-interop/compare/v1.0.2...v1.0.3
[1.0.2]: https://github.com/MichaelGrafnetter/webauthn-interop/compare/v1.0...v1.0.2
[1.0]: https://github.com/MichaelGrafnetter/webauthn-interop/releases/tag/v1.0
4 changes: 2 additions & 2 deletions Src/DSInternals.Passkeys/DSInternals.Passkeys.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
RootModule = 'DSInternals.Passkeys.psm1'

# Version number of this module.
ModuleVersion = '1.0.2'
ModuleVersion = '1.0.3'

# Supported PSEditions
CompatiblePSEditions = @('Desktop','Core')
Expand Down Expand Up @@ -108,7 +108,7 @@ PrivateData = @{
IconUri = 'https://raw.githubusercontent.com/MichaelGrafnetter/DSInternals/master/Src/Icons/module_black.png'

# ReleaseNotes of this module
ReleaseNotes = 'The module is now properly digitally signed. Note that the API is currently in public preview (beta).'
ReleaseNotes = 'Fixed issues with HMAC secret processing. Note that the API is currently in public preview (beta).'

# Prerelease string of this module
# Prerelease = ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
<PackageId>DSInternals.Win32.WebAuthn.Adapter</PackageId>
<Product>WebAuthn Interop Assembly Adapter</Product>
<Title>WebAuthn Interop Assembly Adapter</Title>
<Version>1.0.2</Version>
<AssemblyVersion>1.0.2</AssemblyVersion>
<ProductVersion>1.0.2</ProductVersion>
<FileVersion>1.0.2</FileVersion>
<Version>1.0.3</Version>
<AssemblyVersion>1.0.3</AssemblyVersion>
<ProductVersion>1.0.3</ProductVersion>
<FileVersion>1.0.3</FileVersion>
<Description>Bridge between Fido2.Models and DSInternals.Win32.WebAuthn packages</Description>
<PackageReleaseNotes>- Initial release.
<PackageReleaseNotes>- Fixed issues with HMAC secret processing.
- Windows 10 1903 or newer is required.</PackageReleaseNotes>
</PropertyGroup>

Expand Down
10 changes: 5 additions & 5 deletions Src/DSInternals.Win32.WebAuthn/DSInternals.Win32.WebAuthn.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
<PackageId>DSInternals.Win32.WebAuthn</PackageId>
<Product>WebAuthn Interop Assembly</Product>
<Title>WebAuthn Interop Assembly</Title>
<Version>1.0.2</Version>
<AssemblyVersion>1.0.2</AssemblyVersion>
<ProductVersion>1.0.2</ProductVersion>
<FileVersion>1.0.2</FileVersion>
<Version>1.0.3</Version>
<AssemblyVersion>1.0.3</AssemblyVersion>
<ProductVersion>1.0.3</ProductVersion>
<FileVersion>1.0.3</FileVersion>
<Description>FIDO2 / W3C Web Authentication .NET Library for Windows Desktop and CLI Applications</Description>
<PackageReleaseNotes>-Initial release.
<PackageReleaseNotes>- Resolved issues with HMAC secret and linked device information processing.
- Windows 10 1903 or newer is required.
- A standalone package providing an adapter for data model defined in Fido2.Models is also available.</PackageReleaseNotes>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal class CredentialWithHmacSecretSaltIn : IDisposable
/// <summary>
/// PRF Values for above credential
/// </summary>
private HmacSecretSaltIn _hmacSecretSalt;
private IntPtr _hmacSecretSalt;

/// <summary>
/// Credential ID.
Expand All @@ -42,30 +42,50 @@ public byte[] CredentialId
}
}

/// <summary>
/// PRF Values for above credential
/// </summary>
public HmacSecretSaltIn HmacSecretSalt
{
set
{
_hmacSecretSalt?.Dispose();
_hmacSecretSalt = value;
if(value != null)
{
if (_hmacSecretSalt == IntPtr.Zero)
{
_hmacSecretSalt = Marshal.AllocHGlobal(Marshal.SizeOf<HmacSecretSaltIn>());
}

Marshal.StructureToPtr<HmacSecretSaltIn>(value, _hmacSecretSalt, false);
}
else
{
FreeHmacSecretSalt();
}
}
}

public CredentialWithHmacSecretSaltIn(byte[] credentialId, byte[] first, byte[] second)
public CredentialWithHmacSecretSaltIn(byte[] credentialId, HmacSecretSaltIn hmacSecretSalt)
{
// TODO: Validate that all parameters are present
this.CredentialId = credentialId;
this.HmacSecretSalt = new HmacSecretSaltIn(first, second);
// TODO: Use tuples here
this.HmacSecretSalt = hmacSecretSalt;
}

private void FreeHmacSecretSalt()
{
if (_hmacSecretSalt != IntPtr.Zero)
{
Marshal.FreeHGlobal(_hmacSecretSalt);
_hmacSecretSalt = IntPtr.Zero;
}
}

public void Dispose()
{
_credentialId?.Dispose();
_credentialId = null;

_hmacSecretSalt?.Dispose();
_hmacSecretSalt = null;
FreeHmacSecretSalt();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Net;
using System;
using System.Runtime.InteropServices;

namespace DSInternals.Win32.WebAuthn.Interop
Expand Down Expand Up @@ -79,13 +79,13 @@ internal sealed class Assertion
/// A salt used to generate the HMAC secret.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_ASSERTION_VERSION_3.</remarks>
public HmacSecretSaltOut HmacSecret { get; private set; }
private IntPtr _hmacSecret;

/// <summary>
/// The transport that was used.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_ASSERTION_VERSION_4.</remarks>
public TransportContext UsedTransport { get; private set; }
public AuthenticatorTransport UsedTransport { get; private set; }

/// <remarks>This field has been added in WEBAUTHN_ASSERTION_VERSION_5.</remarks>
private int _unsignedExtensionOutputsLength;
Expand Down Expand Up @@ -118,5 +118,22 @@ internal sealed class Assertion
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_ASSERTION_VERSION_5.</remarks>
public byte[] UnsignedExtensionOutputs => _unsignedExtensionOutputs?.Read(_unsignedExtensionOutputsLength);

/// <summary>
/// A salt used to generate the HMAC secret.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_ASSERTION_VERSION_3.</remarks>
public HmacSecretSaltOut HmacSecret
{
get
{
if (_hmacSecret == IntPtr.Zero)
{
return null;
}

return Marshal.PtrToStructure<HmacSecretSaltOut>(_hmacSecret);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal class AuthenticatorGetAssertionOptions : IDisposable
/// PRF values which will be converted into HMAC-SECRET values according to WebAuthn Specification.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6.</remarks>
private HmacSecretSaltValuesIn _hmacSecretSaltValues;
private IntPtr _hmacSecretSaltValues;

/// <summary>
/// Indicates whether the browser is in private mode. Defaulting to false.
Expand All @@ -109,7 +109,7 @@ internal class AuthenticatorGetAssertionOptions : IDisposable
/// Linked Device Connection Info.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7.</remarks>
public HybridStorageLinkedData LinkedDevice { get; set; }
private IntPtr _linkedDevice { get; set; }

/// <summary>
/// Allowlist MUST contain 1 credential applicable for Hybrid transport.
Expand Down Expand Up @@ -169,11 +169,7 @@ public Guid? CancellationId
}
else
{
if (_cancellationId != IntPtr.Zero)
{
Marshal.FreeHGlobal(_cancellationId);
_cancellationId = IntPtr.Zero;
}
FreeCancellationId();
}
}
}
Expand Down Expand Up @@ -208,11 +204,7 @@ public CredentialList AllowCredentialsEx
}
else
{
if (_allowCredentialList != IntPtr.Zero)
{
Marshal.FreeHGlobal(_allowCredentialList);
_allowCredentialList = IntPtr.Zero;
}
FreeAllowCredentialList();
}
}
}
Expand Down Expand Up @@ -265,23 +257,65 @@ public byte[] LargeBlob
// Get rid of any previous blob first
_largeBlob?.Dispose();

// Now replace the previous value with a new one
// Now replace the previous value with the new one
_largeBlobLength = value?.Length ?? 0;
_largeBlob = new ByteArrayIn(value);
}
}

/// <summary>
/// PRF values which will be converted into HMAC-SECRET values according to WebAuthn Specification.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6.</remarks>

public HmacSecretSaltValuesIn HmacSecretSaltValues
{
set
{
_hmacSecretSaltValues?.Dispose();
_hmacSecretSaltValues = value;
if (value?.HasGlobalHmacSalt ?? false)
{
if (_hmacSecretSaltValues == IntPtr.Zero)
{
_hmacSecretSaltValues = Marshal.AllocHGlobal(Marshal.SizeOf<HmacSecretSaltValuesIn>());
}

Marshal.StructureToPtr<HmacSecretSaltValuesIn>(value, _hmacSecretSaltValues, false);

// Set flag
_flags |= AssertionOptionsFlags.AuthenticatorHmacSecretValues;
}
else
{
FreeHmacSecretSaltValues();

// Unset flag
_flags &= ~AssertionOptionsFlags.AuthenticatorHmacSecretValues;
}
}
}

/// <summary>
/// Linked Device Connection Info.
/// </summary>
/// <remarks>This field has been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7.</remarks>

public HybridStorageLinkedData LinkedDevice
{
set
{
if (value != null)
{
if (_linkedDevice == IntPtr.Zero)
{
_linkedDevice = Marshal.AllocHGlobal(Marshal.SizeOf<HybridStorageLinkedData>());
}

// Set or unset the corresponding flag
_flags = value != null ?
_flags | AssertionOptionsFlags.AuthenticatorHmacSecretValues :
_flags & ~AssertionOptionsFlags.AuthenticatorHmacSecretValues;
Marshal.StructureToPtr<HybridStorageLinkedData>(value, _linkedDevice, false);
}
else
{
FreeLinkedDevice();
}
}
}

Expand Down Expand Up @@ -320,21 +354,50 @@ public void Dispose()
_jsonExt?.Dispose();
_jsonExt = null;

if (_allowCredentialList != IntPtr.Zero)
{
Marshal.FreeHGlobal(_allowCredentialList);
_allowCredentialList = IntPtr.Zero;
}
FreeAllowCredentialList();

_hmacSecretSaltValues?.Dispose();
_hmacSecretSaltValues = null;
FreeHmacSecretSaltValues();

FreeLinkedDevice();

if (_isU2fAppIdUsed != IntPtr.Zero)
{
Marshal.FreeHGlobal(_isU2fAppIdUsed);
_isU2fAppIdUsed = IntPtr.Zero;
}

FreeCancellationId();
}

private void FreeLinkedDevice()
{
if (_linkedDevice != IntPtr.Zero)
{
Marshal.FreeHGlobal(_linkedDevice);
_linkedDevice = IntPtr.Zero;
}
}

private void FreeHmacSecretSaltValues()
{
if (_hmacSecretSaltValues != IntPtr.Zero)
{
Marshal.FreeHGlobal(_hmacSecretSaltValues);
_hmacSecretSaltValues = IntPtr.Zero;
}
}

private void FreeAllowCredentialList()
{
if (_allowCredentialList != IntPtr.Zero)
{
Marshal.FreeHGlobal(_allowCredentialList);
_allowCredentialList = IntPtr.Zero;
}
}

private void FreeCancellationId()
{
if (_cancellationId != IntPtr.Zero)
{
Marshal.FreeHGlobal(_cancellationId);
Expand Down
Loading

0 comments on commit cdb8228

Please sign in to comment.