diff --git a/Src/Fido2.Ctap2/Commands/AuthenticatorClientPinCommand.cs b/Src/Fido2.Ctap2/Commands/AuthenticatorClientPinCommand.cs index ea1d2e60..c4a34547 100644 --- a/Src/Fido2.Ctap2/Commands/AuthenticatorClientPinCommand.cs +++ b/Src/Fido2.Ctap2/Commands/AuthenticatorClientPinCommand.cs @@ -3,36 +3,25 @@ namespace Fido2NetLib.Ctap2; -public sealed class AuthenticatorClientPinCommand : CtapCommand +public sealed class AuthenticatorClientPinCommand( + uint pinProtocol, + AuthenticatorClientPinSubCommand subCommand, + CredentialPublicKey? keyAgreement = null, + byte[]? pinAuth = null, + byte[]? newPinEnc = null, + byte[]? pinHashEnc = null) : CtapCommand { - public AuthenticatorClientPinCommand( - uint pinProtocol, - AuthenticatorClientPinSubCommand subCommand, - CredentialPublicKey? keyAgreement = null, - byte[]? pinAuth = null, - byte[]? newPinEnc = null, - byte[]? pinHashEnc = null) - { - - PinProtocol = pinProtocol; - SubCommand = subCommand; - KeyAgreement = keyAgreement; - PinAuth = pinAuth; - NewPinEnc = newPinEnc; - PinHashEnc = pinHashEnc; - } - /// /// Required PIN protocol version chosen by the client. /// [CborMember(0x01)] - public uint PinProtocol { get; } + public uint PinProtocol { get; } = pinProtocol; /// /// The authenticator Client PIN sub command currently being requested. /// [CborMember(0x02)] - public AuthenticatorClientPinSubCommand SubCommand { get; } + public AuthenticatorClientPinSubCommand SubCommand { get; } = subCommand; /// /// Public key of platformKeyAgreementKey. @@ -40,25 +29,25 @@ public AuthenticatorClientPinCommand( /// The "alg" parameter MUST contain a COSEAlgorithmIdentifier value. /// [CborMember(0x03)] - public CredentialPublicKey? KeyAgreement { get; } + public CredentialPublicKey? KeyAgreement { get; } = keyAgreement; /// /// First 16 bytes of HMAC-SHA-256 of encrypted contents using sharedSecret. /// [CborMember(0x04)] - public byte[]? PinAuth { get; } + public byte[]? PinAuth { get; } = pinAuth; /// /// Encrypted new PIN using sharedSecret. /// [CborMember(0x05)] - public byte[]? NewPinEnc { get; } + public byte[]? NewPinEnc { get; } = newPinEnc; /// /// Encrypted first 16 bytes of SHA-256 of PIN using sharedSecret. /// [CborMember(0x06)] - public byte[]? PinHashEnc { get; } + public byte[]? PinHashEnc { get; } = pinHashEnc; public override CtapCommandType Type => CtapCommandType.AuthenticatorClientPin; diff --git a/Src/Fido2.Models/CredentialCreateOptions.cs b/Src/Fido2.Models/CredentialCreateOptions.cs index 9c674993..bc55d159 100644 --- a/Src/Fido2.Models/CredentialCreateOptions.cs +++ b/Src/Fido2.Models/CredentialCreateOptions.cs @@ -59,7 +59,7 @@ public sealed class CredentialCreateOptions : Fido2ResponseBase /// This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator.The client is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter. /// [JsonPropertyName("excludeCredentials")] - public IReadOnlyList ExcludeCredentials { get; set; } = Array.Empty(); + public IReadOnlyList ExcludeCredentials { get; set; } = []; /// /// This OPTIONAL member contains additional parameters requesting additional processing by the client and authenticator. For example, if transaction confirmation is sought from the user, then the prompt string might be included as an extension. @@ -85,8 +85,8 @@ public static CredentialCreateOptions Create( Rp = new PublicKeyCredentialRpEntity(config.ServerDomain, config.ServerName, config.ServerIcon), Timeout = config.Timeout, User = user, - PubKeyCredParams = new List(10) - { + PubKeyCredParams = + [ // Add additional as appropriate PubKeyCredParam.Ed25519, PubKeyCredParam.ES256, @@ -98,7 +98,7 @@ public static CredentialCreateOptions Create( PubKeyCredParam.ES512, PubKeyCredParam.RS512, PubKeyCredParam.PS512, - }, + ], AuthenticatorSelection = authenticatorSelection, Attestation = attestationConveyancePreference, ExcludeCredentials = excludeCredentials, @@ -119,29 +119,25 @@ public static CredentialCreateOptions FromJson(string json) #nullable enable -public sealed class PubKeyCredParam +/// +/// Constructs a PubKeyCredParam instance +/// +[method: JsonConstructor] +public sealed class PubKeyCredParam( + COSE.Algorithm alg, + PublicKeyCredentialType type = PublicKeyCredentialType.PublicKey) { - /// - /// Constructs a PubKeyCredParam instance - /// - [JsonConstructor] - public PubKeyCredParam(COSE.Algorithm alg, PublicKeyCredentialType type = PublicKeyCredentialType.PublicKey) - { - Type = type; - Alg = alg; - } - /// /// The type member specifies the type of credential to be created. /// [JsonPropertyName("type")] - public PublicKeyCredentialType Type { get; } + public PublicKeyCredentialType Type { get; } = type; /// /// The alg member specifies the cryptographic signature algorithm with which the newly generated credential will be used, and thus also the type of asymmetric key pair to be generated, e.g., RSA or Elliptic Curve. /// [JsonPropertyName("alg")] - public COSE.Algorithm Alg { get; } + public COSE.Algorithm Alg { get; } = alg; public static readonly PubKeyCredParam ES256 = new(COSE.Algorithm.ES256); // External authenticators support the ES256 algorithm public static readonly PubKeyCredParam ES384 = new(COSE.Algorithm.ES384); @@ -158,31 +154,28 @@ public PubKeyCredParam(COSE.Algorithm alg, PublicKeyCredentialType type = Public /// /// PublicKeyCredentialRpEntity /// -public sealed class PublicKeyCredentialRpEntity +public sealed class PublicKeyCredentialRpEntity( + string id, + string name, + string? icon = null) { - public PublicKeyCredentialRpEntity(string id, string name, string? icon = null) - { - Name = name; - Id = id; - Icon = icon; - } - /// /// A unique identifier for the Relying Party entity, which sets the RP ID. /// [JsonPropertyName("id")] - public string Id { get; set; } + public string Id { get; set; } = id; /// /// A human-readable name for the entity. Its function depends on what the PublicKeyCredentialEntity represents: /// [JsonPropertyName("name")] - public string Name { get; set; } + public string Name { get; set; } = name; [JsonPropertyName("icon")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Icon { get; set; } + public string? Icon { get; set; } = icon; } + #nullable disable /// diff --git a/Src/Fido2.Models/Fido2Configuration.cs b/Src/Fido2.Models/Fido2Configuration.cs index f904bfef..b69ec978 100644 --- a/Src/Fido2.Models/Fido2Configuration.cs +++ b/Src/Fido2.Models/Fido2Configuration.cs @@ -52,10 +52,7 @@ public IReadOnlySet Origins { get { - if (_origins == null) - { - _origins = new HashSet(0); - } + _origins ??= new HashSet(0); return _origins; } @@ -91,14 +88,14 @@ public IReadOnlySet FullyQualifiedOrigins /// /// List of metadata statuses for an authenticator that should cause attestations to be rejected. /// - public AuthenticatorStatus[] UndesiredAuthenticatorMetadataStatuses { get; set; } = new AuthenticatorStatus[] - { + public AuthenticatorStatus[] UndesiredAuthenticatorMetadataStatuses { get; set; } = + [ AuthenticatorStatus.ATTESTATION_KEY_COMPROMISE, AuthenticatorStatus.USER_VERIFICATION_BYPASS, AuthenticatorStatus.USER_KEY_REMOTE_COMPROMISE, AuthenticatorStatus.USER_KEY_PHYSICAL_COMPROMISE, AuthenticatorStatus.REVOKED - }; + ]; /// /// Whether or not to accept a backup eligible credential diff --git a/Src/Fido2.Models/Objects/AuthenticationExtensionsDevicePublicKeyOutputs.cs b/Src/Fido2.Models/Objects/AuthenticationExtensionsDevicePublicKeyOutputs.cs index 33a8397b..1b799be7 100644 --- a/Src/Fido2.Models/Objects/AuthenticationExtensionsDevicePublicKeyOutputs.cs +++ b/Src/Fido2.Models/Objects/AuthenticationExtensionsDevicePublicKeyOutputs.cs @@ -4,20 +4,16 @@ namespace Fido2NetLib.Objects; using System.Text.Json.Serialization; -public sealed class AuthenticationExtensionsDevicePublicKeyOutputs +[method: JsonConstructor] +public sealed class AuthenticationExtensionsDevicePublicKeyOutputs( + byte[] authenticatorOutput, + byte[] signature) { - [JsonConstructor] - public AuthenticationExtensionsDevicePublicKeyOutputs(byte[] authenticatorOutput, byte[] signature) - { - AuthenticatorOutput = authenticatorOutput; - Signature = signature; - } - [JsonConverter(typeof(Base64UrlConverter))] [JsonPropertyName("authenticatorOutput")] - public byte[] AuthenticatorOutput { get; } + public byte[] AuthenticatorOutput { get; } = authenticatorOutput; [JsonConverter(typeof(Base64UrlConverter))] [JsonPropertyName("signature")] - public byte[] Signature { get; } + public byte[] Signature { get; } = signature; } diff --git a/Src/Fido2.Models/UndesiredMetadataStatusFido2VerificationException.cs b/Src/Fido2.Models/UndesiredMetadataStatusFido2VerificationException.cs index 18619f02..d710d0ec 100644 --- a/Src/Fido2.Models/UndesiredMetadataStatusFido2VerificationException.cs +++ b/Src/Fido2.Models/UndesiredMetadataStatusFido2VerificationException.cs @@ -3,15 +3,11 @@ /// /// Exception thrown when a new attestation comes from an authenticator with a current reported security issue. /// -public class UndesiredMetadataStatusFido2VerificationException : Fido2VerificationException +public class UndesiredMetadataStatusFido2VerificationException(StatusReport statusReport) + : Fido2VerificationException($"Authenticator found with undesirable status. Was {statusReport.Status}") { - public UndesiredMetadataStatusFido2VerificationException(StatusReport statusReport) : base($"Authenticator found with undesirable status. Was {statusReport.Status}") - { - StatusReport = statusReport; - } - /// /// Status report from the authenticator that caused the attestation to be rejected. /// - public StatusReport StatusReport { get; } + public StatusReport StatusReport { get; } = statusReport; } diff --git a/Src/Fido2/Assembly.cs b/Src/Fido2/Assembly.cs deleted file mode 100644 index a825116a..00000000 --- a/Src/Fido2/Assembly.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Test")] diff --git a/Src/Fido2/AttestationFormat/Tpm.cs b/Src/Fido2/AttestationFormat/Tpm.cs index 61d6481e..bd4e0b47 100644 --- a/Src/Fido2/AttestationFormat/Tpm.cs +++ b/Src/Fido2/AttestationFormat/Tpm.cs @@ -15,8 +15,8 @@ namespace Fido2NetLib; internal sealed class Tpm : AttestationVerifier { - public static readonly HashSet TPMManufacturers = new() - { + public static readonly HashSet TPMManufacturers = + [ "id:FFFFF1D0", // FIDO testing TPM // From https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-Vendor-ID-Registry-Version-1.02-Revision-1.00.pdf "id:414D4400", // 'AMD' AMD @@ -42,7 +42,7 @@ internal sealed class Tpm : AttestationVerifier "id:57454300", // 'WEC' Winbond "id:524F4343", // 'ROCC' Fuzhou Rockchip "id:474F4F47", // 'GOOG' Google - }; + ]; public override ValueTask VerifyAsync(VerifyAttestationRequest request) { @@ -309,9 +309,9 @@ This detects this condition and repacks each devices attributes SEQUENCE into it foreach (Asn1Element o in deviceAttributes[0].Sequence) { - wrappedElements.Add(Asn1Element.CreateSetOf(new List(1) { + wrappedElements.Add(Asn1Element.CreateSetOf([ Asn1Element.CreateSequence((List)o.Sequence) - })); + ])); } deviceAttributes = wrappedElements; diff --git a/Src/Fido2/Cbor/CborBoolean.cs b/Src/Fido2/Cbor/CborBoolean.cs index af96e7ea..a2781fc6 100644 --- a/Src/Fido2/Cbor/CborBoolean.cs +++ b/Src/Fido2/Cbor/CborBoolean.cs @@ -2,19 +2,14 @@ namespace Fido2NetLib.Cbor; -public sealed class CborBoolean : CborObject +public sealed class CborBoolean(bool value) : CborObject { public static readonly CborBoolean True = new(true); public static readonly CborBoolean False = new(false); - public CborBoolean(bool value) - { - Value = value; - } - public override CborType Type => CborType.Boolean; - public bool Value { get; } + public bool Value { get; } = value; public override int GetHashCode() { diff --git a/Src/Fido2/Cbor/CborByteString.cs b/Src/Fido2/Cbor/CborByteString.cs index a7c0a877..7c81ba18 100644 --- a/Src/Fido2/Cbor/CborByteString.cs +++ b/Src/Fido2/Cbor/CborByteString.cs @@ -2,18 +2,11 @@ namespace Fido2NetLib.Cbor; -public sealed class CborByteString : CborObject +public sealed class CborByteString(byte[] value) : CborObject { - public CborByteString(byte[] value) - { - ArgumentNullException.ThrowIfNull(value); - - Value = value; - } - public override CborType Type => CborType.ByteString; - public byte[] Value { get; } + public byte[] Value { get; } = value ?? throw new ArgumentNullException(nameof(value)); public int Length => Value.Length; diff --git a/Src/Fido2/Cbor/CborInteger.cs b/Src/Fido2/Cbor/CborInteger.cs index 73c335d0..5e5aa542 100644 --- a/Src/Fido2/Cbor/CborInteger.cs +++ b/Src/Fido2/Cbor/CborInteger.cs @@ -2,16 +2,11 @@ namespace Fido2NetLib.Cbor; -internal sealed class CborInteger : CborObject +internal sealed class CborInteger(long value) : CborObject { - public CborInteger(long value) - { - Value = value; - } - public override CborType Type => CborType.Integer; - public long Value { get; } + public long Value { get; } = value; public override bool Equals(object? obj) { diff --git a/Src/Fido2/Cbor/CborMap.cs b/Src/Fido2/Cbor/CborMap.cs index b2f85334..95b493f4 100644 --- a/Src/Fido2/Cbor/CborMap.cs +++ b/Src/Fido2/Cbor/CborMap.cs @@ -13,7 +13,7 @@ public sealed class CborMap : CborObject, IReadOnlyDictionary CborType.TextString; public int Length => Value.Length; - public string Value { get; } + public string Value { get; } = value ?? throw new ArgumentNullException(nameof(value)); public static implicit operator string(CborTextString value) => value.Value; diff --git a/Src/Fido2/Fido2.csproj b/Src/Fido2/Fido2.csproj index 07febdd5..287e9e63 100644 --- a/Src/Fido2/Fido2.csproj +++ b/Src/Fido2/Fido2.csproj @@ -18,6 +18,10 @@ + + + +