2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Threading.Tasks;
20 using System.Runtime.InteropServices;
22 namespace Tizen.Account.FidoClient
25 /// Class to find available FIDO specific authenticators on the device
27 /// <since_tizen> 3 </since_tizen>
28 public static class UafAuthenticatorFinder
31 /// Retrieves all the available FIDO authenticators supported by this Device.
33 /// <since_tizen> 3 </since_tizen>
34 /// <returns>Enumerable list of authenticators</returns>
35 /// <privilege>http://tizen.org/privilege/fido.client</privilege>
36 /// <feature>http://tizen.org/feature/fido.uaf</feature>
37 /// <exception cref="UnauthorizedAccessException">Thrown when the application does not have privilege to access this method</exception>
38 /// <exception cref="NotSupportedException">FIDO is not supported</exception>
42 /// IEnumerable<AuthenticatorInformation> authInfos = await UafAuthenticatorFinder.DiscoverAuthenticatorsAsync();
43 /// foreach (AuthenticatorInformation authInfo in authInfos)
45 /// string aaid = authInfo.Aaid;
46 /// string title = authInfo.Title;
50 public static async Task<IEnumerable<AuthenticatorInformation>> DiscoverAuthenticatorsAsync()
52 IEnumerable<AuthenticatorInformation> result = null;
53 await Task.Run(() => result = Discover());
57 private static IEnumerable<AuthenticatorInformation> Discover()
59 IList<AuthenticatorInformation> result = new List<AuthenticatorInformation>();
61 Interop.UafAuthenticator.FidoAuthenticatorCallback cb = (IntPtr authHandle, IntPtr userData) =>
63 Log.Info(ErrorFactory.LogTag, "Iterating authenticators");
64 result.Add(GetAuthInfo(authHandle));
67 int ret = Interop.UafAuthenticator.ForeachAuthenticator(cb, IntPtr.Zero);
68 if(ret != (int)FidoErrorCode.None)
70 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
71 throw ErrorFactory.GetException(ret);
77 private static AuthenticatorInformation GetAuthInfo(IntPtr authHandle)
79 var authInfo = new AuthenticatorInformation();
82 int ret = Interop.UafAuthenticator.GetTitle(authHandle, out stringPtr);
83 if (ret != (int)FidoErrorCode.None)
85 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
86 throw ErrorFactory.GetException(ret);
88 authInfo.Title = Marshal.PtrToStringAnsi(stringPtr);
89 Interop.Libc.Free(stringPtr);
91 ret = Interop.UafAuthenticator.GetAaid(authHandle, out stringPtr);
92 if (ret != (int)FidoErrorCode.None)
94 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
95 throw ErrorFactory.GetException(ret);
97 authInfo.Aaid = Marshal.PtrToStringAnsi(stringPtr);
98 Interop.Libc.Free(stringPtr);
100 ret = Interop.UafAuthenticator.GetDescription(authHandle, out stringPtr);
101 if (ret != (int)FidoErrorCode.None)
103 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
104 throw ErrorFactory.GetException(ret);
106 authInfo.Description = Marshal.PtrToStringAnsi(stringPtr);
107 Interop.Libc.Free(stringPtr);
109 ret = Interop.UafAuthenticator.GetAssertionScheme(authHandle, out stringPtr);
110 if (ret != (int)FidoErrorCode.None)
112 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
113 throw ErrorFactory.GetException(ret);
115 authInfo.AssertionScheme = Marshal.PtrToStringAnsi(stringPtr);
116 Interop.Libc.Free(stringPtr);
119 ret = Interop.UafAuthenticator.GetAlgorithm(authHandle, out authAlgo);
120 if (ret != (int)FidoErrorCode.None)
122 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
123 throw ErrorFactory.GetException(ret);
126 int usrVerificationMethod;
127 ret = Interop.UafAuthenticator.GetVerificationMethod(authHandle, out usrVerificationMethod);
128 if (ret != (int)FidoErrorCode.None)
130 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
131 throw ErrorFactory.GetException(ret);
134 int keyProtectionType;
135 ret = Interop.UafAuthenticator.GetKeyProtectionMethod(authHandle, out keyProtectionType);
136 if (ret != (int)FidoErrorCode.None)
138 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
139 throw ErrorFactory.GetException(ret);
142 int matcherProtection;
143 ret = Interop.UafAuthenticator.GetMatcherProtectionMethod(authHandle, out matcherProtection);
144 if (ret != (int)FidoErrorCode.None)
146 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
147 throw ErrorFactory.GetException(ret);
151 ret = Interop.UafAuthenticator.GetAttachmentHint(authHandle, out attachmentHint);
152 if (ret != (int)FidoErrorCode.None)
154 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
155 throw ErrorFactory.GetException(ret);
158 bool isSecondaryOnly = Interop.UafAuthenticator.GetIsSecondFactorOnly(authHandle);
161 ret = Interop.UafAuthenticator.GetTcDiscplay(authHandle, out tcDisplayType);
162 if (ret != (int)FidoErrorCode.None)
164 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
165 throw ErrorFactory.GetException(ret);
168 ret = Interop.UafAuthenticator.GetTcDisplayType(authHandle, out stringPtr);
169 if (ret != (int)FidoErrorCode.None)
171 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
172 throw ErrorFactory.GetException(ret);
174 authInfo.TcDisplayContentType = Marshal.PtrToStringAnsi(stringPtr);
175 Interop.Libc.Free(stringPtr);
177 ret = Interop.UafAuthenticator.GetIcon(authHandle, out stringPtr);
178 if (ret != (int)FidoErrorCode.None)
180 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
181 throw ErrorFactory.GetException(ret);
183 authInfo.Icon = Marshal.PtrToStringAnsi(stringPtr);
184 Interop.Libc.Free(stringPtr);
186 var attestationTypes = new List<AuthenticatorAttestationType> ();
187 Interop.UafAuthenticator.FidoAttestationTypeCallback cb = (int type, IntPtr usrData) =>
189 attestationTypes.Add((AuthenticatorAttestationType)type);
192 ret = Interop.UafAuthenticator.ForeachAttestationType(authHandle, cb, IntPtr.Zero);
193 if (ret != (int)FidoErrorCode.None)
195 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
196 throw ErrorFactory.GetException(ret);
199 authInfo.AuthenticationAlgorithm = (AuthenticationAlgorithm)authAlgo;
200 authInfo.UserVerification = (UserVerificationMethod)usrVerificationMethod;
201 authInfo.KeyProtection = (KeyProtectionType)keyProtectionType;
202 authInfo.MatcherProtection = (MatcherProtectionType)matcherProtection;
203 authInfo.AttachmentHint = (AuthenticatorAttachmentHint)attachmentHint;
204 authInfo.IsSecondFactorOnly = isSecondaryOnly;
205 authInfo.TcDisplayType = (TransactionConfirmationDisplayType)tcDisplayType;
206 authInfo.AttestationTypes = attestationTypes;