diff --git a/src/Tizen.Security.WebAuthn/Interop/Interop.Libweabuthn.cs b/src/Tizen.Security.WebAuthn/Interop/Interop.Libweabuthn.cs
new file mode 100644
index 00000000000..27ba520ba03
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Interop/Interop.Libweabuthn.cs
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Libraries
+ {
+ public const string Libwebauthn = "libwebauthn-client.so.1";
+ }
+
+ internal static partial class Libwebauthn
+ {
+ [DllImport(Libraries.Libwebauthn, EntryPoint = "wauthn_set_api_version", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int SetApiVersion(int apiVersionNumber);
+ // int wauthn_set_api_version(int api_version_number);
+
+ [DllImport(Libraries.Libwebauthn, EntryPoint = "wauthn_supported_authenticators", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int SupportedAuthenticators(out uint supported);
+ // int wauthn_supported_authenticators(unsigned int *supported);
+
+ [DllImport(Libraries.Libwebauthn, EntryPoint = "wauthn_make_credential", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int MakeCredential([In] WauthnClientData clientData, [In] WauthnPubkeyCredCreationOptions options, [In, Out] WauthnMcCallbacks callbacks);
+ // int wauthn_make_credential( const wauthn_client_data_s *client_data, const wauthn_pubkey_cred_creation_options_s *options, wauthn_mc_callbacks_s *callbacks);
+
+ [DllImport(Libraries.Libwebauthn, EntryPoint = "wauthn_get_assertion", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int GetAssertion([In] WauthnClientData clientData, [In] WauthnPubkeyCredRequestOptions options, [In, Out] WauthnGaCallbacks callbacks);
+ // int wauthn_get_assertion( const wauthn_client_data_s *client_data, const wauthn_pubkey_cred_request_options_s *options, wauthn_ga_callbacks_s *callbacks);
+
+ [DllImport(Libraries.Libwebauthn, EntryPoint = "wauthn_cancel", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int Cancel();
+ // int wauthn_cancel();
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Interop/Interop.Types.cs b/src/Tizen.Security.WebAuthn/Interop/Interop.Types.cs
new file mode 100644
index 00000000000..c85dbd09d19
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Interop/Interop.Types.cs
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Internals;
+using Tizen.Security.WebAuthn;
+
+internal static partial class Interop
+{
+ private const string pkg = "webauthn";
+
+ #region Delegates
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void WauthnDisplayQrcodeCallback([In][MarshalAs(UnmanagedType.LPStr)] string qrContents, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void WauthnMcOnResponseCallback([In] WauthnPubkeyCredentialAttestation pubkeyCred, WauthnError result, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void WauthnGaOnResponseCallback([In] WauthnPubkeyCredentialAssertion pubkeyCred, WauthnError result, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void WauthnUpdateLinkedDataCallback([In] IntPtr linkedData, WauthnError result, IntPtr userData);
+
+ #endregion
+ #region Classes
+
+ [NativeStruct("wauthn_rp_entity_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnRpEntity
+ {
+ public readonly IntPtr name; // string
+ public readonly IntPtr id; // string
+
+ public WauthnRpEntity(IntPtr name, IntPtr id)
+ {
+ this.name = name;
+ this.id = id;
+ }
+ }
+
+ [NativeStruct("wauthn_user_entity_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnUserEntity
+ {
+ public readonly IntPtr name; // string
+ public readonly IntPtr id; // WauthnConstBuffer*
+ public readonly IntPtr displayName; // string
+
+ public WauthnUserEntity(IntPtr name, IntPtr id, IntPtr displayName)
+ {
+ this.name = name;
+ this.id = id;
+ this.displayName = displayName;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_params_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredParams
+ {
+ public readonly nuint size;
+ public readonly IntPtr parameters; // WauthnPubkeyCredParam[]
+
+ public WauthnPubkeyCredParams(nuint size, IntPtr parameters)
+ {
+ this.size = size;
+ this.parameters = parameters;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_descriptors_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredDescriptors
+ {
+ public readonly nuint size;
+ public readonly IntPtr descriptors; // WauthnPubkeyCredDescriptor[]
+
+ public WauthnPubkeyCredDescriptors(nuint size, IntPtr descriptors)
+ {
+ this.size = size;
+ this.descriptors = descriptors;
+ }
+ }
+
+ [NativeStruct("wauthn_authenticator_sel_cri_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnAuthenticationSelCri
+ {
+ public readonly AuthenticatorAttachment attachment;
+ public readonly ResidentKeyRequirement residentKey;
+ public readonly byte requireResidentKey;
+ public readonly UserVerificationRequirement userVerification;
+
+ public WauthnAuthenticationSelCri(
+ AuthenticatorAttachment attachment,
+ ResidentKeyRequirement residentKey,
+ byte requireResidentKey,
+ UserVerificationRequirement userVerification)
+ {
+ this.attachment = attachment;
+ this.residentKey = residentKey;
+ this.requireResidentKey = requireResidentKey;
+ this.userVerification = userVerification;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_hints_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredHints
+ {
+ public readonly nuint size;
+ public readonly IntPtr hints; // PubkeyCredHint[]
+
+ public WauthnPubkeyCredHints(nuint size, IntPtr hints)
+ {
+ this.size = size;
+ this.hints = hints;
+ }
+ }
+
+ [NativeStruct("wauthn_attestation_formats_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnAttestationFormats
+ {
+ public readonly nuint size;
+ public readonly IntPtr attestationFormats; // WauthnConstBuffer[]
+
+ public WauthnAttestationFormats(nuint size, IntPtr attestationFormats)
+ {
+ this.size = size;
+ this.attestationFormats = attestationFormats;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_creation_options_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredCreationOptions
+ {
+ public readonly IntPtr rp; // WauthnRpEntity*
+ public readonly IntPtr user; // WauthnUserEntity*
+ public readonly IntPtr pubkeyCredParams; // WauthnPubkeyCredParams*
+ public readonly nuint timeout;
+ public readonly IntPtr excludeCredentials; // WauthnPubkeyCredDescriptors*
+ public readonly IntPtr authenticatorSelection; // WauthnAuthenticationSelCri*
+ public readonly IntPtr hints; // WauthnPubkeyCredHints*
+ public readonly AttestationPref attestation;
+ public readonly IntPtr attestationFormats; // WauthnAttestationFormats*
+ public readonly IntPtr extensions; // WauthnAuthenticationExts*
+ public readonly IntPtr linkedDevice; // WauthnHybridLinkedData*
+
+ public WauthnPubkeyCredCreationOptions(
+ IntPtr rp,
+ IntPtr user,
+ IntPtr pubkeyCredParams,
+ nuint timeout,
+ IntPtr excludeCredentials,
+ IntPtr authenticatorSelection,
+ IntPtr hints,
+ AttestationPref attestation,
+ IntPtr attestationFormats,
+ IntPtr extensions,
+ IntPtr linkedDevice)
+ {
+ this.rp = rp;
+ this.user = user;
+ this.pubkeyCredParams = pubkeyCredParams;
+ this.timeout = timeout;
+ this.excludeCredentials = excludeCredentials;
+ this.authenticatorSelection = authenticatorSelection;
+ this.hints = hints;
+ this.attestation = attestation;
+ this.attestationFormats = attestationFormats;
+ this.extensions = extensions;
+ this.linkedDevice = linkedDevice;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_request_options_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredRequestOptions
+ {
+ public readonly nuint timeout;
+ [MarshalAs(UnmanagedType.LPStr)]
+ public readonly string rpId;
+ public readonly IntPtr allowCredentials; // WauthnPubkeyCredDescriptors*
+ public readonly UserVerificationRequirement userVerification;
+ public readonly IntPtr hints; // WauthnPubkeyCredHints*
+ public readonly AttestationPref attestation;
+ public readonly IntPtr attestationFormats; // WauthnAttestationFormats*
+ public readonly IntPtr extensions; // WauthnAuthenticationExt*
+ public readonly IntPtr linkedDevice; // WauthnHybridLinkedData*
+
+ public WauthnPubkeyCredRequestOptions(
+ nuint timeout,
+ string rpId,
+ IntPtr allowCredentials,
+ UserVerificationRequirement userVerification,
+ IntPtr hints,
+ AttestationPref attestation,
+ IntPtr attestationFormats,
+ IntPtr extensions,
+ IntPtr linkedDevice)
+ {
+ this.timeout = timeout;
+ this.rpId = rpId;
+ this.allowCredentials = allowCredentials;
+ this.userVerification = userVerification;
+ this.hints = hints;
+ this.attestation = attestation;
+ this.attestationFormats = attestationFormats;
+ this.extensions = extensions;
+ this.linkedDevice = linkedDevice;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_credential_attestation_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredentialAttestation
+ {
+ public readonly IntPtr id; // WauthnConstBuffer*
+ public readonly PubkeyCredType type;
+ public readonly IntPtr rawId; // WauthnConstBuffer*
+ public readonly IntPtr response; // WauthnAuthenticatorAttestationResponse*
+ public readonly AuthenticatorAttachment authenticatorAttachment;
+ public readonly IntPtr extensions; // WauthnAuthenticationExts*
+ public readonly IntPtr linkedDevice; // WauthnHybridLinkedData*
+
+ public WauthnPubkeyCredentialAttestation(
+ IntPtr id,
+ PubkeyCredType type,
+ IntPtr rawId,
+ IntPtr response,
+ AuthenticatorAttachment authenticatorAttachment,
+ IntPtr extensions,
+ IntPtr linkedDevice)
+ {
+ this.id = id;
+ this.type = type;
+ this.rawId = rawId;
+ this.response = response;
+ this.authenticatorAttachment = authenticatorAttachment;
+ this.extensions = extensions;
+ this.linkedDevice = linkedDevice;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_credential_assertion_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnPubkeyCredentialAssertion
+ {
+ public readonly IntPtr id; // WauthnConstBuffer*
+ public readonly PubkeyCredType type;
+ public readonly IntPtr rawId; // WauthnConstBuffer*
+ public readonly IntPtr response; // WauthnAuthenticatorAssertionResponse*
+ public readonly AuthenticatorAttachment authenticatorAttachment;
+ public readonly IntPtr extensions; // WauthnAuthenticationExts*
+ public readonly IntPtr linkedDevice; // WauthnHybridLinkedData*
+
+ public WauthnPubkeyCredentialAssertion(
+ IntPtr id,
+ IntPtr rawId,
+ IntPtr response,
+ AuthenticatorAttachment authenticatorAttachment,
+ IntPtr extensions,
+ IntPtr linkedDevice)
+ {
+ this.id = id;
+ this.rawId = rawId;
+ this.response = response;
+ this.authenticatorAttachment = authenticatorAttachment;
+ this.extensions = extensions;
+ this.linkedDevice = linkedDevice;
+ }
+ }
+
+ [NativeStruct("wauthn_client_data_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnClientData
+ {
+ public readonly IntPtr clientDataJson; // WauthnConstBuffer*
+ public readonly HashAlgorithm hashAlgo;
+
+ public WauthnClientData(IntPtr clientDataJson, HashAlgorithm hashAlgo)
+ {
+ this.clientDataJson = clientDataJson;
+ this.hashAlgo = hashAlgo;
+ }
+ }
+
+ [NativeStruct("wauthn_mc_callbacks_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnMcCallbacks
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnDisplayQrcodeCallback qrcodeCallback;
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnMcOnResponseCallback responseCallback;
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnUpdateLinkedDataCallback linkedDataCallback;
+ public readonly IntPtr userData = IntPtr.Zero;
+
+ public WauthnMcCallbacks(
+ WauthnDisplayQrcodeCallback qrcodeCallback,
+ WauthnMcOnResponseCallback responseCallback,
+ WauthnUpdateLinkedDataCallback linkedDataCallback)
+ {
+ this.qrcodeCallback = qrcodeCallback;
+ this.responseCallback = responseCallback;
+ this.linkedDataCallback = linkedDataCallback;
+ }
+ }
+
+ [NativeStruct("wauthn_ga_callbacks_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal class WauthnGaCallbacks
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnDisplayQrcodeCallback qrcodeCallback;
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnGaOnResponseCallback responseCallback;
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public readonly WauthnUpdateLinkedDataCallback linkedDataCallback;
+ public readonly IntPtr userData = IntPtr.Zero;
+
+ public WauthnGaCallbacks(
+ WauthnDisplayQrcodeCallback qrcodeCallback,
+ WauthnGaOnResponseCallback responseCallback,
+ WauthnUpdateLinkedDataCallback linkedDataCallback)
+ {
+ this.qrcodeCallback = qrcodeCallback;
+ this.responseCallback = responseCallback;
+ this.linkedDataCallback = linkedDataCallback;
+ }
+ }
+ #endregion
+ #region Structs
+
+ [NativeStruct("wauthn_const_buffer_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnConstBuffer
+ {
+ public readonly IntPtr data; // byte[]
+ public readonly nuint size;
+
+ public WauthnConstBuffer(IntPtr data, nuint size)
+ {
+ this.data = data;
+ this.size = size;
+ }
+
+ public readonly byte[] ToArray()
+ {
+ var ret = new byte[size];
+ Marshal.Copy(data, ret, 0, (int)size);
+ return ret;
+ }
+ }
+
+ [NativeStruct("wauthn_authenticator_attestation_response_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnAuthenticatorAttestationResponse
+ {
+ public readonly IntPtr clientDataJson; // WauthnConstBuffer*
+ public readonly IntPtr attestationObject; // WauthnConstBuffer*
+ public readonly uint transports;
+ public readonly IntPtr authenticatorData; // WauthnConstBuffer*
+ public readonly IntPtr subjectPubkeyInfo; // WauthnConstBuffer*
+ public readonly CoseAlgorithm pubkeyAlg;
+
+ public WauthnAuthenticatorAttestationResponse(
+ IntPtr clientDataJson,
+ IntPtr attestationObject,
+ uint transports,
+ IntPtr authenticatorData,
+ IntPtr subjectPubkeyInfo,
+ CoseAlgorithm pubkeyAlg)
+ {
+ this.clientDataJson = clientDataJson;
+ this.attestationObject = attestationObject;
+ this.transports = transports;
+ this.authenticatorData = authenticatorData;
+ this.subjectPubkeyInfo = subjectPubkeyInfo;
+ this.pubkeyAlg = pubkeyAlg;
+ }
+ }
+
+ [NativeStruct("wauthn_authenticator_assertion_response_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnAuthenticatorAssertionResponse
+ {
+ public readonly IntPtr clientDataJson; // WauthnConstBuffer*
+ public readonly IntPtr authenticatorData; // WauthnConstBuffer*
+ public readonly IntPtr signature; // WauthnConstBuffer*
+ public readonly IntPtr userHandle; // WauthnConstBuffer*
+ public readonly IntPtr attestationObject; // WauthnConstBuffer*
+
+ public WauthnAuthenticatorAssertionResponse(
+ IntPtr clientDataJson,
+ IntPtr authenticatorData,
+ IntPtr signature,
+ IntPtr userHandle,
+ IntPtr attestationObject)
+ {
+ this.clientDataJson = clientDataJson;
+ this.authenticatorData = authenticatorData;
+ this.signature = signature;
+ this.userHandle = userHandle;
+ this.attestationObject = attestationObject;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_param_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnPubkeyCredParam
+ {
+ public readonly PubkeyCredType type;
+ public readonly CoseAlgorithm alg;
+
+ public WauthnPubkeyCredParam(PubkeyCredType type, CoseAlgorithm alg)
+ {
+ this.type = type;
+ this.alg = alg;
+ }
+ }
+
+ [NativeStruct("wauthn_pubkey_cred_descriptor_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnPubkeyCredDescriptor
+ {
+ public readonly PubkeyCredType type;
+ public readonly IntPtr id; // WauthnConstBuffer*
+ public readonly AuthenticatorTransport transport;
+
+ public WauthnPubkeyCredDescriptor(PubkeyCredType type, IntPtr id, AuthenticatorTransport transport)
+ {
+ this.type = type;
+ this.id = id;
+ this.transport = transport;
+ }
+ }
+
+ [NativeStruct("wauthn_authentication_ext_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnAuthenticationExt
+ {
+ public readonly IntPtr extensionId; // WauthnConstBuffer*
+ public readonly IntPtr extensionValue; // WauthnConstBuffer*
+
+ public WauthnAuthenticationExt(IntPtr extensionId, IntPtr extensionValue)
+ {
+ this.extensionId = extensionId;
+ this.extensionValue = extensionValue;
+ }
+ }
+
+ [NativeStruct("wauthn_authentication_exts_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnAuthenticationExts
+ {
+ public readonly nuint size;
+ public readonly IntPtr descriptors; // WauthnAuthenticationExt[]
+
+ public WauthnAuthenticationExts(nuint size, IntPtr descriptors)
+ {
+ this.size = size;
+ this.descriptors = descriptors;
+ }
+ }
+
+ [NativeStruct("wauthn_hybrid_linked_data_s", Include="webauthn-types.h", PkgConfig=pkg)]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct WauthnHybridLinkedData
+ {
+ public readonly IntPtr contactId; // WauthnConstBuffer*
+ public readonly IntPtr linkId; // WauthnConstBuffer*
+ public readonly IntPtr linkSecret; // WauthnConstBuffer*
+ public readonly IntPtr authenticatorPubkey; // WauthnConstBuffer*
+ public readonly IntPtr authenticatorName; // WauthnConstBuffer*
+ public readonly IntPtr signature; // WauthnConstBuffer*
+ public readonly IntPtr tunnelServerDomain; // WauthnConstBuffer*
+ public readonly IntPtr identityKey; // WauthnConstBuffer*
+
+ public WauthnHybridLinkedData(
+ IntPtr contactId,
+ IntPtr linkId,
+ IntPtr linkSecret,
+ IntPtr authenticatorPubkey,
+ IntPtr authenticatorName,
+ IntPtr signature,
+ IntPtr tunnelServerDomain,
+ IntPtr identityKey)
+ {
+ this.contactId = contactId;
+ this.linkId = linkId;
+ this.linkSecret = linkSecret;
+ this.authenticatorPubkey = authenticatorPubkey;
+ this.authenticatorName = authenticatorName;
+ this.signature = signature;
+ this.tunnelServerDomain = tunnelServerDomain;
+ this.identityKey = identityKey;
+ }
+ }
+
+ #endregion
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.csproj b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.csproj
new file mode 100644
index 00000000000..bb1db212d74
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.csproj
@@ -0,0 +1,11 @@
+
+
+
+ library
+ net6.0
+
+
+
+
+
+
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.sln b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.sln
new file mode 100644
index 00000000000..c045ea994f6
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.002.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.Security.WebAuthn", "Tizen.Security.WebAuthn.csproj", "{CEC2F310-E4BA-4FDB-8B06-8AA73C006ABC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CEC2F310-E4BA-4FDB-8B06-8AA73C006ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CEC2F310-E4BA-4FDB-8B06-8AA73C006ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CEC2F310-E4BA-4FDB-8B06-8AA73C006ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CEC2F310-E4BA-4FDB-8B06-8AA73C006ABC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {52E8477B-782E-40D2-B5F2-9047EE144C1A}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationExtension.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationExtension.cs
new file mode 100644
index 00000000000..630461152db
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationExtension.cs
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Interop;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Authenticator extension.
+ ///
+ /// 12
+ public class AuthenticationExtension
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ ///
+ /// Extension Identifier defined in the following registry:
+ /// https://www.iana.org/assignments/webauthn/webauthn.xhtml#webauthn-extension-ids
+ ///
+ /// Extension value.
+ public AuthenticationExtension(byte[] extensionId, byte[] extensionValue)
+ {
+ ExtensionId = extensionId;
+ ExtensionValue = extensionValue;
+ }
+
+ internal AuthenticationExtension(WauthnAuthenticationExt ext)
+ {
+ ExtensionId = NullSafeMarshal.PtrToArray(ext.extensionId);
+ ExtensionValue = NullSafeMarshal.PtrToArray(ext.extensionValue);
+ }
+
+ ///
+ /// Extension identifier.
+ ///
+ public byte[] ExtensionId { get; init; }
+ ///
+ /// Extension value.
+ ///
+ public byte[] ExtensionValue { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationSelectionCriteria.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationSelectionCriteria.cs
new file mode 100644
index 00000000000..1f4714caa56
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticationSelectionCriteria.cs
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Authenticator selection criteria.
+ ///
+ /// 12
+ public class AuthenticationSelectionCriteria
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ /// Authenticator attachment modality.
+ /// Specifies the extent to which the Relying Party desires to create a client-side discoverable credential.
+ /// Relying Parties SHOULD set it to true if, and only if, residentKey is set to required.
+ /// Specifies the Relying Party's requirements regarding user verification.
+ public AuthenticationSelectionCriteria(
+ AuthenticatorAttachment attachment,
+ ResidentKeyRequirement residentKey,
+ bool requireResidentKey,
+ UserVerificationRequirement userVerification)
+ {
+ Attachment = attachment;
+ ResidentKey = residentKey;
+ RequireResidentKey = requireResidentKey;
+ UserVerification = userVerification;
+ }
+
+ ///
+ /// Authenticator attachment modality.
+ ///
+ public AuthenticatorAttachment Attachment { get; init; }
+ ///
+ /// The extent to which the Relying Party desires to create a client-side discoverable credential.
+ ///
+ public ResidentKeyRequirement ResidentKey { get; init; }
+ ///
+ /// Whether residentKey is required.
+ ///
+ public bool RequireResidentKey { get; init; }
+ ///
+ /// The Relying Party's requirements regarding user verification.
+ ///
+ public UserVerificationRequirement UserVerification { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Authenticator.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Authenticator.cs
new file mode 100644
index 00000000000..68707c8b3a7
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Authenticator.cs
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using static Interop;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Public web authentication API.
+ ///
+ /// 12
+ public static class Authenticator
+ {
+ private const int API_VERSION_NUMBER = 0x00000001;
+ private static bool _apiVersionSet = false;
+ private static bool _busy = false;
+ private static object _userData = null;
+ private static WauthnDisplayQrcodeCallback _qrCodeCallback;
+ private static WauthnMcOnResponseCallback _mcResponseCallback;
+ private static WauthnGaOnResponseCallback _gaResponseCallback;
+ private static WauthnUpdateLinkedDataCallback _linkedDataCallback;
+ private static WauthnMcCallbacks _wauthnMcCallbacks;
+ private static WauthnGaCallbacks _wauthnGaCallbacks;
+
+ #region Public API
+ ///
+ /// Gets information on authenticator types that the client platform supports.
+ ///
+ /// 12
+ /// http://tizen.org/feature/security.webauthn
+ /// An enum with the collection of all supported authenticator types.
+ /// The required feature is not supported.
+ public static AuthenticatorTransport SupportedAuthenticators()
+ {
+ int ret = Libwebauthn.SupportedAuthenticators(out uint supported);
+ CheckErrNThrow(ret, "Get supported authenticators");
+
+ return (AuthenticatorTransport)supported;
+ }
+
+ ///
+ /// Makes a new web authentication credential and stores it to authenticator.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#sctn-createCredential
+ ///
+ /// 12
+ /// http://tizen.org/privilege/bluetooth
+ /// http://tizen.org/privilege/internet
+ /// public
+ ///
+ /// http://tizen.org/feature/security.webauthn
+ /// http://tizen.org/feature/network.bluetooth.le
+ /// and at least one of the following:
+ /// http://tizen.org/feature/network.wifi
+ /// http://tizen.org/feature/network.ethernet
+ /// http://tizen.org/feature/network.telephony
+ ///
+ /// UTF-8 encoded JSON serialization of the client data.
+ /// Specifies the desired attributes of the to-be-created public key credential.
+ /// The callback functions to be invoked.
+ /// The required feature is not supported.
+ /// Required privilege is missing.
+ /// Input parameter is invalid.
+ /// Operation invalid in current state.
+ /// Canceled by a cancel request.
+ public static void MakeCredential(ClientData clientData, PubkeyCredCreationOptions options, MakeCredentialCallbacks callbacks)
+ {
+ CheckPreconditions();
+ try
+ {
+ CheckNullNThrow(clientData);
+ CheckNullNThrow(clientData.JsonData);
+ CheckNullNThrow(options);
+ CheckNullNThrow(options.Rp);
+ CheckNullNThrow(options.User);
+ CheckNullNThrow(options.PubkeyCredParams);
+ CheckNullNThrow(callbacks);
+ CheckNullNThrow(callbacks.QrcodeCallback);
+ CheckNullNThrow(callbacks.ResponseCallback);
+ CheckNullNThrow(callbacks.LinkedDataCallback);
+
+ // Create callback wrappers
+ WrapMcCallbacks(callbacks);
+ AuthenticatorStorage.SetDataForMakeCredential(clientData, options);
+
+ int ret = Libwebauthn.MakeCredential(
+ AuthenticatorStorage.WauthnClientData,
+ AuthenticatorStorage.WauthnPubkeyCredCreationOptions,
+ _wauthnMcCallbacks);
+ CheckErrNThrow(ret, "Make Credential");
+ }
+ catch
+ {
+ Cleanup();
+ throw;
+ }
+ }
+
+ ///
+ /// Gets assertion from the authenticator.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#sctn-getAssertion
+ ///
+ /// 12
+ /// http://tizen.org/privilege/bluetooth
+ /// http://tizen.org/privilege/internet
+ /// public
+ ///
+ /// http://tizen.org/feature/security.webauthn
+ /// http://tizen.org/feature/network.bluetooth.le
+ /// and at least one of the following:
+ /// http://tizen.org/feature/network.wifi
+ /// http://tizen.org/feature/network.ethernet
+ /// http://tizen.org/feature/network.telephony
+ ///
+ /// UTF-8 encoded JSON serialization of the client data.
+ /// Specifies the desired attributes of the public key credential to discover.
+ /// The callback functions to be invoked.
+ /// The required feature is not supported.
+ /// Required privilege is missing.
+ /// Input parameter is invalid.
+ /// Operation invalid in current state.
+ /// Canceled by a cancel request.
+ public static void GetAssertion(ClientData clientData, PubkeyCredRequestOptions options, GetAssertionCallbacks callbacks)
+ {
+ CheckPreconditions();
+ try
+ {
+ CheckNullNThrow(clientData);
+ CheckNullNThrow(clientData.JsonData);
+ CheckNullNThrow(options);
+ CheckNullNThrow(callbacks);
+ CheckNullNThrow(callbacks.QrcodeCallback);
+ CheckNullNThrow(callbacks.ResponseCallback);
+ CheckNullNThrow(callbacks.LinkedDataCallback);
+
+ // Create callback wrappers
+ WrapGaCallbacks(callbacks);
+ AuthenticatorStorage.SetDataForGetAssertion(clientData, options);
+
+ int ret = Libwebauthn.GetAssertion(
+ AuthenticatorStorage.WauthnClientData,
+ AuthenticatorStorage.WauthnPubkeyCredRequestOptions,
+ _wauthnGaCallbacks);
+ CheckErrNThrow(ret, "Get Assertion");
+ }
+ catch
+ {
+ Cleanup();
+ throw;
+ }
+ }
+
+ ///
+ /// Stops the previous or call.
+ ///
+ /// 12
+ /// http://tizen.org/feature/security.webauthn
+ /// The required feature is not supported.
+ /// Not allowed in the current context.
+ public static void Cancel()
+ {
+ int ret = Libwebauthn.Cancel();
+ CheckErrNThrow(ret, "Cancel operation");
+ }
+
+ #endregion
+ #region Helper methods
+
+ private static void SetApiVersion(int apiVersionNumber)
+ {
+ int ret = Libwebauthn.SetApiVersion(apiVersionNumber);
+ CheckErrNThrow(ret, "Set API version");
+ _apiVersionSet = true;
+ }
+ private static void WrapMcCallbacks(MakeCredentialCallbacks callbacks)
+ {
+ _userData = callbacks.UserData;
+
+ void qrCodeWrapper(string qrContents, IntPtr _)
+ {
+ callbacks.QrcodeCallback(qrContents, _userData);
+ }
+
+ void onResponseWrapper(WauthnPubkeyCredentialAttestation pubkeyCred, WauthnError result, IntPtr _)
+ {
+ PubkeyCredAttestation pubkeyCredManaged = pubkeyCred is not null ? new(pubkeyCred) : null;
+ callbacks.ResponseCallback(pubkeyCredManaged, result, _userData);
+
+ if (result != WauthnError.None)
+ Cleanup();
+ }
+
+ void linkedDataWrapper(IntPtr linkedData, WauthnError result, IntPtr _)
+ {
+ HybridLinkedData linkedDataManaged = linkedData != IntPtr.Zero ? new(Marshal.PtrToStructure(linkedData)) : null;
+ callbacks.LinkedDataCallback(linkedDataManaged, result, _userData);
+
+ if (result != WauthnError.NoneAndWait)
+ Cleanup();
+ }
+
+ _qrCodeCallback = new WauthnDisplayQrcodeCallback(qrCodeWrapper);
+ _mcResponseCallback = new WauthnMcOnResponseCallback(onResponseWrapper);
+ _linkedDataCallback = new WauthnUpdateLinkedDataCallback(linkedDataWrapper);
+
+ _wauthnMcCallbacks = new WauthnMcCallbacks(_qrCodeCallback, _mcResponseCallback, _linkedDataCallback);
+ }
+
+ private static void WrapGaCallbacks(GetAssertionCallbacks callbacks)
+ {
+ _userData = callbacks.UserData;
+
+ void qrCodeWrapper(string qrContents, IntPtr _)
+ {
+ callbacks.QrcodeCallback(qrContents, _userData);
+ }
+
+ void onResponseWrapper(WauthnPubkeyCredentialAssertion pubkeyCred, WauthnError result, IntPtr _)
+ {
+ PubkeyCredAssertion pubkeyCredManaged = pubkeyCred is not null ? new(pubkeyCred) : null;
+ callbacks.ResponseCallback(pubkeyCredManaged, result, _userData);
+
+ if (result != WauthnError.None)
+ Cleanup();
+ }
+
+ void linkedDataWrapper(IntPtr linkedData, WauthnError result, IntPtr _)
+ {
+ HybridLinkedData linkedDataManaged = linkedData != IntPtr.Zero ? new(Marshal.PtrToStructure(linkedData)) : null;
+ callbacks.LinkedDataCallback(linkedDataManaged, result, _userData);
+
+ if (result != WauthnError.NoneAndWait)
+ Cleanup();
+ }
+ _qrCodeCallback = new WauthnDisplayQrcodeCallback(qrCodeWrapper);
+ _gaResponseCallback = new WauthnGaOnResponseCallback(onResponseWrapper);
+ _linkedDataCallback = new WauthnUpdateLinkedDataCallback(linkedDataWrapper);
+
+ _wauthnGaCallbacks = new WauthnGaCallbacks(_qrCodeCallback, _gaResponseCallback, _linkedDataCallback);
+ }
+
+ private static void CheckPreconditions()
+ {
+ if (!_apiVersionSet)
+ SetApiVersion(API_VERSION_NUMBER);
+ if (_busy)
+ throw new InvalidOperationException("Authenticator busy");
+
+ _busy = true;
+ }
+
+ private static void Cleanup()
+ {
+ _busy = false;
+ AuthenticatorStorage.Cleanup();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAssertionResponse.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAssertionResponse.cs
new file mode 100644
index 00000000000..c8bc6723d9f
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAssertionResponse.cs
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Interop;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// The response of GetAssertion().
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#authenticatorassertionresponse
+ ///
+ /// 12
+ public class AuthenticatorAssertionResponse
+ {
+ internal AuthenticatorAssertionResponse(WauthnAuthenticatorAssertionResponse wauthnResponse)
+ {
+ ClientDataJson = NullSafeMarshal.PtrToArray(wauthnResponse.clientDataJson);
+ AuthenticatorData = NullSafeMarshal.PtrToArray(wauthnResponse.attestationObject);
+ Signature = NullSafeMarshal.PtrToArray(wauthnResponse.signature);
+ UserHandle = NullSafeMarshal.PtrToArray(wauthnResponse.userHandle);
+ AttestationObject = NullSafeMarshal.PtrToArray(wauthnResponse.attestationObject);
+ }
+
+ ///
+ /// JSON-compatible serialization of client data.
+ ///
+ public byte[] ClientDataJson { get; init; }
+ ///
+ /// The authenticator data contained within attestation_object.
+ /// For more information, refer to https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data
+ ///
+ public byte[] AuthenticatorData { get; init; }
+ ///
+ /// The raw signature returned from the authenticator.
+ /// For more information, refer to https://www.w3.org/TR/webauthn-3/#sctn-op-get-assertion
+ ///
+ public byte[] Signature { get; init; }
+ ///
+ /// The user handle returned from the authenticator,
+ /// or null if the authenticator did not return a user handle.
+ ///
+ public byte[] UserHandle { get; init; }
+ ///
+ /// This OPTIONAL attribute contains an attestation object,
+ /// if the authenticator supports attestation in assertions.
+ ///
+ public byte[] AttestationObject { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAttestationResponse.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAttestationResponse.cs
new file mode 100644
index 00000000000..e4209c00f52
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorAttestationResponse.cs
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Interop;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// The response of MakeCredential().
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#authenticatorattestationresponse
+ ///
+ /// 12
+ public class AuthenticatorAttestationResponse
+ {
+ internal AuthenticatorAttestationResponse(WauthnAuthenticatorAttestationResponse wauthnResponse)
+ {
+ ClientDataJson = NullSafeMarshal.PtrToArray(wauthnResponse.clientDataJson);
+ AttestationObject = NullSafeMarshal.PtrToArray(wauthnResponse.attestationObject);
+ Transports = (AuthenticatorTransport)wauthnResponse.transports;
+ AuthenticatorData = NullSafeMarshal.PtrToArray(wauthnResponse.authenticatorData);
+ SubjectPubkeyInfo = NullSafeMarshal.PtrToArray(wauthnResponse.subjectPubkeyInfo);
+ PubkeyAlg = wauthnResponse.pubkeyAlg;
+ }
+
+ ///
+ /// JSON-compatible serialization of client data.
+ ///
+ public byte[] ClientDataJson { get; init; }
+ ///
+ /// The CBOR encoded Attestation Object to be returned to the RP.
+ ///
+ public byte[] AttestationObject { get; init; }
+ ///
+ /// To represent multiple transports, can be ORed multiple times.
+ ///
+ public AuthenticatorTransport Transports { get; init; }
+ ///
+ /// The authenticator data contained within attestation_object.
+ /// For more information, refer to https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data
+ ///
+ public byte[] AuthenticatorData { get; init; }
+ ///
+ /// DER SubjectPublicKeyInfo of the new credential, or null if this is not available.
+ /// For more information, refer to https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.7
+ ///
+ public byte[] SubjectPubkeyInfo { get; init; }
+ ///
+ /// The COSEAlgorithmIdentifier of the new credential.
+ ///
+ public CoseAlgorithm PubkeyAlg { get; init; }
+
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorStorage.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorStorage.cs
new file mode 100644
index 00000000000..a47c6718f89
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/AuthenticatorStorage.cs
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using static Interop;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ internal static class AuthenticatorStorage
+ {
+ #region Internal unmanaged memory
+ private static UnmanagedMemory[] _credentialsIdUnmanagedDataArray;
+ private static UnmanagedMemory[] _credentialsIdUnmanagedConstBufferArray;
+ private static UnmanagedMemory[] _attestationFormatsUnmanagedDataArray;
+ private static UnmanagedMemory[] _attestationFormatsUnmanagedConstBufferArray;
+ private static UnmanagedMemory[] _extensionIdUnmanagedDataArray;
+ private static UnmanagedMemory[] _extensionIdUnmanagedConstBufferArray;
+ private static UnmanagedMemory[] _extensionValueUnmanagedDataArray;
+ private static UnmanagedMemory[] _extensionValueUnmanagedConstBufferArray;
+ private static UnmanagedMemory _jsonDataUnmanaged = new();
+ private static UnmanagedMemory _jsonDataConstBufferUnmanaged = new();
+ private static UnmanagedMemory _rpNameUnmanaged = new();
+ private static UnmanagedMemory _rpIdUnmanaged = new();
+ private static UnmanagedMemory _rpUnmanaged = new();
+ private static UnmanagedMemory _userNameUnmanaged = new();
+ private static UnmanagedMemory _userIdDataUnmanaged = new();
+ private static UnmanagedMemory _userIdConstBufferUnmanaged = new();
+ private static UnmanagedMemory _userDisplayNameUnmanaged = new();
+ private static UnmanagedMemory _userUnmanaged = new();
+ private static UnmanagedMemory _pubkeyCredParamsParametersUnmanaged = new();
+ private static UnmanagedMemory _pubkeyCredParamsUnmanaged = new();
+ private static UnmanagedMemory _credentialsDescriptorsUnmanaged = new();
+ private static UnmanagedMemory _credentialsUnmanaged = new();
+ private static UnmanagedMemory _authenticatorSelectionUnmanaged = new();
+ private static UnmanagedMemory _hintsArrayUnmanaged = new();
+ private static UnmanagedMemory _hintsUnmanaged = new();
+ private static UnmanagedMemory _attestationFormatsArrayUnmanaged = new();
+ private static UnmanagedMemory _attestationFormatsUnmanaged = new();
+ private static UnmanagedMemory _extensionsArrayUnmanaged = new();
+ private static UnmanagedMemory _extensionsUnmanaged = new();
+ private static UnmanagedMemory _contactIdDataUnmanaged = new();
+ private static UnmanagedMemory _contactIdUnmanaged = new();
+ private static UnmanagedMemory _linkIdDataUnmanaged = new();
+ private static UnmanagedMemory _linkIdUnmanaged = new();
+ private static UnmanagedMemory _linkSecretDataUnmanaged = new();
+ private static UnmanagedMemory _linkSecretUnmanaged = new();
+ private static UnmanagedMemory _authenticatorPubkeyDataUnmanaged = new();
+ private static UnmanagedMemory _authenticatorPubkeyUnmanaged = new();
+ private static UnmanagedMemory _authenticatorNameDataUnmanaged = new();
+ private static UnmanagedMemory _authenticatorNameUnmanaged = new();
+ private static UnmanagedMemory _signatureDataUnmanaged = new();
+ private static UnmanagedMemory _signatureUnmanaged = new();
+ private static UnmanagedMemory _tunnelServerDomainDataUnmanaged = new();
+ private static UnmanagedMemory _tunnelServerDomainUnmanaged = new();
+ private static UnmanagedMemory _identityKeyDataUnmanaged = new();
+ private static UnmanagedMemory _identityKeyUnmanaged = new();
+ private static UnmanagedMemory _linkedDeviceUnmanaged = new();
+ #endregion
+
+ public static void SetDataForMakeCredential(ClientData clientData, PubkeyCredCreationOptions options)
+ {
+ CopyClientData(clientData);
+ CopyCredCreationOptions(options);
+ }
+
+ public static void SetDataForGetAssertion(ClientData clientData, PubkeyCredRequestOptions options)
+ {
+ CopyClientData(clientData);
+ CopyCredRequestOptions(options);
+ }
+
+ public static void Cleanup()
+ {
+ CleanupArray(_credentialsIdUnmanagedDataArray);
+ CleanupArray(_credentialsIdUnmanagedConstBufferArray);
+ CleanupArray(_attestationFormatsUnmanagedDataArray);
+ CleanupArray(_attestationFormatsUnmanagedConstBufferArray);
+ CleanupArray(_extensionIdUnmanagedDataArray);
+ CleanupArray(_extensionIdUnmanagedConstBufferArray);
+ CleanupArray(_extensionValueUnmanagedDataArray);
+ CleanupArray(_extensionValueUnmanagedConstBufferArray);
+
+ _jsonDataUnmanaged.Dispose();
+ _jsonDataConstBufferUnmanaged.Dispose();
+ _rpNameUnmanaged.Dispose();
+ _rpIdUnmanaged.Dispose();
+ _rpUnmanaged.Dispose();
+ _userNameUnmanaged.Dispose();
+ _userIdConstBufferUnmanaged.Dispose();
+ _userDisplayNameUnmanaged.Dispose();
+ _userUnmanaged.Dispose();
+ _pubkeyCredParamsParametersUnmanaged.Dispose();
+ _pubkeyCredParamsUnmanaged.Dispose();
+ _credentialsDescriptorsUnmanaged.Dispose();
+ _credentialsUnmanaged.Dispose();
+ _authenticatorSelectionUnmanaged.Dispose();
+ _hintsArrayUnmanaged.Dispose();
+ _hintsUnmanaged.Dispose();
+ _attestationFormatsArrayUnmanaged.Dispose();
+ _attestationFormatsUnmanaged.Dispose();
+ _extensionsArrayUnmanaged.Dispose();
+ _extensionsUnmanaged.Dispose();
+ _contactIdDataUnmanaged.Dispose();
+ _contactIdUnmanaged.Dispose();
+ _linkIdDataUnmanaged.Dispose();
+ _linkIdUnmanaged.Dispose();
+ _linkSecretDataUnmanaged.Dispose();
+ _linkSecretUnmanaged.Dispose();
+ _authenticatorPubkeyDataUnmanaged.Dispose();
+ _authenticatorPubkeyUnmanaged.Dispose();
+ _authenticatorNameDataUnmanaged.Dispose();
+ _authenticatorNameUnmanaged.Dispose();
+ _signatureDataUnmanaged.Dispose();
+ _signatureUnmanaged.Dispose();
+ _tunnelServerDomainDataUnmanaged.Dispose();
+ _tunnelServerDomainUnmanaged.Dispose();
+ _identityKeyDataUnmanaged.Dispose();
+ _identityKeyUnmanaged.Dispose();
+ _linkedDeviceUnmanaged.Dispose();
+ }
+
+ private static void CopyClientData(ClientData clientData)
+ {
+ _jsonDataUnmanaged = UnmanagedMemory.PinArray(clientData.JsonData);
+ _jsonDataConstBufferUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_jsonDataUnmanaged, (nuint)clientData.JsonData.Length));
+ WauthnClientData = new WauthnClientData(_jsonDataConstBufferUnmanaged, clientData.HashAlgo);
+ }
+
+ private static void CopyCredCreationOptions(PubkeyCredCreationOptions options)
+ {
+ CopyRp(options.Rp);
+ CopyUser(options.User);
+ CopyCredParams(options.PubkeyCredParams);
+ CopyCredentials(options.ExcludeCredentials);
+ CopyAuthenticatorSelection(options.AuthenticatorSelection);
+ CopyHints(options.Hints);
+ CopyAttestationFormats(options.AttestationFormats);
+ CopyExtensions(options.Extensions);
+ CopyLinkedDevice(options.LinkedDevice);
+
+ WauthnPubkeyCredCreationOptions = new WauthnPubkeyCredCreationOptions(
+ _rpUnmanaged,
+ _userUnmanaged,
+ _pubkeyCredParamsUnmanaged,
+ (nuint)options.Timeout,
+ _credentialsUnmanaged,
+ _authenticatorSelectionUnmanaged,
+ _hintsUnmanaged,
+ options.Attestation,
+ _attestationFormatsUnmanaged,
+ _extensionsUnmanaged,
+ _linkedDeviceUnmanaged);
+ }
+
+ private static void CopyCredRequestOptions(PubkeyCredRequestOptions options)
+ {
+ CopyCredentials(options.AllowCredentials);
+ CopyHints(options.Hints);
+ CopyAttestationFormats(options.AttestationFormats);
+ CopyExtensions(options.Extensions);
+ CopyLinkedDevice(options.LinkedDevice);
+ WauthnPubkeyCredRequestOptions = new WauthnPubkeyCredRequestOptions(
+ (nuint)options.Timeout,
+ options.RpId,
+ _credentialsUnmanaged,
+ options.UserVerification,
+ _hintsUnmanaged,
+ options.Attestation,
+ _attestationFormatsUnmanaged,
+ _extensionsUnmanaged,
+ _linkedDeviceUnmanaged);
+ }
+
+ private static void CopyRp(RelyingPartyEntity rp)
+ {
+ _rpNameUnmanaged = new UnmanagedMemory(rp.Name);
+ _rpIdUnmanaged = new UnmanagedMemory(rp.Id);
+ _rpUnmanaged = new UnmanagedMemory(new WauthnRpEntity(_rpNameUnmanaged, _rpIdUnmanaged));
+ }
+
+ private static void CopyUser(UserEntity user)
+ {
+ _userNameUnmanaged = new UnmanagedMemory(user.Name);
+ _userIdDataUnmanaged = UnmanagedMemory.PinArray(user.Id);
+ _userIdConstBufferUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_userIdDataUnmanaged, (nuint)user.Id.Length));
+ _userDisplayNameUnmanaged = new UnmanagedMemory(user.DisplayName);
+ _userUnmanaged = new UnmanagedMemory(new WauthnUserEntity(
+ _userNameUnmanaged,
+ _userIdConstBufferUnmanaged,
+ _userDisplayNameUnmanaged));
+ }
+
+ private static void CopyCredParams(IEnumerable credParams)
+ {
+ if (credParams is null || !credParams.Any())
+ return;
+
+ WauthnPubkeyCredParam[] pubkeyCredParamStructArray = credParams.Select((PubkeyCredParam param) => new WauthnPubkeyCredParam(param.Type, param.Alg)).ToArray();
+ _pubkeyCredParamsParametersUnmanaged = UnmanagedMemory.PinArray(pubkeyCredParamStructArray);
+ _pubkeyCredParamsUnmanaged = new UnmanagedMemory(new WauthnPubkeyCredParams((nuint)pubkeyCredParamStructArray.Length, _pubkeyCredParamsParametersUnmanaged));
+ }
+
+ private static void CopyCredentials(IEnumerable credentials)
+ {
+ if (credentials is null || !credentials.Any())
+ return;
+
+ var credentialsCount = credentials.Count();
+ _credentialsIdUnmanagedDataArray = new UnmanagedMemory[credentialsCount];
+ _credentialsIdUnmanagedConstBufferArray = new UnmanagedMemory[credentialsCount];
+ var credentialsStructArray = new WauthnPubkeyCredDescriptor[credentialsCount];
+
+ for (int i = 0; i < credentialsCount; i++)
+ {
+ PubkeyCredDescriptor descriptor = credentials.ElementAt(i);
+ _credentialsIdUnmanagedDataArray[i] = UnmanagedMemory.PinArray(descriptor.Id);
+ var credentialIdUnmanagedConstBuffer = new UnmanagedMemory(new WauthnConstBuffer(_credentialsIdUnmanagedDataArray[i], (nuint)descriptor.Id.Length));
+ _credentialsIdUnmanagedConstBufferArray[i] = credentialIdUnmanagedConstBuffer;
+ credentialsStructArray[i] = new WauthnPubkeyCredDescriptor(descriptor.Type, credentialIdUnmanagedConstBuffer, descriptor.Transport);
+ }
+ _credentialsDescriptorsUnmanaged = UnmanagedMemory.PinArray(credentialsStructArray);
+ _credentialsUnmanaged = new UnmanagedMemory(new WauthnPubkeyCredDescriptors((nuint)credentialsCount, _credentialsDescriptorsUnmanaged));
+ }
+
+ private static void CopyAuthenticatorSelection(AuthenticationSelectionCriteria selection)
+ {
+ if (selection is null)
+ return;
+
+ _authenticatorSelectionUnmanaged = new UnmanagedMemory(new WauthnAuthenticationSelCri(
+ selection.Attachment,
+ selection.ResidentKey,
+ (byte)(selection.RequireResidentKey ? 1 : 0),
+ selection.UserVerification));
+ }
+
+ private static void CopyHints(IEnumerable hints)
+ {
+ if (hints is null || !hints.Any())
+ return;
+
+ int[] hintsArray = hints.Select((PubkeyCredHint hint) => (int)hint).ToArray();
+ _hintsArrayUnmanaged = UnmanagedMemory.PinArray(hintsArray);
+ _hintsUnmanaged = new UnmanagedMemory(new WauthnPubkeyCredHints((nuint)hintsArray.Length, _hintsArrayUnmanaged));
+ }
+
+ private static void CopyAttestationFormats(IEnumerable attestationFormats)
+ {
+ if (attestationFormats is null || !attestationFormats.Any())
+ return;
+
+ var attestationFormatsCount = attestationFormats.Count();
+ _attestationFormatsUnmanagedDataArray = new UnmanagedMemory[attestationFormatsCount];
+ _attestationFormatsUnmanagedConstBufferArray = new UnmanagedMemory[attestationFormatsCount];
+ var attestationFormatConstBufferStructArray = new WauthnConstBuffer[attestationFormatsCount];
+
+
+ for (int i = 0; i < attestationFormatsCount; i++)
+ {
+ byte[] attestationFormat = attestationFormats.ElementAt(i);
+ _attestationFormatsUnmanagedDataArray[i] = UnmanagedMemory.PinArray(attestationFormat);
+ attestationFormatConstBufferStructArray[i] = new WauthnConstBuffer(_attestationFormatsUnmanagedDataArray[i], (nuint)attestationFormat.Length);
+ _attestationFormatsUnmanagedConstBufferArray[i] = new UnmanagedMemory(attestationFormatConstBufferStructArray[i]);
+ }
+ _attestationFormatsArrayUnmanaged = UnmanagedMemory.PinArray(attestationFormatConstBufferStructArray);
+ _attestationFormatsUnmanaged = new UnmanagedMemory(new WauthnAttestationFormats((nuint)attestationFormatsCount, _attestationFormatsArrayUnmanaged));
+ }
+
+ private static void CopyExtensions(IEnumerable extensions)
+ {
+ if (extensions is null || !extensions.Any())
+ return;
+
+ var extensionCount = extensions.Count();
+ var extensionStructArray = new WauthnAuthenticationExt[extensionCount];
+ _extensionIdUnmanagedDataArray = new UnmanagedMemory[extensionCount];
+ _extensionIdUnmanagedConstBufferArray = new UnmanagedMemory[extensionCount];
+ _extensionValueUnmanagedDataArray = new UnmanagedMemory[extensionCount];
+ _extensionValueUnmanagedConstBufferArray = new UnmanagedMemory[extensionCount];
+
+ for (int i = 0; i < extensionCount; i++)
+ {
+ AuthenticationExtension ext = extensions.ElementAt(i);
+ _extensionIdUnmanagedDataArray[i] = UnmanagedMemory.PinArray(ext.ExtensionId);
+ var extensionIdUnmanagedConstBuffer = new UnmanagedMemory(new WauthnConstBuffer(_extensionIdUnmanagedDataArray[i], (nuint)ext.ExtensionId.Length));
+ _extensionIdUnmanagedConstBufferArray[i] = extensionIdUnmanagedConstBuffer;
+
+ _extensionValueUnmanagedDataArray[i] = UnmanagedMemory.PinArray(ext.ExtensionValue);
+ var extensionValueUnmanagedConstBuffer = new UnmanagedMemory(new WauthnConstBuffer(_extensionValueUnmanagedDataArray[i], (nuint)ext.ExtensionValue.Length));
+ _extensionValueUnmanagedConstBufferArray[i] = extensionValueUnmanagedConstBuffer;
+
+ extensionStructArray[i] = new WauthnAuthenticationExt(extensionIdUnmanagedConstBuffer, extensionValueUnmanagedConstBuffer);
+ }
+ _extensionsArrayUnmanaged = UnmanagedMemory.PinArray(extensionStructArray);
+ _extensionsUnmanaged = new UnmanagedMemory(new WauthnAuthenticationExts((nuint)extensionCount, _extensionsArrayUnmanaged));
+ }
+
+ private static void CopyLinkedDevice(HybridLinkedData linkedDevice)
+ {
+ if (linkedDevice is null)
+ return;
+
+ _contactIdDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.ContactId);
+ _contactIdUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_contactIdDataUnmanaged, (nuint)linkedDevice.ContactId.Length));
+
+ _linkIdDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.LinkId);
+ _linkIdUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_linkIdDataUnmanaged, (nuint)linkedDevice.LinkId.Length));
+
+ _linkSecretDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.LinkSecret);
+ _linkSecretUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_linkSecretDataUnmanaged, (nuint)linkedDevice.LinkSecret.Length));
+
+ _authenticatorPubkeyDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.AuthenticatorPubkey);
+ _authenticatorPubkeyUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_authenticatorPubkeyDataUnmanaged, (nuint)linkedDevice.AuthenticatorPubkey.Length));
+
+ _authenticatorNameDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.AuthenticatorName);
+ _authenticatorNameUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_authenticatorNameDataUnmanaged, (nuint)linkedDevice.AuthenticatorName.Length));
+
+ _signatureDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.Signature);
+ _signatureUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_signatureDataUnmanaged, (nuint)linkedDevice.Signature.Length));
+
+ _tunnelServerDomainDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.TunnelServerDomain);
+ _tunnelServerDomainUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_tunnelServerDomainDataUnmanaged, (nuint)linkedDevice.TunnelServerDomain.Length));
+
+ _identityKeyDataUnmanaged = UnmanagedMemory.PinArray(linkedDevice.IdentityKey);
+ _identityKeyUnmanaged = new UnmanagedMemory(new WauthnConstBuffer(_identityKeyDataUnmanaged, (nuint)linkedDevice.IdentityKey.Length));
+
+ _linkedDeviceUnmanaged = new UnmanagedMemory(new WauthnHybridLinkedData(
+ _contactIdUnmanaged,
+ _linkIdUnmanaged,
+ _linkSecretUnmanaged,
+ _authenticatorPubkeyUnmanaged,
+ _authenticatorNameUnmanaged,
+ _signatureUnmanaged,
+ _tunnelServerDomainUnmanaged,
+ _identityKeyUnmanaged));
+
+ if (_linkedDeviceUnmanaged == IntPtr.Zero)
+ throw new TimeoutException("linked null");
+ }
+
+ public static void CleanupArray(UnmanagedMemory[] array)
+ {
+ if (array is null)
+ return;
+ foreach (var memory in array)
+ memory.Dispose();
+ }
+
+ public static WauthnClientData WauthnClientData { get; private set; }
+ public static WauthnPubkeyCredCreationOptions WauthnPubkeyCredCreationOptions { get; private set; }
+ public static WauthnPubkeyCredRequestOptions WauthnPubkeyCredRequestOptions { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ClientData.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ClientData.cs
new file mode 100644
index 00000000000..609cfb4e749
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ClientData.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Client data JSON.
+ ///
+ ///
+ /// Refer to the following W3C specification about how to encode jsonData.
+ /// https://www.w3.org/TR/webauthn-3/#collectedclientdata-json-compatible-serialization-of-client-data
+ ///
+ /// 12
+ public class ClientData
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ /// UTF-8 encoded JSON serialization of the client data.
+ /// Hash algorithm used to hash the JsonData property.
+ public ClientData(byte[] jsonData, HashAlgorithm hashAlgo)
+ {
+ JsonData = jsonData;
+ HashAlgo = hashAlgo;
+ }
+
+ ///
+ /// UTF-8 encoded JSON serialization of the client data.
+ ///
+ public byte[] JsonData { get; init; }
+ ///
+ /// Hash algorithm used to hash the JsonData property.
+ ///
+ public HashAlgorithm HashAlgo{ get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AttestationPref.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AttestationPref.cs
new file mode 100644
index 00000000000..72e82da87be
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AttestationPref.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn attestation preference.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enumdef-attestationconveyancepreference
+ ///
+ /// 12
+ public enum AttestationPref
+ {
+ ///
+ /// Relying party not interested in authenticator attestation.
+ ///
+ None = 0,
+ ///
+ /// Indirect attestation preferred.
+ ///
+ Indirect = 1,
+ ///
+ /// Direct attestation preferred.
+ ///
+ Direct = 2,
+ ///
+ /// Enterprise attestation preferred.
+ ///
+ Enterprise = 3,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorAttachment.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorAttachment.cs
new file mode 100644
index 00000000000..ca0b6d85a07
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorAttachment.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn authentication attachment value.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enumdef-authenticatorattachment
+ ///
+ /// 12
+ public enum AuthenticatorAttachment
+ {
+ ///
+ /// No attachment.
+ ///
+ None = 0,
+ ///
+ /// Platform attachment.
+ ///
+ Platform = 1,
+ ///
+ /// Cross-platform attachment.
+ ///
+ CrossPlatform = 2,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorTransport.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorTransport.cs
new file mode 100644
index 00000000000..1204281e79b
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/AuthenticatorTransport.cs
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn authenticator transports.
+ ///
+ ///
+ /// Multiple transport values can be combined using bit-wise operation.
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enum-transport
+ ///
+ /// 12
+ [Flags]
+ public enum AuthenticatorTransport : uint
+ {
+ ///
+ /// No transport specified.
+ ///
+ None = 0x00000000,
+ ///
+ /// Authenticator reachable over USB.
+ ///
+ Usb = 0x00000001,
+ ///
+ /// Authenticator reachable over NFC.
+ ///
+ Nfc = 0x00000002,
+ ///
+ /// Authenticator reachable over BLE.
+ ///
+ Ble = 0x00000004,
+ ///
+ /// Authenticator reachable using Smart Card.
+ ///
+ Smartcard = 0x00000008,
+ ///
+ /// Authenticator reachable using a combination of mechanisms.
+ ///
+ Hybrid = 0x00000010,
+ ///
+ /// Authenticator reachable using a client device-specific transport.
+ ///
+ Internal = 0x00000020,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/CoseAlgorithm.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/CoseAlgorithm.cs
new file mode 100644
index 00000000000..cf88cde620d
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/CoseAlgorithm.cs
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn COSE (CBOR Object Signing and Encryption) algorithms.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#sctn-alg-identifier
+ ///
+ /// 12
+ public enum CoseAlgorithm
+ {
+ ///
+ /// ES256
+ ///
+ EcdsaP256WithSha256 = -7,
+ ///
+ /// ES384
+ ///
+ EcdsaP384WithSha384 = -35,
+ ///
+ /// ES512
+ ///
+ EcdsaP521WithSha512 = -36,
+ ///
+ /// EdDSA
+ ///
+ Eddsa = -8,
+ ///
+ /// PS256
+ ///
+ RsaPssWithSha256 = -37,
+ ///
+ /// PS384
+ ///
+ RsaPssWithSha384 = -38,
+ ///
+ /// PS512
+ ///
+ RsaPssWithSha512 = -39,
+ ///
+ /// RS256
+ ///
+ RsaSsaPkcs1V1_5WithSha256 = -257,
+ ///
+ /// RS384
+ ///
+ RsaSsaPkcs1V1_5WithSha384 = -258,
+ ///
+ /// RS512
+ ///
+ RsaSsaPkcs1V1_5WithSha512 = -259,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/HashAlogithm.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/HashAlogithm.cs
new file mode 100644
index 00000000000..1ca2a480726
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/HashAlogithm.cs
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn hash algorithms.
+ /// Currently one hash algorithm is used, namely "SHA-256".
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#collectedclientdata-hash-of-the-serialized-client-data
+ ///
+ /// 12
+ public enum HashAlgorithm
+ {
+ ///
+ /// SHA-256
+ ///
+ Sha256 = 1,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredHint.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredHint.cs
new file mode 100644
index 00000000000..cc09494f162
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredHint.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn public key credential hint value.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enumdef-publickeycredentialhints
+ ///
+ /// 12
+ public enum PubkeyCredHint
+ {
+ ///
+ /// None.
+ ///
+ None = 0,
+ ///
+ /// Physical security key.
+ ///
+ SecurityKey = 1,
+ ///
+ /// Platform authenticator attached to a client device.
+ ///
+ ClientDevice = 2,
+ ///
+ /// General-purpose authenticator.
+ ///
+ Hybrid = 3, // Hybrid
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredType.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredType.cs
new file mode 100644
index 00000000000..6a4207a46d5
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/PubkeyCredType.cs
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn credential type.
+ /// Currently one credential type is defined, namely "public-key".
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enumdef-publickeycredentialtype
+ ///
+ /// 12
+ public enum PubkeyCredType
+ {
+ ///
+ /// Public-key.
+ ///
+ PublicKey = 1,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/ResidentKeyRequirement.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/ResidentKeyRequirement.cs
new file mode 100644
index 00000000000..8def5ff56bf
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/ResidentKeyRequirement.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn resident key requirement value.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enum-residentKeyRequirement
+ ///
+ /// 12
+ public enum ResidentKeyRequirement
+ {
+ ///
+ /// None.
+ ///
+ None = 0,
+ ///
+ /// Resident key discouraged.
+ ///
+ Discouraged = 1,
+ ///
+ /// Resident key preferred.
+ ///
+ Preferred = 2,
+ ///
+ /// Resident key required.
+ ///
+ Required = 3,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/UserVerificationRequirement.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/UserVerificationRequirement.cs
new file mode 100644
index 00000000000..9052bd771da
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/UserVerificationRequirement.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn user verification requirement value.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#enumdef-userverificationrequirement
+ ///
+ /// 12
+ public enum UserVerificationRequirement
+ {
+ ///
+ /// None.
+ ///
+ None = 0,
+ ///
+ /// User verification required.
+ ///
+ Required = 1,
+ ///
+ /// User verification preferred.
+ ///
+ Preferred = 2,
+ ///
+ /// User verification discouraged.
+ ///
+ Discouraged = 3,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/WauthnError.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/WauthnError.cs
new file mode 100644
index 00000000000..abd7e816349
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/Enums/WauthnError.cs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using Tizen.Internals.Errors;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// WebAuthn error code.
+ ///
+ public enum WauthnError
+ {
+ ///
+ /// Successful.
+ ///
+ None = ErrorCode.None,
+ ///
+ /// Unknown error.
+ ///
+ Unknown = ErrorCode.Unknown,
+ ///
+ /// Invalid function parameter.
+ ///
+ InvalidParameter = ErrorCode.InvalidParameter,
+ ///
+ /// Permission denied.
+ ///
+ PermissionDenied = ErrorCode.PermissionDenied,
+ ///
+ /// Not supported operation.
+ ///
+ NotSupported = ErrorCode.NotSupported,
+ ///
+ /// Memory error.
+ ///
+ OutOfMemory = ErrorCode.OutOfMemory,
+ ///
+ /// Canceled by cancel request.
+ ///
+ Canceled = ErrorCode.Canceled,
+ ///
+ /// Timeout.
+ ///
+ TimedOut = ErrorCode.TimedOut,
+ ///
+ /// Authenticator is uncontactable.
+ ///
+ ConnectionRefused = ErrorCode.ConnectionRefused,
+ ///
+ /// Successful and needs to wait for other result.
+ ///
+ NoneAndWait = TizenErrorWebAuthn | 0x01,
+ ///
+ /// Not allowed in the current context.
+ ///
+ NotAllowed = TizenErrorWebAuthn | 0x02,
+ ///
+ /// Invalid State.
+ ///
+ InvalidState = TizenErrorWebAuthn | 0x03,
+ ///
+ /// Encoding operation failed.
+ ///
+ EncodingFailed = TizenErrorWebAuthn | 0x04,
+ ///
+ /// Socket error.
+ ///
+ Socket = TizenErrorWebAuthn | 0x05,
+ ///
+ /// Socket operation on non-socket error.
+ ///
+ NoSuchDevice = TizenErrorWebAuthn | 0x06,
+ ///
+ /// Socket access denied.
+ ///
+ AccessDenied = TizenErrorWebAuthn | 0x07,
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ErrorFactory.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ErrorFactory.cs
new file mode 100644
index 00000000000..0015d130d9c
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/ErrorFactory.cs
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Runtime.CompilerServices;
+using Tizen.Internals.Errors;
+
+namespace Tizen.Security.WebAuthn
+{
+ internal static class ErrorFactory
+ {
+ internal const int TizenErrorWebAuthn = -0x03100000;
+ private const string LogTag = "Tizen.Security.WebAuthn";
+
+ internal static void CheckErrNThrow(int err, string msg)
+ {
+ string fullMessage = $"[{LogTag}] {msg}, error={ErrorFacts.GetErrorMessage(err)}";
+
+ switch (err)
+ {
+ case (int)WauthnError.None:
+ return;
+ case (int)WauthnError.InvalidParameter:
+ throw new ArgumentException(fullMessage);
+ case (int)WauthnError.PermissionDenied:
+ throw new UnauthorizedAccessException(fullMessage);
+ case (int)WauthnError.NotSupported:
+ throw new NotSupportedException(fullMessage);
+ case (int)WauthnError.Canceled:
+ throw new OperationCanceledException(fullMessage);
+ case (int)WauthnError.TimedOut:
+ throw new TimeoutException(fullMessage);
+ default:
+ throw new InvalidOperationException(fullMessage);
+ }
+ }
+
+ internal static void CheckNullNThrow(object obj, [CallerArgumentExpression("obj")] string name = null)
+ {
+ if (obj is null)
+ throw new ArgumentNullException(name);
+ }
+ }
+}
+
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/GetAssertionCallbacks.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/GetAssertionCallbacks.cs
new file mode 100644
index 00000000000..b3a79daa60b
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/GetAssertionCallbacks.cs
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Callback function list used to get assertion with .
+ ///
+ /// 12
+ public class GetAssertionCallbacks
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Provided callbacks MUST NOT THROW.
+ ///
+ /// 12
+ ///
+ /// Callback function for displaying QR code.
+ /// The qr_contents are encoded as you can see in the encodeQRContents() function of the
+ /// FIDO specification:
+ /// https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#hybrid-qr-initiated.
+ /// The qr_contents is encoded like "FIDO:/0254318383..........7406596245".
+ /// The image to be displayed shall be created from qr_contents
+ /// with media vision API ().
+ /// If the request does not need to display a QR code
+ /// then this callback function won't be invoked.
+ ///
+ ///
+ /// Callback function for getting the final response.
+ /// Invoked when the response for the GetAssertion request need to be returned.
+ /// The result of the GetAssertion request may be one of the following:
+ /// * if the request is completed well,
+ /// * if the request is cancelled by a Cancel() request.
+ /// * if the server entered invalid state. Known causes:
+ /// - proxy issues,
+ /// - reached the limit of credentials stored by the authenticator.
+ /// * if the request times out. Known causes:
+ /// - authenticator does not respond during state assisted transactions due to
+ /// lack of push notifications support (e.g. missing Google Account).
+ ///
+ ///
+ /// Callback function for getting the updated linked device data. May be called multiple times.
+ /// Invoked when the response for the request
+ /// needs to be returned. The result of this request may be one of the following:
+ /// * if the request is completed well,
+ /// * if the request is cancelled by a Cancel() request.
+ /// * if the server entered invalid state. Known causes:
+ /// - proxy issues,
+ /// - reached the limit of credentials stored by the authenticator.
+ /// * if the request times out. Known causes:
+ /// - authenticator does not respond during state assisted transactions due to
+ /// lack of push notifications support (e.g. missing Google Account).
+ ///
+ /// User data to be passed to , and .
+ public GetAssertionCallbacks(
+ Action qrcodeCallback,
+ Action responseCallback,
+ Action linkedDataCallback,
+ object userData)
+ {
+ QrcodeCallback = qrcodeCallback;
+ ResponseCallback = responseCallback;
+ LinkedDataCallback = linkedDataCallback;
+ UserData = userData;
+ }
+
+ ///
+ /// Callback function for displaying QR code.
+ ///
+ public Action QrcodeCallback { get; init; }
+ ///
+ /// Callback function for getting the final response.
+ ///
+ public Action ResponseCallback { get; init; }
+ ///
+ /// Callback function for getting the updated linked device data.
+ ///
+ public Action LinkedDataCallback { get; init; }
+ ///
+ /// User data to be passed to , and .
+ ///
+ public object UserData { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/HybridLinkedData.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/HybridLinkedData.cs
new file mode 100644
index 00000000000..f12d8852cc0
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/HybridLinkedData.cs
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Interop;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Linked device data.
+ ///
+ ///
+ /// The linked device data is used for state assisted transaction.
+ /// From the successful QR initiated transaction, the linked device data
+ /// might be returned from an authenticator to a webauthn client
+ /// via or .
+ /// Then the client can store the linked device data and use it in the next call
+ /// for or .
+ /// Then the stated assisted transaction will start instead of QR initiated transaction.
+ ///
+ /// For more information, find a section with the keyword, "linking map",
+ /// from the following specification.
+ /// https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html
+ ///
+ /// For more information about state assisted transaction, refer to the following.
+ /// https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#hybrid-state-assisted
+ ///
+ /// 12
+ public class HybridLinkedData
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// More information on the CBOR format can be found in the following specification:
+ /// https://www.rfc-editor.org/rfc/rfc8949.html
+ ///
+ /// CBOR:"1".
+ /// CBOR:"2".
+ /// CBOR:"3".
+ /// CBOR:"4".
+ /// CBOR:"5".
+ /// CBOR:"6".
+ /// Domain String of tunnel server.
+ /// Identity Key created during QR initiated transaction.
+ public HybridLinkedData(
+ byte[] contactId,
+ byte[] linkId,
+ byte[] linkSecret,
+ byte[] authenticatorPubkey,
+ byte[] authenticatorName,
+ byte[] signature,
+ byte[] tunnelServerDomain,
+ byte[] identityKey)
+ {
+ ContactId = contactId;
+ LinkId = linkId;
+ LinkSecret = linkSecret;
+ AuthenticatorPubkey = authenticatorPubkey;
+ AuthenticatorName = authenticatorName;
+ Signature = signature;
+ TunnelServerDomain = tunnelServerDomain;
+ IdentityKey = identityKey;
+ }
+
+ internal HybridLinkedData(WauthnHybridLinkedData linkedData)
+ {
+ ContactId = NullSafeMarshal.PtrToArray(linkedData.contactId);
+ LinkId = NullSafeMarshal.PtrToArray(linkedData.linkId);
+ LinkSecret = NullSafeMarshal.PtrToArray(linkedData.linkSecret);
+ AuthenticatorPubkey = NullSafeMarshal.PtrToArray(linkedData.authenticatorPubkey);
+ AuthenticatorName = NullSafeMarshal.PtrToArray(linkedData.authenticatorName);
+ Signature = NullSafeMarshal.PtrToArray(linkedData.signature);
+ TunnelServerDomain = NullSafeMarshal.PtrToArray(linkedData.tunnelServerDomain);
+ IdentityKey = NullSafeMarshal.PtrToArray(linkedData.identityKey);
+ }
+
+ ///
+ /// CBOR:"1".
+ ///
+ public byte[] ContactId { get; init; }
+ ///
+ /// CBOR:"3".
+ ///
+ public byte[] LinkId { get; init; }
+ ///
+ /// CBOR:"3".
+ ///
+ public byte[] LinkSecret { get; init; }
+ ///
+ /// CBOR:"4".
+ ///
+ public byte[] AuthenticatorPubkey { get; init; }
+ ///
+ /// CBOR:"5".
+ ///
+ public byte[] AuthenticatorName { get; init; }
+ ///
+ /// CBOR:"6".
+ ///
+ public byte[] Signature { get; init; }
+ ///
+ /// Domain String of tunnel server.
+ ///
+ public byte[] TunnelServerDomain { get; init; }
+ ///
+ /// Identity Key created during QR initiated transaction.
+ ///
+ public byte[] IdentityKey { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/MakeCredentialCallbacks.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/MakeCredentialCallbacks.cs
new file mode 100644
index 00000000000..9d3ecf19485
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/MakeCredentialCallbacks.cs
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Callback function list used to make credential with .
+ ///
+ /// 12
+ public class MakeCredentialCallbacks
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Provided callbacks MUST NOT THROW.
+ ///
+ /// 12
+ ///
+ /// Callback function for displaying QR code.
+ /// The qr_contents are encoded as you can see in the encodeQRContents() function of the
+ /// FIDO specification:
+ /// https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#hybrid-qr-initiated.
+ /// The qr_contents is encoded like "FIDO:/0254318383..........7406596245".
+ /// The image to be displayed shall be created from qr_contents
+ /// with media vision API ().
+ /// If the request does not need to display a QR code
+ /// then this callback function won't be invoked.
+ ///
+ ///
+ /// Callback function for getting the final response.
+ /// Invoked when the response for the request
+ /// needs to be returned. The result of this request may be one of the following:
+ /// * if the request is completed well,
+ /// * if the request is cancelled by a Cancel() request.
+ /// * if the server entered invalid state. Known causes:
+ /// - proxy issues,
+ /// - reached the limit of credentials stored by the authenticator.
+ /// * if the request times out. Known causes:
+ /// - authenticator does not respond during state assisted transactions due to
+ /// lack of push notifications support (e.g. missing Google Account).
+ ///
+ ///
+ /// Callback function for getting the updated linked device data. May be called multiple times.
+ /// Invoked when the response for the get assertion request needs to be returned.
+ /// The result of the MakeCredential request may be one of the following:
+ /// * if the request is completed well,
+ /// * if the request is cancelled by a Cancel() request.
+ /// * if the server entered invalid state. Known causes:
+ /// - proxy issues,
+ /// - reached the limit of credentials stored by the authenticator.
+ /// * if the request times out. Known causes:
+ /// - authenticator does not respond during state assisted transactions due to
+ /// lack of push notifications support (e.g. missing Google Account).
+ ///
+ /// User data to be passed to , and .
+ public MakeCredentialCallbacks(
+ Action qrcodeCallback,
+ Action responseCallback,
+ Action linkedDataCallback,
+ object userData)
+ {
+ QrcodeCallback = qrcodeCallback;
+ ResponseCallback = responseCallback;
+ LinkedDataCallback = linkedDataCallback;
+ UserData = userData;
+ }
+
+ ///
+ /// Callback function for displaying QR code.
+ ///
+ public Action QrcodeCallback { get; init; }
+ ///
+ /// Callback function for getting the final response.
+ ///
+ public Action ResponseCallback { get; init; }
+ ///
+ /// Callback function for getting the updated linked device data.
+ ///
+ public Action LinkedDataCallback { get; init; }
+ ///
+ /// User data to be passed to , and .
+ ///
+ public object UserData { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/NullSafeMarshal.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/NullSafeMarshal.cs
new file mode 100644
index 00000000000..36dc2f6d90e
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/NullSafeMarshal.cs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using static Interop;
+
+namespace Tizen.Security.WebAuthn
+{
+ internal static class NullSafeMarshal
+ {
+ internal static byte[] PtrToArray(IntPtr ptr)
+ {
+ if (ptr == IntPtr.Zero)
+ return null;
+
+ return Marshal.PtrToStructure(ptr).ToArray();
+ }
+ }
+}
+
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAssertion.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAssertion.cs
new file mode 100644
index 00000000000..292a30e66a0
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAssertion.cs
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using static Interop;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Public key credential response for .
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#iface-pkcredential
+ /// https://www.w3.org/TR/webauthn-3/#sctn-credentialrequestoptions-extension
+ ///
+ /// 12
+ public class PubkeyCredAssertion
+ {
+ internal PubkeyCredAssertion(WauthnPubkeyCredentialAssertion assertion)
+ {
+ Id = NullSafeMarshal.PtrToArray(assertion.id);
+ Type = assertion.type;
+ RawId = NullSafeMarshal.PtrToArray(assertion.rawId);
+ Response = assertion.response != IntPtr.Zero ? new AuthenticatorAssertionResponse(
+ Marshal.PtrToStructure(assertion.response)) :
+ null;
+ AuthenticatorAttachment = assertion.authenticatorAttachment;
+
+ if (assertion.extensions != IntPtr.Zero)
+ {
+ var wauthnExts = Marshal.PtrToStructure(assertion.extensions);
+ var extensionsArray = new AuthenticationExtension[wauthnExts.size];
+ unsafe
+ {
+ var extPtr = (WauthnAuthenticationExt*)wauthnExts.descriptors;
+ for (int i = 0; i < (int)wauthnExts.size; i++)
+ {
+ var wauthnExt = Marshal.PtrToStructure(new IntPtr(extPtr + i * sizeof(WauthnAuthenticationExt)));
+ extensionsArray[i] = new AuthenticationExtension(wauthnExt);
+ }
+ }
+ Extensions = extensionsArray;
+ }
+ else
+ {
+ Extensions = null;
+ }
+
+ LinkedDevice = assertion.linkedDevice != IntPtr.Zero ?
+ new HybridLinkedData(Marshal.PtrToStructure(assertion.linkedDevice)) :
+ null;
+ }
+
+ ///
+ /// The base64url encoding of credential’s identifier.
+ ///
+ public byte[] Id { get; init; }
+ ///
+ /// The credential’s type.
+ ///
+ public PubkeyCredType Type { get; init; }
+ ///
+ /// The raw value of credential’s identifier.
+ ///
+ public byte[] RawId { get; init; }
+ ///
+ /// Authenticator's response.
+ ///
+ public AuthenticatorAssertionResponse Response { get; init; }
+ ///
+ /// Authenticator attachment modality.
+ ///
+ public AuthenticatorAttachment AuthenticatorAttachment { get; init; }
+ ///
+ /// The results of processing client extensions requested by the Relying Party
+ /// upon the Relying Party's invocation of GetAssertion(). (optional)
+ ///
+ public IEnumerable Extensions { get; init; }
+ ///
+ /// Linked Device Connection Info (optional).
+ /// If not null, the caller has to store this value and use this
+ /// in the next transaction to invoke state assisted transaction.
+ ///
+ public HybridLinkedData LinkedDevice { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAttestation.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAttestation.cs
new file mode 100644
index 00000000000..12368be29f2
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredAttestation.cs
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using static Interop;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Public key credential response for .
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#iface-pkcredential
+ /// https://www.w3.org/TR/webauthn-3/#sctn-credentialcreationoptions-extension
+ ///
+ /// 12
+ public class PubkeyCredAttestation
+ {
+ internal PubkeyCredAttestation(WauthnPubkeyCredentialAttestation attestation)
+ {
+ Id = NullSafeMarshal.PtrToArray(attestation.id);
+ Type = attestation.type;
+ RawId = NullSafeMarshal.PtrToArray(attestation.rawId);
+ Response = attestation.response != IntPtr.Zero ?
+ new AuthenticatorAttestationResponse(Marshal.PtrToStructure(attestation.response)) :
+ null;
+ AuthenticatorAttachment = attestation.authenticatorAttachment;
+
+ if (attestation.extensions != IntPtr.Zero)
+ {
+ var wauthnExts = Marshal.PtrToStructure(attestation.extensions);
+ var extensionsArray = new AuthenticationExtension[wauthnExts.size];
+ unsafe
+ {
+ var extPtr = (WauthnAuthenticationExt*)wauthnExts.descriptors;
+ for (int i = 0; i < (int)wauthnExts.size; i++)
+ {
+ var wauthnExt = Marshal.PtrToStructure(new IntPtr(extPtr + i * sizeof(WauthnAuthenticationExt)));
+ extensionsArray[i] = new AuthenticationExtension(wauthnExt);
+ }
+ }
+ Extensions = extensionsArray;
+ }
+ else
+ {
+ Extensions = null;
+ }
+
+ LinkedDevice = attestation.linkedDevice != IntPtr.Zero ?
+ new HybridLinkedData(Marshal.PtrToStructure(attestation.linkedDevice)) :
+ null;
+ }
+
+ ///
+ /// The base64url encoding of credential’s identifier.
+ ///
+ public byte[] Id { get; init; }
+ ///
+ /// The credential’s type.
+ ///
+ public PubkeyCredType Type { get; init; }
+ ///
+ /// The raw value of credential’s identifier.
+ ///
+ public byte[] RawId { get; init; }
+ ///
+ /// Authenticator's response.
+ ///
+ public AuthenticatorAttestationResponse Response { get; init; }
+ ///
+ /// Authenticator attachment modality.
+ ///
+ public AuthenticatorAttachment AuthenticatorAttachment { get; init; }
+ ///
+ /// The results of processing client extensions requested by the Relying Party
+ /// upon the Relying Party's invocation of MakeCredential(). (optional)
+ ///
+ public IEnumerable Extensions { get; init; }
+ ///
+ /// Linked Device Connection Info (optional).
+ /// If not null, the caller has to store this value and use thi
+ /// in the next transaction to invoke state assisted transaction.
+ ///
+ public HybridLinkedData LinkedDevice { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredCreationOptions.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredCreationOptions.cs
new file mode 100644
index 00000000000..9f812041609
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredCreationOptions.cs
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System.Collections.Generic;
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Make credential options.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialcreationoptions
+ ///
+ /// 12
+ public class PubkeyCredCreationOptions
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// /// 12
+ /// Contains a name and an identifier for the Relying Party responsible for the request.
+ /// Contains names and an identifier for the user account performing the registration.
+ ///
+ /// Lists the key types and signature algorithms the Relying Party supports,
+ /// ordered from most preferred to least preferred.
+ ///
+ ///
+ /// Specifies a time, in milliseconds,
+ /// that the Relying Party is willing to wait for the call to complete.
+ /// This is treated as a hint, and MAY be overridden by the client.
+ /// The value, '0', means no timeout is set. (optional)
+ ///
+ ///
+ /// The Relying Party SHOULD use this argument to list any existing credentials mapped
+ /// to this user account (as identified by user.id). (optional)
+ ///
+ ///
+ /// The Relying Party MAY use his argument to specify capabilities and settings that the
+ /// authenticator MUST or SHOULD satisfy to participate in this operation. (optional)
+ ///
+ ///
+ /// Contains zero or more elements from to
+ /// guide the user agent in interacting with the user. (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to specify a preference regarding attestation conveyance.
+ /// The default value is . (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to specify a preference regarding the attestation
+ /// statement format used by the authenticator. The default value is the empty list, which
+ /// indicates no preference. (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to provide client extension inputs requesting
+ /// additional processing by the client and authenticator. (optional)
+ ///
+ ///
+ /// Linked Device Connection Info. Optional.
+ /// If not null, the state assisted transaction will start.
+ ///
+ public PubkeyCredCreationOptions(
+ RelyingPartyEntity rp,
+ UserEntity user,
+ IEnumerable pubkeyCredParams,
+ ulong timeout = 0,
+ IEnumerable excludeCredentials = null,
+ AuthenticationSelectionCriteria authenticatorSelection = null,
+ IEnumerable hints = null,
+ AttestationPref attestation = AttestationPref.None,
+ IEnumerable attestationFormats = null,
+ IEnumerable extensions = null,
+ HybridLinkedData linkedDevice = null)
+ {
+ Rp = rp;
+ User = user;
+ PubkeyCredParams = pubkeyCredParams;
+ Timeout = timeout;
+ ExcludeCredentials = excludeCredentials;
+ AuthenticatorSelection = authenticatorSelection;
+ Hints = hints;
+ Attestation = attestation;
+ AttestationFormats = attestationFormats;
+ Extensions = extensions;
+ LinkedDevice = linkedDevice;
+ }
+
+ ///
+ /// Contains a name and an identifier for the Relying Party responsible for the request.
+ ///
+ public RelyingPartyEntity Rp { get; init; }
+ ///
+ /// Contains names and an identifier for the user account performing the registration.
+ ///
+ public UserEntity User { get; init; }
+ ///
+ /// Lists the key types and signature algorithms the Relying Party supports,
+ /// ordered from most preferred to least preferred.
+ ///
+ public IEnumerable PubkeyCredParams { get; init; }
+ ///
+ /// Specifies a time, in milliseconds, that the Relying Party is willing to wait for the
+ /// call to complete. This is treated as a hint, and MAY be overridden by the client.
+ /// The value, '0', means no timeout is set.
+ ///
+ public ulong Timeout { get; init; }
+ ///
+ /// Lists any existing credentials mapped to this user account (as identified by user.id).
+ ///
+ public IEnumerable ExcludeCredentials { get; init; }
+ ///
+ /// Specifies capabilities and settings that the authenticator MUST or SHOULD satisfy
+ /// to participate in this operation.
+ ///
+ public AuthenticationSelectionCriteria AuthenticatorSelection { get; init; }
+ ///
+ /// Contains zero or more elements from to
+ /// guide the user agent in interacting with the user.
+ ///
+ public IEnumerable Hints { get; init; }
+ ///
+ /// Specifies a preference regarding attestation conveyance.
+ ///
+ public AttestationPref Attestation { get; init; }
+ ///
+ /// Specifies a preference regarding the attestation statement format used by the authenticator.
+ ///
+ public IEnumerable AttestationFormats { get; init; }
+ ///
+ /// Client extension inputs requesting additional processing by the client and authenticator.
+ ///
+ public IEnumerable Extensions { get; init; }
+ ///
+ /// Linked Device Connection Info. If not null, the state assisted transaction will start.
+ ///
+ public HybridLinkedData LinkedDevice { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredDescriptor.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredDescriptor.cs
new file mode 100644
index 00000000000..f1a6523318b
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredDescriptor.cs
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Public key credential descriptor.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialdescriptor
+ ///
+ /// 12
+ public class PubkeyCredDescriptor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of the public key credential.
+ /// The credential ID of the public key credential.
+ /// To represent multiple transports, this enum can be ORed multiple times.
+ public PubkeyCredDescriptor(PubkeyCredType type, byte[] id, AuthenticatorTransport transport)
+ {
+ Type = type;
+ Id = id;
+ Transport = transport;
+ }
+ ///
+ /// The type of the public key credential.
+ ///
+ public PubkeyCredType Type { get; init; }
+ ///
+ /// The credential ID of the public key credential.
+ ///
+ public byte[] Id { get; init; }
+ ///
+ /// Transport types.
+ ///
+ public AuthenticatorTransport Transport { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredParam.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredParam.cs
new file mode 100644
index 00000000000..762b1195b55
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredParam.cs
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Parameter for credential generation.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialparameters
+ ///
+ /// 12
+ public class PubkeyCredParam
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ /// Well-known credential type specifying a credential to create.
+ /// Well-known COSE algorithm specifying the algorithm to use for the credential.
+ public PubkeyCredParam(PubkeyCredType type, CoseAlgorithm alg)
+ {
+ Type = type;
+ Alg = alg;
+ }
+ ///
+ /// Well-known credential type specifying a credential to create.
+ ///
+ public PubkeyCredType Type { get; init; }
+ ///
+ /// Well-known COSE algorithm specifying the algorithm to use for the credential.
+ ///
+ public CoseAlgorithm Alg { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredRequestOptions.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredRequestOptions.cs
new file mode 100644
index 00000000000..3df50f33ae0
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/PubkeyCredRequestOptions.cs
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System.Collections.Generic;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Get assertion options.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictionary-assertion-options
+ ///
+ /// 12
+ public class PubkeyCredRequestOptions
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ ///
+ /// Specifies a time, in milliseconds, that the Relying Party is willing to wait for the
+ /// call to complete. This is treated as a hint, and MAY be overridden by the client.
+ /// The value, '0', means no timeout is set. (optional)
+ ///
+ ///
+ /// Specifies the RP ID claimed by the Relying Party. (optional)
+ ///
+ ///
+ /// Used by the client to find authenticators eligible for this authentication ceremony. (optional)
+ ///
+ ///
+ /// Specifies the Relying Party's requirements regarding user verification for the
+ /// GetAssertion() operation. The default value is . (optional)
+ ///
+ ///
+ /// Contains zero or more elements from to
+ /// guide the user agent in interacting with the user. (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to specify a preference regarding
+ /// attestation conveyance. The default value is . (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to specify a preference regarding the attestation
+ /// statement format used by the authenticator. The default value is the empty list,
+ /// which indicates no preference. (optional)
+ ///
+ ///
+ /// The Relying Party MAY use this argument to provide client extension inputs requesting
+ /// additional processing by the client and authenticator. (optional)
+ ///
+ ///
+ /// Linked Device Connection Info. Optional.
+ /// If not null, the state assisted transaction will start.
+ ///
+ public PubkeyCredRequestOptions(
+ ulong timeout = 0,
+ string rpId = null,
+ IEnumerable allowCredentials = null,
+ UserVerificationRequirement userVerification = UserVerificationRequirement.Preferred,
+ IEnumerable hints = null,
+ AttestationPref attestation = AttestationPref.None,
+ IEnumerable attestationFormats = null,
+ IEnumerable extensions = null,
+ HybridLinkedData linkedDevice = null)
+ {
+ Timeout = timeout;
+ RpId = rpId;
+ AllowCredentials = allowCredentials;
+ UserVerification = userVerification;
+ Hints = hints;
+ Attestation = attestation;
+ AttestationFormats = attestationFormats;
+ Extensions = extensions;
+ LinkedDevice = linkedDevice;
+ }
+
+ ///
+ /// Specifies a time, in milliseconds, that the Relying Party is willing to wait for the
+ /// call to complete. This is treated as a hint, and MAY be overridden by the client.
+ /// The value, '0', means no timeout is set.
+ ///
+ public ulong Timeout { get; init; }
+ ///
+ /// Specifies the RP ID claimed by the Relying Party.
+ ///
+ public string RpId { get; init; }
+ ///
+ /// Used by the client to find authenticators eligible for this authentication ceremony.
+ ///
+ public IEnumerable AllowCredentials { get; init; }
+ ///
+ /// Specifies the Relying Party's requirements regarding user verification for the GetAssertion() operation.
+ ///
+ public UserVerificationRequirement UserVerification { get; init; }
+ ///
+ /// Contains zero or more elements from to
+ /// guide the user agent in interacting with the user.
+ ///
+ public IEnumerable Hints { get; init; }
+ ///
+ /// Specifies a preference regarding attestation conveyance.
+ ///
+ public AttestationPref Attestation { get; init; }
+ ///
+ /// Specifies a preference regarding the attestation statement format used by the authenticator.
+ ///
+ public IEnumerable AttestationFormats { get; init; }
+ ///
+ /// Client extension inputs requesting additional processing by the client and authenticator.
+ ///
+ public IEnumerable Extensions { get; init; }
+ ///
+ /// Linked Device Connection Info. If not null, the state assisted transaction will start.
+ ///
+ public HybridLinkedData LinkedDevice { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/RelyingPartyEntity.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/RelyingPartyEntity.cs
new file mode 100644
index 00000000000..f00fdec4fc6
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/RelyingPartyEntity.cs
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// Relying Party entity.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialrpentity
+ ///
+ /// 12
+ public class RelyingPartyEntity
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ /// The name of RP.
+ /// The RPID.
+ public RelyingPartyEntity(string name, string id)
+ {
+ Name = name;
+ Id = id;
+ }
+
+ ///
+ /// The name of RP.
+ ///
+ public string Name { get; init; }
+ ///
+ /// The RPID.
+ ///
+ public string Id { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UnmanagedMemory.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UnmanagedMemory.cs
new file mode 100644
index 00000000000..2ada7c055f6
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UnmanagedMemory.cs
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Security.WebAuthn
+{
+ internal class UnmanagedMemory : IDisposable
+ {
+ private bool _disposed = false;
+ IntPtr _memory = IntPtr.Zero;
+
+ public UnmanagedMemory()
+ {}
+
+ public UnmanagedMemory(object obj)
+ {
+ _memory = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
+ Marshal.StructureToPtr(obj, _memory, false);
+ }
+
+
+ public UnmanagedMemory(string obj)
+ {
+ _memory = Marshal.StringToHGlobalAnsi(obj);
+ }
+
+ unsafe private UnmanagedMemory(IntPtr pinned, int size)
+ {
+ _memory = Marshal.AllocHGlobal(size);
+ Buffer.MemoryCopy((void*)pinned, (void*)_memory, size, size);
+ }
+
+ ~UnmanagedMemory()
+ {
+ Dispose(false);
+ }
+
+ public static UnmanagedMemory PinArray(T[] array) where T : struct
+ {
+ if (array is null)
+ return new UnmanagedMemory();
+
+ GCHandle pinnedArray = GCHandle.Alloc(array, GCHandleType.Pinned);
+ var ret = new UnmanagedMemory(pinnedArray.AddrOfPinnedObject(), Marshal.SizeOf(array[0]) * array.Length);
+ pinnedArray.Free();
+ return ret;
+ }
+
+ public static implicit operator IntPtr(UnmanagedMemory pinned)
+ {
+ return pinned._memory;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ return;
+ if (_memory != IntPtr.Zero)
+ Marshal.FreeHGlobal(_memory);
+
+ _memory = IntPtr.Zero;
+ _disposed = true;
+ }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UserEntity.cs b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UserEntity.cs
new file mode 100644
index 00000000000..6eb65e12145
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/Tizen.Security.WebAuthn/UserEntity.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+using static Tizen.Security.WebAuthn.ErrorFactory;
+
+namespace Tizen.Security.WebAuthn
+{
+ ///
+ /// User entity.
+ ///
+ ///
+ /// Refer to the following W3C specification for more information.
+ /// https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialuserentity
+ ///
+ /// 12
+ public class UserEntity
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 12
+ /// A human-palatable name for the entity.
+ ///
+ /// The ID of the user account. An ID is a byte sequence with a maximum size of 64 bytes,
+ /// and is not meant to be displayed to the user.
+ ///
+ /// A human-palatable name for the user account, intended only for display.
+ public UserEntity(string name, byte[] id, string displayName)
+ {
+ Name = name;
+ Id = id;
+ DisplayName = displayName;
+ }
+
+ ///
+ /// A human-palatable name for the entity.
+ ///
+ public string Name { get; init; }
+ ///
+ /// The ID of the user account.
+ ///
+ public byte[] Id { get; init; }
+ ///
+ /// A human-palatable name for the user account, intended only for display.
+ ///
+ public string DisplayName { get; init; }
+ }
+}
diff --git a/src/Tizen.Security.WebAuthn/doc/api/Tizen.Security.WebAuthn.md b/src/Tizen.Security.WebAuthn/doc/api/Tizen.Security.WebAuthn.md
new file mode 100644
index 00000000000..1a66141c89b
--- /dev/null
+++ b/src/Tizen.Security.WebAuthn/doc/api/Tizen.Security.WebAuthn.md
@@ -0,0 +1,21 @@
+---
+uid: Tizen.Security.WebAuthn
+summary: The Web Authentication module provides a C# API enabling the creation and use of
+ strong, attested, scoped, public key-based credentials by web applications, for the
+ purpose of strongly authenticating users
+remarks: *content
+---
+## Overview
+It provides an [Authenticator](xref:Tizen.Security.WebAuthn.Authenticator) class containing methods for creating public key-based credentials
+([Authenticator.MakeCredential()](xref:Tizen.Security.WebAuthn.Authenticator.MakeCredential(Tizen.Security.WebAuthn.ClientData,Tizen.Security.WebAuthn.PubkeyCredCreationOptions,Tizen.Security.WebAuthn.MakeCredentialCallbacks))) and using them ([Authenticator.GetAssertion()](xref:Tizen.Security.WebAuthn.Authenticator.GetAssertion(Tizen.Security.WebAuthn.ClientData,Tizen.Security.WebAuthn.PubkeyCredRequestOptions,Tizen.Security.WebAuthn.GetAssertionCallbacks))). Both these operations are performed asynchronously. Callbacks passed as arguments are used to notify about the progress
+or when user's interaction is necessary. Due to significant amount of time required to complete both
+requests, cancelation is also possible with the help of Authenticator.Cancel(). The module also
+provides a variety of data types based on W3C Web Authentication API (https://www.w3.org/TR/webauthn-3/)
+used to control the credential creation and assertion process.
+
+## Related features
+This module is related with the following features:
+ * http://tizen.org/feature/security.webauthn
+ * http://tizen.org/feature/network.bluetooth.le
+ * and network connection features (http://tizen.org/feature/network.wifi, http://tizen.org/feature/network.ethernet, http://tizen.org/feature/network.telephony)
+