3a655efca503f980cbaa7b26bb28f64b398e38bf
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Smartcard / Tizen.Network.Smartcard / SmartcardChannel.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.Runtime.InteropServices;
19 using System.Collections.Generic;
20
21 namespace Tizen.Network.Smartcard
22 {
23     /// <summary>
24     /// A class for Smartcard channel informations. It allows applications to handle channel informations.
25     /// </summary>
26     /// <privilege>http://tizen.org/privilege/secureelement</privilege>
27     public class SmartcardChannel : IDisposable
28     {
29         private int _channelHandle = -1;
30         private bool disposed = false;
31         private SmartcardSession _sessionObject;
32
33         /// <summary>
34         /// Whether the kind of channel is basic.
35         /// </summary>
36         public bool IsBasicChannel
37         {
38             get
39             {
40                 bool isBasicChannel;
41                 int ret = Interop.Smartcard.Channel.ChannelIsBasicChannel(_channelHandle, out isBasicChannel);
42                 if (ret != (int)SmartcardError.None)
43                 {
44                     Log.Error(Globals.LogTag, "Failed to get basic channel, Error - " + (SmartcardError)ret);
45                 }
46                 return isBasicChannel;
47             }
48         }
49
50         /// <summary>
51         /// Whether the kind of channel is logical.
52         /// </summary>
53         public bool IsLogicalChannel
54         {
55             get
56             {
57                 bool isBasicChannel;
58                 int ret = Interop.Smartcard.Channel.ChannelIsBasicChannel(_channelHandle, out isBasicChannel);
59                 if (ret != (int)SmartcardError.None)
60                 {
61                     Log.Error(Globals.LogTag, "Failed to get logical channel, Error - " + (SmartcardError)ret);
62                 }
63                 return !isBasicChannel;
64             }
65         }
66
67         /// <summary>
68         /// Whether the channel is closed.
69         /// </summary>
70         public bool IsClosed
71         {
72             get
73             {
74                 bool isClosed;
75                 int ret = Interop.Smartcard.Channel.ChannelIsClosed(_channelHandle, out isClosed);
76                 if (ret != (int)SmartcardError.None)
77                 {
78                     Log.Error(Globals.LogTag, "Failed to get closed, Error - " + (SmartcardError)ret);
79                 }
80                 return isClosed;
81             }
82         }
83
84         /// <summary>
85         /// The session that has opened the given channel.
86         /// </summary>
87         public SmartcardSession Session
88         {
89             get
90             {
91                 int session;
92                 int ret = Interop.Smartcard.Channel.ChannelGetSession(_channelHandle, out session);
93                 if (ret != (int)SmartcardError.None)
94                 {
95                     Log.Error(Globals.LogTag, "Failed to get session, Error - " + (SmartcardError)ret);
96                 }
97
98                 if (_sessionObject.GetHandle() != session)
99                 {
100                     Log.Error(Globals.LogTag, "Does not correspond with session, Error - " + _sessionObject.GetHandle() + " " + session);
101                 }
102
103                 return _sessionObject;
104             }
105         }
106
107         internal SmartcardChannel(SmartcardSession sessionHandle, int channelHandle)
108         {
109             _sessionObject = sessionHandle;
110             _channelHandle = channelHandle;
111         }
112
113         ~SmartcardChannel()
114         {
115             Dispose(false);
116         }
117
118         public void Dispose()
119         {
120             Dispose(true);
121             GC.SuppressFinalize(this);
122         }
123
124         private void Dispose(bool disposing)
125         {
126             if (disposed)
127                 return;
128
129             if (disposing)
130             {
131                 // Free managed objects.
132             }
133             //Free unmanaged objects
134             disposed = true;
135         }
136
137         /// <summary>
138         /// Closes the given channel to the Secure Element.
139         /// </summary>
140         public void Close()
141         {
142             int ret = Interop.Smartcard.Channel.ChannelClose(_channelHandle);
143             if (ret != (int)SmartcardError.None)
144             {
145                 Log.Error(Globals.LogTag, "Failed to channel close, Error - " + (SmartcardError)ret);
146                 SmartcardErrorFactory.ThrowSmartcardException(ret);
147             }
148             Dispose(true);
149         }
150
151         /// <summary>
152         /// Gets the response to the select command.
153         /// </summary>
154         /// <returns>Byte array to retrieve the SELECT response.</returns>
155         public byte[] GetSelectedResponse()
156         {
157             byte[] respList;
158             IntPtr strAtr;
159             int len;
160             int ret = Interop.Smartcard.Channel.ChannelGetSelectResponse(_channelHandle, out strAtr, out len);
161             if (ret != (int)SmartcardError.None)
162             {
163                 Log.Error(Globals.LogTag, "Failed to get select response, Error - " + (SmartcardError)ret);
164             }
165
166             respList = new byte[len];
167             for (int i = 0; i < len; i++)
168             {
169                 respList[i] = Marshal.ReadByte(strAtr);
170                 strAtr += sizeof(byte);
171             }
172             return respList;
173         }
174
175         /// <summary>
176         /// Transmits an APDU command (as per ISO/IEC 7816-4) to the Secure Element.
177         /// </summary>
178         /// <returns>Byte array for the response APDU plus status words.</returns>
179         /// <param name="cmd">Command APDU to be send to the secure element.</param>
180         public byte[] Transmit(byte[] cmd)
181         {
182             byte[] atrList;
183             IntPtr strAtr;
184             int len;
185             int ret = Interop.Smartcard.Channel.ChannelTransmit(_channelHandle, cmd, cmd.Length, out strAtr, out len);
186             if (ret != (int)SmartcardError.None)
187             {
188                 Log.Error(Globals.LogTag, "Failed to transmit, Error - " + (SmartcardError)ret);
189             }
190
191             atrList = new byte[len];
192             for (int i = 0; i < len; i++)
193             {
194                 atrList[i] = Marshal.ReadByte(strAtr);
195                 strAtr += sizeof(byte);
196             }
197
198             return atrList;
199         }
200
201         /// <summary>
202         /// Helper function to retrieves the response APDU of the previous transmit() call.
203         /// </summary>
204         /// <returns>Byte array for the response APDU plus status words.</returns>
205         public byte[] GetTransmittedResponse()
206         {
207             byte[] respList;
208             IntPtr strAtr;
209             int len;
210             int ret = Interop.Smartcard.Channel.ChannelTransmitRetrieveResponse(_channelHandle, out strAtr, out len);
211             if (ret != (int)SmartcardError.None)
212             {
213                 Log.Error(Globals.LogTag, "Failed to get trasmit retrieve response, Error - " + (SmartcardError)ret);
214             }
215
216             respList = new byte[len];
217             for (int i = 0; i < len; i++)
218             {
219                 respList[i] = Marshal.ReadByte(strAtr);
220                 strAtr += sizeof(byte);
221             }
222             return respList;
223         }
224
225         /// <summary>
226         /// Performs a selection of the next Applet on the given channel that matches to the partial Application ID(AID).
227         /// </summary>
228         /// <returns>True or false depending whether another applet with the partial Application ID(AID).</returns>
229         public bool SelectNext()
230         {
231             bool selectNext;
232             int ret = Interop.Smartcard.Channel.ChannelSelectNext(_channelHandle, out selectNext);
233             if (ret != (int)SmartcardError.None)
234             {
235                 Log.Error(Globals.LogTag, "Failed to select next, Error - " + (SmartcardError)ret);
236             }
237             return selectNext;
238         }
239     }
240 }