Apply coding rule
[platform/core/connectivity/smartcard-service.git] / common / GPARAM.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 /* standard library header */
18 #include <glib.h>
19
20 /* SLP library header */
21
22 /* local header */
23 #include "Debug.h"
24 #include "GPARAM.h"
25 #include "APDUHelper.h"
26 #include "FileObject.h"
27 #include "NumberStream.h"
28 #include "SimpleTLV.h"
29 #include "ISO7816BERTLV.h"
30 #include "AccessCondition.h"
31
32 #ifndef EXTERN_API
33 #define EXTERN_API __attribute__((visibility("default")))
34 #endif
35
36 namespace smartcard_service_api
37 {
38         static unsigned char aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 0x00 };
39         static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram));
40
41 #define GET_DATA_ALL            0
42 #define GET_DATA_SPECIFIC       1
43 #define GET_DATA_REFRESH_TAG    2
44 #define GET_DATA_NEXT           3
45
46 #define ARAM_TAG_ALL_AR         0x0000FF40
47 #define ARAM_TAG_AR             0x0000FF50
48 #define ARAM_TAG_REFRESH        0x0000DF20
49
50 #define DO_TAG_AID_REF          0x0000004F
51 #define DO_TAG_AID_REF_DEFAULT  0x000000C0
52 #define DO_TAG_HASH_REF         0x000000C1
53 #define DO_TAG_APDU_AR          0x000000D0
54 #define DO_TAG_NFC_AR           0x000000D1
55 #define DO_TAG_REF              0x000000E1
56 #define DO_TAG_REF_AR           0x000000E2
57 #define DO_TAG_AR               0x000000E3
58
59         GPARAM::GPARAM(Channel *channel)
60                 : FileObject(channel)
61         {
62         }
63
64         int GPARAM::select()
65         {
66                 return FileObject::select(AID_ARAM);
67         }
68
69         static int doTransmit(Channel *channel, const ByteArray &command, ByteArray &response)
70         {
71                 int result;
72                 ByteArray resp;
73
74                 _BEGIN();
75
76                 result = channel->transmitSync(command, resp);
77                 if (result == SCARD_ERROR_OK) {
78                         result = ResponseHelper::getStatus(resp);
79                         if (result >= SCARD_ERROR_OK) {
80                                 response = ResponseHelper::getDataField(resp);
81                                 _DBG("response[%d] : %s", response.size(), response.toString().c_str());
82                         } else {
83                                 _ERR("transmit returns error, [%d]", result);
84                         }
85                 } else {
86                         _ERR("transmitSync failed, [%d]", result);
87                 }
88
89                 _END();
90
91                 return result;
92         }
93
94         static int doCommand(Channel *channel, int command, ByteArray &response)
95         {
96                 int result;
97                 APDUCommand helper;
98                 ByteArray cmd, resp;
99
100                 _BEGIN();
101
102                 switch (command) {
103                 case GET_DATA_ALL :
104                         helper.setCommand(0x80, 0xCA, 0xFF, 0x40, ByteArray::EMPTY, 0);
105                         break;
106
107                 case GET_DATA_REFRESH_TAG :
108                         helper.setCommand(0x80, 0xCA, 0xDF, 0x20, ByteArray::EMPTY, 0);
109                         break;
110
111                 case GET_DATA_NEXT :
112                         helper.setCommand(0x80, 0xCA, 0xFF, 0x60, ByteArray::EMPTY, 0);
113                         break;
114                 }
115
116                 helper.getBuffer(cmd);
117
118                 _DBG("command[%d] : %s", cmd.size(), cmd.toString().c_str());
119
120                 result = doTransmit(channel, cmd, response);
121
122                 _END();
123
124                 return result;
125         }
126
127         static int doCommand(Channel *channel, ByteArray &data, ByteArray &response)
128         {
129                 int result;
130                 APDUCommand helper;
131                 ByteArray cmd;
132
133                 helper.setCommand(0x80, 0xCA, 0xFF, 0x50, data, 0);
134                 helper.getBuffer(cmd);
135
136                 result = doTransmit(channel, cmd, response);
137
138                 return result;
139         }
140
141         int getLengthAndValue(const ByteArray &data, ByteArray &value)
142         {
143                 int result = -1;
144                 int offset = 0;
145
146                 if (data.isEmpty() == true) {
147                         return result;
148                 }
149
150                 if (data.at(offset) == 0xFF && data.at(offset + 1) == 0x40) {
151                         uint8_t count;
152
153                         offset += 2;
154                         count = data.at(offset);
155
156                         offset += 1;
157                         if (count & 0x80) {
158                                 int i;
159
160                                 count &= ~0x80;
161                                 result = 0;
162
163                                 for (i = 0; i < count; i++) {
164                                         result = (result << 8) | data.at(offset + i);
165                                 }
166
167                                 offset += i;
168                         } else {
169                                 result = count;
170                         }
171
172                         if (result > 0) {
173                                 value.assign(data.getBuffer(offset),
174                                         MIN((uint32_t)result,
175                                                 data.size() - offset));
176                         }
177                 } else {
178                         _ERR("invalid tag");
179                 }
180
181                 return result;
182         }
183
184         int GPARAM::getDataAll(ByteArray &data)
185         {
186                 int result;
187                 ByteArray response;
188
189                 _BEGIN();
190
191                 result = doCommand(channel, GET_DATA_ALL, response);
192                 if (result >= SCARD_ERROR_OK) {
193                         int length;
194
195                         length = getLengthAndValue(response, data);
196                         if (length > 0){
197                                 while (length > (int)data.size()) {
198                                         result = doCommand(channel, GET_DATA_NEXT, response);
199                                         if (result >= SCARD_ERROR_OK) {
200                                                 data += response;
201                                         } else {
202                                                 _ERR("generateCommand failed, [%d]", result);
203                                                 data.clear();
204                                                 break;
205                                         }
206                                 }
207
208                                 _DBG("data[%d] : %s", data.size(), data.toString().c_str());
209                         } else if (length == 0) {
210                                 _INFO("Response-ALL-AR-DO is empty");
211                                 data.clear();
212                         } else {
213                                 _ERR("invalid result, %s", response.toString().c_str());
214                                 result = SCARD_ERROR_UNAVAILABLE;
215                         }
216                 } else {
217                         _ERR("doCommand failed, [%d]", result);
218                 }
219
220                 _END();
221
222                 return result;
223         }
224
225         static int createRefDo(const ByteArray &aid, const ByteArray &hash, ByteArray &refDo)
226         {
227                 ByteArray temp;
228
229                 temp = SimpleTLV::encode(DO_TAG_AID_REF, aid);
230                 temp += SimpleTLV::encode(DO_TAG_HASH_REF, hash);
231
232                 refDo = SimpleTLV::encode(DO_TAG_REF, temp);
233                 _DBG("encoded Ref DO : %s", refDo.toString().c_str());
234
235                 return SCARD_ERROR_OK;
236         }
237
238         int GPARAM::getDataSpecific(const ByteArray &aid, const ByteArray &hash,
239                 ByteArray &data)
240         {
241                 int result;
242                 ByteArray refDo, response;
243
244                 _BEGIN();
245
246                 createRefDo(aid, hash, refDo);
247
248                 result = doCommand(channel, refDo, response);
249                 if (result >= SCARD_ERROR_OK) {
250                         ISO7816BERTLV tlv(response);
251
252                         if (tlv.decodeTLV() == true &&
253                                 tlv.getTag() == ARAM_TAG_AR) {
254                                 unsigned int length = tlv.size();
255
256                                 if (length > 0){
257                                         data = tlv.getValue();
258
259                                         while (length > data.size()) {
260                                                 result = doCommand(channel, GET_DATA_NEXT, response);
261                                                 if (result >= SCARD_ERROR_OK) {
262                                                         data += response;
263                                                 } else {
264                                                         _ERR("generateCommand failed, [%d]", result);
265                                                         data.clear();
266                                                         break;
267                                                 }
268                                         }
269                                         _DBG("data[%d] : %s", data.size(), data.toString().c_str());
270                                 } else {
271                                         _INFO("Response-ALL-AR-DO is empty");
272                                         data.clear();
273                                 }
274                         } else {
275                                 _ERR("decodeTLV failed, %s", response.toString().c_str());
276                                 result = SCARD_ERROR_ILLEGAL_PARAM;
277                         }
278                 } else {
279                         _ERR("doCommand failed, [%d]", result);
280                 }
281
282                 _END();
283
284                 return result;
285         }
286
287         int GPARAM::getDataRefreshTag(ByteArray &tag)
288         {
289                 int result;
290                 ByteArray response;
291
292                 _BEGIN();
293
294                 result = doCommand(channel, GET_DATA_REFRESH_TAG, response);
295                 if (result >= SCARD_ERROR_OK) {
296                         ISO7816BERTLV tlv(response);
297
298                         if (tlv.decodeTLV() == true &&
299                                 tlv.getTag() == ARAM_TAG_REFRESH &&
300                                 tlv.size() == 8) {
301                                 tag = tlv.getValue();
302                                 result = SCARD_ERROR_OK;
303                                 _DBG("refreshTag[%d] : %s", tag.size(), tag.toString().c_str());
304                         } else {
305                                 _ERR("decodeTLV failed, %s", response.toString().c_str());
306                                 result = SCARD_ERROR_ILLEGAL_PARAM;
307                         }
308                 } else {
309                         _ERR("generateCommand failed, [%d]", result);
310                 }
311
312                 _END();
313
314                 return result;
315         }
316 } /* namespace smartcard_service_api */