using System.Runtime.InteropServices; using ProtonVPN.OperatingSystems.WebAuthn.Enums; using ProtonVPN.OperatingSystems.WebAuthn.Interop.Marshalers; namespace ProtonVPN.OperatingSystems.WebAuthn.Interop.Structs; /// /// Information about Extension. /// /// Corresponds to WEBAUTHN_EXTENSION. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class ExtensionIn : IDisposable { /// /// Extension identifier. /// public string Identifier { get; private set; } private int _dataLength; /// /// Extension data. /// private ByteArrayIn _data; public ExtensionIn(string id, byte[] data) { Identifier = id; _dataLength = data?.Length ?? 0; _data = new ByteArrayIn(data); } public static ExtensionIn CreateHmacSecret() { // Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET // MakeCredential Input Type: BOOL. // - pvExtension must point to a BOOL with the value TRUE. // - cbExtension must contain the sizeof(BOOL). byte[] binaryTrue = BitConverter.GetBytes(1); return new ExtensionIn(ApiConstants.ExtensionIdentifierHmacSecret, binaryTrue); } public static ExtensionIn CreateCredProtect(UserVerification uv, bool enforce) { // Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT // MakeCredential Input Type: WEBAUTHN_CRED_PROTECT_EXTENSION_IN. // - pvExtension must point to a WEBAUTHN_CRED_PROTECT_EXTENSION_IN struct // - cbExtension will contain the sizeof(WEBAUTHN_CRED_PROTECT_EXTENSION_IN). int structSize = sizeof(UserVerification) + sizeof(int); byte[] extensionData = new byte[structSize]; BitConverter.GetBytes((int)uv).CopyTo(extensionData, 0); BitConverter.GetBytes(enforce ? 1 : 0).CopyTo(extensionData, sizeof(UserVerification)); return new ExtensionIn(ApiConstants.ExtensionIdentifierCredProtect, extensionData); } public static ExtensionIn CreateCredBlobAttestation(byte[] blob) { if (blob == null) { throw new ArgumentNullException(nameof(blob)); } // Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB // MakeCredential Input Type: WEBAUTHN_CRED_BLOB_EXTENSION. // - pvExtension must point to a WEBAUTHN_CRED_BLOB_EXTENSION struct // - cbExtension must contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION). int structSize = blob.Length + sizeof(int); byte[] extensionData = new byte[structSize]; BitConverter.GetBytes(blob.Length).CopyTo(extensionData, 0); blob.CopyTo(extensionData, sizeof(int)); return new ExtensionIn(ApiConstants.ExtensionIdentifierCredBlob, extensionData); } public static ExtensionIn CreateCredBlobAssertion() { // Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB // GetAssertion Input Type: BOOL. // - pvExtension must point to a BOOL with the value TRUE to request the credBlob. // - cbExtension must contain the sizeof(BOOL). byte[] binaryTrue = BitConverter.GetBytes(1); return new ExtensionIn(ApiConstants.ExtensionIdentifierCredBlob, binaryTrue); } public static ExtensionIn CreateMinPinLength() { // Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH // MakeCredential Input Type: BOOL. // - pvExtension must point to a BOOL with the value TRUE to request the minPinLength. // - cbExtension must contain the sizeof(BOOL). byte[] binaryTrue = BitConverter.GetBytes(1); return new ExtensionIn(ApiConstants.ExtensionIdentifierMinPinLength, binaryTrue); } public void Dispose() { _data?.Dispose(); _data = null; } }