Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Account.FidoClient / Tizen.Account.FidoClient / UafAuthenticatorFinder.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Threading.Tasks;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.Account.FidoClient
23 {
24     /// <summary>
25     /// Class to find available FIDO specific authenticators on the device
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public static class UafAuthenticatorFinder
29     {
30         /// <summary>
31         /// Retrieves  all the available FIDO authenticators supported by this Device.
32         /// </summary>
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>
39
40         /// <example>
41         /// <code>
42         ///     IEnumerable<AuthenticatorInformation> authInfos = await UafAuthenticatorFinder.DiscoverAuthenticatorsAsync();
43         ///     foreach (AuthenticatorInformation authInfo in authInfos)
44         ///     {
45         ///         string aaid = authInfo.Aaid;
46         ///         string title = authInfo.Title;
47         ///     }
48         /// </code>
49         /// </example>
50         public static async Task<IEnumerable<AuthenticatorInformation>> DiscoverAuthenticatorsAsync()
51         {
52             IEnumerable<AuthenticatorInformation> result = null;
53             await Task.Run(() => result = Discover());
54             return result;
55         }
56
57         private static IEnumerable<AuthenticatorInformation> Discover()
58         {
59             IList<AuthenticatorInformation> result = new List<AuthenticatorInformation>();
60
61             Interop.UafAuthenticator.FidoAuthenticatorCallback cb = (IntPtr authHandle, IntPtr userData) =>
62             {
63                 Log.Info(ErrorFactory.LogTag, "Iterating authenticators");
64                 result.Add(GetAuthInfo(authHandle));
65             };
66
67             int ret = Interop.UafAuthenticator.ForeachAuthenticator(cb, IntPtr.Zero);
68             if(ret != (int)FidoErrorCode.None)
69             {
70                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
71                 throw ErrorFactory.GetException(ret);
72             }
73
74             return result;
75         }
76
77         private static AuthenticatorInformation GetAuthInfo(IntPtr authHandle)
78         {
79             var authInfo = new AuthenticatorInformation();
80
81             IntPtr stringPtr;
82             int ret = Interop.UafAuthenticator.GetTitle(authHandle, out stringPtr);
83             if (ret != (int)FidoErrorCode.None)
84             {
85                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
86                 throw ErrorFactory.GetException(ret);
87             }
88             authInfo.Title = Marshal.PtrToStringAnsi(stringPtr);
89             Interop.Libc.Free(stringPtr);
90
91             ret = Interop.UafAuthenticator.GetAaid(authHandle, out stringPtr);
92             if (ret != (int)FidoErrorCode.None)
93             {
94                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
95                 throw ErrorFactory.GetException(ret);
96             }
97             authInfo.Aaid = Marshal.PtrToStringAnsi(stringPtr);
98             Interop.Libc.Free(stringPtr);
99
100             ret = Interop.UafAuthenticator.GetDescription(authHandle, out stringPtr);
101             if (ret != (int)FidoErrorCode.None)
102             {
103                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
104                 throw ErrorFactory.GetException(ret);
105             }
106             authInfo.Description = Marshal.PtrToStringAnsi(stringPtr);
107             Interop.Libc.Free(stringPtr);
108
109             ret = Interop.UafAuthenticator.GetAssertionScheme(authHandle, out stringPtr);
110             if (ret != (int)FidoErrorCode.None)
111             {
112                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
113                 throw ErrorFactory.GetException(ret);
114             }
115             authInfo.AssertionScheme = Marshal.PtrToStringAnsi(stringPtr);
116             Interop.Libc.Free(stringPtr);
117
118             int authAlgo;
119             ret = Interop.UafAuthenticator.GetAlgorithm(authHandle, out authAlgo);
120             if (ret != (int)FidoErrorCode.None)
121             {
122                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
123                 throw ErrorFactory.GetException(ret);
124             }
125
126             int usrVerificationMethod;
127             ret = Interop.UafAuthenticator.GetVerificationMethod(authHandle, out usrVerificationMethod);
128             if (ret != (int)FidoErrorCode.None)
129             {
130                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
131                 throw ErrorFactory.GetException(ret);
132             }
133
134             int keyProtectionType;
135             ret = Interop.UafAuthenticator.GetKeyProtectionMethod(authHandle, out keyProtectionType);
136             if (ret != (int)FidoErrorCode.None)
137             {
138                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
139                 throw ErrorFactory.GetException(ret);
140             }
141
142             int matcherProtection;
143             ret = Interop.UafAuthenticator.GetMatcherProtectionMethod(authHandle, out matcherProtection);
144             if (ret != (int)FidoErrorCode.None)
145             {
146                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
147                 throw ErrorFactory.GetException(ret);
148             }
149
150             int attachmentHint;
151             ret = Interop.UafAuthenticator.GetAttachmentHint(authHandle, out attachmentHint);
152             if (ret != (int)FidoErrorCode.None)
153             {
154                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
155                 throw ErrorFactory.GetException(ret);
156             }
157
158             bool isSecondaryOnly = Interop.UafAuthenticator.GetIsSecondFactorOnly(authHandle);
159
160             int tcDisplayType;
161             ret = Interop.UafAuthenticator.GetTcDiscplay(authHandle, out tcDisplayType);
162             if (ret != (int)FidoErrorCode.None)
163             {
164                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
165                 throw ErrorFactory.GetException(ret);
166             }
167
168             ret = Interop.UafAuthenticator.GetTcDisplayType(authHandle, out stringPtr);
169             if (ret != (int)FidoErrorCode.None)
170             {
171                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
172                 throw ErrorFactory.GetException(ret);
173             }
174             authInfo.TcDisplayContentType = Marshal.PtrToStringAnsi(stringPtr);
175             Interop.Libc.Free(stringPtr);
176
177             ret = Interop.UafAuthenticator.GetIcon(authHandle, out stringPtr);
178             if (ret != (int)FidoErrorCode.None)
179             {
180                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
181                 throw ErrorFactory.GetException(ret);
182             }
183             authInfo.Icon = Marshal.PtrToStringAnsi(stringPtr);
184             Interop.Libc.Free(stringPtr);
185
186             var attestationTypes = new List<AuthenticatorAttestationType> ();
187             Interop.UafAuthenticator.FidoAttestationTypeCallback cb = (int type, IntPtr usrData) =>
188             {
189                 attestationTypes.Add((AuthenticatorAttestationType)type);
190             };
191
192             ret = Interop.UafAuthenticator.ForeachAttestationType(authHandle, cb, IntPtr.Zero);
193             if (ret != (int)FidoErrorCode.None)
194             {
195                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
196                 throw ErrorFactory.GetException(ret);
197             }
198
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;
207
208             return authInfo;
209         }
210     }
211 }