using System.Runtime.InteropServices; using ProtonVPN.OperatingSystems.WebAuthn.Interop.Marshalers; namespace ProtonVPN.OperatingSystems.WebAuthn.Interop.Structs; /// Corresponds to WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT. [StructLayout(LayoutKind.Sequential)] public class CredentialWithHmacSecretSaltIn : IDisposable { /// /// Size of the credential ID. /// private int _credentialIdLength; /// /// Credential ID. /// private ByteArrayIn _credentialId; /// /// PRF Values for above credential /// private nint _hmacSecretSalt; /// /// Credential ID. /// public byte[] CredentialId { get { return _credentialId?.Read(_credentialIdLength); } set { // Get rid of any previous value first _credentialId?.Dispose(); // Now replace the previous value with a new one _credentialIdLength = value?.Length ?? 0; _credentialId = new ByteArrayIn(value); } } /// /// PRF Values for above credential /// public HmacSecretSaltIn HmacSecretSalt { set { if (value != null) { if (_hmacSecretSalt == nint.Zero) { _hmacSecretSalt = Marshal.AllocHGlobal(Marshal.SizeOf()); } Marshal.StructureToPtr(value, _hmacSecretSalt, false); } else { FreeHmacSecretSalt(); } } } public CredentialWithHmacSecretSaltIn(byte[] credentialId, HmacSecretSaltIn hmacSecretSalt) { CredentialId = credentialId; HmacSecretSalt = hmacSecretSalt; } private void FreeHmacSecretSalt() { if (_hmacSecretSalt != nint.Zero) { Marshal.FreeHGlobal(_hmacSecretSalt); _hmacSecretSalt = nint.Zero; } } public void Dispose() { _credentialId?.Dispose(); _credentialId = null; FreeHmacSecretSalt(); } } [StructLayout(LayoutKind.Sequential)] public sealed class CredentialsWithHmacSecretSaltIn : SafeStructArrayIn { public CredentialsWithHmacSecretSaltIn(CredentialWithHmacSecretSaltIn[] credsWithHmacSecretSalt) : base(credsWithHmacSecretSalt) { } }