Add new feature and 2 enum values for USB secure element
[platform/core/api/smartcard.git] / src / ClientChannel.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 <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <glib.h>
22
23 /* SLP library header */
24
25 /* local header */
26 #include "smartcard_debug.h"
27 #include "ClientChannel.h"
28 #include "ReaderHelper.h"
29 #include "APDUHelper.h"
30 #include "ClientGDBus.h"
31
32 /* LCOV_EXCL_START */
33
34 #ifndef EXTERN_API
35 #define EXTERN_API __attribute__((visibility("default")))
36 #endif
37
38 namespace smartcard_service_api
39 {
40         ClientChannel::ClientChannel(void *context, Session *session,
41                 int channelNum, const ByteArray &selectResponse, void *handle)
42                 : Channel(session)
43         {
44                 this->channelNum = -1;
45                 this->handle = NULL;
46                 this->context = NULL;
47
48                 if (handle == NULL)
49                 {
50                         _ERR("ClientIPC::getInstance() failed");
51
52                         return;
53                 }
54
55                 this->channelNum = channelNum;
56                 this->handle = handle;
57                 this->selectResponse = selectResponse;
58                 this->context = context;
59
60                 /* init default context */
61                 GError *error = NULL;
62
63                 proxy = smartcard_service_channel_proxy_new_for_bus_sync(
64                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
65                         "org.tizen.SmartcardService",
66                         "/org/tizen/SmartcardService/Channel",
67                         NULL, &error);
68                 if (proxy == NULL)
69                 {
70                         if (error != NULL) {
71                                 _ERR("Can not create proxy : %s", error->message);
72                                 g_error_free(error);
73                         }
74                         return;
75                 }
76         }
77
78         ClientChannel::~ClientChannel()
79         {
80                 closeSync();
81         }
82
83         void ClientChannel::channel_transmit_cb(GObject *source_object,
84                 GAsyncResult *res, gpointer user_data)
85         {
86                 CallbackParam *param = (CallbackParam *)user_data;
87                 transmitCallback callback;
88                 gint result;
89                 GVariant *var_response;
90                 GError *error = NULL;
91                 ByteArray response;
92
93                 _INFO("MSG_REQUEST_TRANSMIT");
94
95                 if (param == NULL) {
96                         _ERR("null parameter!!!");
97                         return;
98                 }
99
100                 callback = (transmitCallback)param->callback;
101
102                 if (smartcard_service_channel_call_transmit_finish(
103                         SMARTCARD_SERVICE_CHANNEL(source_object),
104                         &result, &var_response, res, &error) == true) {
105                         if (result == SCARD_ERROR_OK) {
106                                 GDBusHelper::convertVariantToByteArray(var_response, response);
107                         } else {
108                                 _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
109                         }
110                 } else {
111                         if (error != NULL) {
112                                 _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
113                                 g_error_free(error);
114                         }
115
116                         result = SCARD_ERROR_IPC_FAILED;
117                 }
118
119                 if (callback != NULL) {
120                         callback(response.getBuffer(),
121                                 response.size(),
122                                 result, param->user_param);
123                 }
124
125                 delete param;
126         }
127
128         void ClientChannel::channel_close_cb(GObject *source_object,
129                 GAsyncResult *res, gpointer user_data)
130         {
131                 CallbackParam *param = (CallbackParam *)user_data;
132                 ClientChannel *channel;
133                 closeChannelCallback callback;
134                 gint result;
135                 GError *error = NULL;
136
137                 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
138
139                 if (param == NULL) {
140                         _ERR("null parameter!!!");
141                         return;
142                 }
143
144                 channel = (ClientChannel *)param->instance;
145                 callback = (closeChannelCallback)param->callback;
146
147                 if (smartcard_service_channel_call_close_channel_finish(
148                         SMARTCARD_SERVICE_CHANNEL(source_object),
149                         &result, res, &error) == true) {
150                         if (result == SCARD_ERROR_OK) {
151                                 channel->channelNum = -1;
152                         } else {
153                                 _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
154                         }
155                 } else {
156                         if (error != NULL) {
157                                 _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
158                                 g_error_free(error);
159                         }
160
161                         result = SCARD_ERROR_IPC_FAILED;
162                 }
163
164                 if (callback != NULL) {
165                         callback(result, param->user_param);
166                 }
167
168                 delete param;
169         }
170
171         void ClientChannel::closeSync()
172         {
173                 if (isClosed() == false)
174                 {
175                         if (getSession()->getReader()->isSecureElementPresent() == true) {
176                                 gint ret;
177                                 GError *error = NULL;
178
179
180                                 if (proxy == NULL) {
181                                         _ERR("dbus proxy is not initialized yet");
182                                         throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
183                                 }
184
185                                 if (smartcard_service_channel_call_close_channel_sync(
186                                         (SmartcardServiceChannel *)proxy,
187                                         GPOINTER_TO_UINT(context),
188                                         GPOINTER_TO_UINT(handle),
189                                         &ret, NULL, &error) == true) {
190                                         if (ret == SCARD_ERROR_OK) {
191                                                 channelNum = -1;
192                                         } else {
193                                                 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
194                                                 THROW_ERROR(ret);
195                                         }
196                                 } else {
197                                         if (error != NULL) {
198                                                 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
199                                                 g_error_free(error);
200                                         }
201
202                                         throw ErrorIO(SCARD_ERROR_IPC_FAILED);
203                                 }
204                         } else {
205                                 _INFO("unavailable channel");
206                         }
207                 }
208         }
209
210         int ClientChannel::close(closeChannelCallback callback, void *userParam)
211         {
212                 int result = SCARD_ERROR_OK;
213
214                 if (isClosed() == false) {
215                         if (getSession()->getReader()->isSecureElementPresent() == true) {
216                                 CallbackParam *param = new CallbackParam();
217
218                                 param->instance = this;
219                                 param->callback = (void *)callback;
220                                 param->user_param = userParam;
221
222                                 smartcard_service_channel_call_close_channel(
223                                         (SmartcardServiceChannel *)proxy,
224                                         GPOINTER_TO_UINT(context),
225                                         GPOINTER_TO_UINT(handle), NULL,
226                                         &ClientChannel::channel_close_cb, param);
227                         } else {
228                                 _ERR("unavailable channel");
229                                 result = SCARD_ERROR_ILLEGAL_STATE;
230                         }
231                 }
232
233                 return result;
234         }
235
236         int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
237         {
238                 int rv = SCARD_ERROR_OK;
239
240                 if (getSession()->getReader()->isSecureElementPresent() == true) {
241                         GVariant *var_command = NULL, *var_response = NULL;
242                         GError *error = NULL;
243
244                         var_command = GDBusHelper::convertByteArrayToVariant(command);
245
246                         if (smartcard_service_channel_call_transmit_sync(
247                                 (SmartcardServiceChannel *)proxy,
248                                 GPOINTER_TO_UINT(context),
249                                 GPOINTER_TO_UINT(handle),
250                                 var_command, &rv, &var_response,
251                                 NULL, &error) == true) {
252                                 if (rv == SCARD_ERROR_OK) {
253                                         GDBusHelper::convertVariantToByteArray(var_response, transmitResponse);
254                                         result = transmitResponse;
255                                 } else {
256                                         _ERR("smartcard_service_session_call_transmit failed, [%d]", rv);
257                                         THROW_ERROR(rv);
258                                 }
259                         } else {
260                                 if (error != NULL) {
261                                         _ERR("smartcard_service_session_call_transmit failed, [%s]", error->message);
262                                         g_error_free(error);
263                                 }
264
265                                 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
266                         }
267                 } else {
268                         _ERR("unavailable channel");
269                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
270                 }
271
272                 return rv;
273         }
274
275         int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
276         {
277                 int result;
278
279                 if (getSession()->getReader()->isSecureElementPresent() == true) {
280                         GVariant *var_command;
281                         CallbackParam *param = new CallbackParam();
282
283                         param->instance = this;
284                         param->callback = (void *)callback;
285                         param->user_param = userParam;
286
287                         var_command = GDBusHelper::convertByteArrayToVariant(command);
288
289                         smartcard_service_channel_call_transmit(
290                                 (SmartcardServiceChannel *)proxy,
291                                 GPOINTER_TO_UINT(context),
292                                 GPOINTER_TO_UINT(handle),
293                                 var_command, NULL,
294                                 &ClientChannel::channel_transmit_cb, param);
295
296                         result = SCARD_ERROR_OK;
297                 } else {
298                         _ERR("unavailable channel");
299                         result = SCARD_ERROR_ILLEGAL_STATE;
300                 }
301
302                 return result;
303         }
304 } /* namespace smartcard_service_api */
305
306 /* export C API */
307 #define CHANNEL_EXTERN_BEGIN \
308         if (handle != NULL) \
309         { \
310                 ClientChannel *channel = (ClientChannel *)handle;
311
312 #define CHANNEL_EXTERN_END \
313         } \
314         else \
315         { \
316                 _ERR("Invalid param"); \
317         }
318
319 using namespace smartcard_service_api;
320
321 EXTERN_API int channel_close_sync(channel_h handle)
322 {
323         int result = SCARD_ERROR_OK;
324
325         CHANNEL_EXTERN_BEGIN;
326
327         try
328         {
329                 channel->closeSync();
330         }
331         catch (ExceptionBase &e)
332         {
333                 _ERR("Error occur : %s\n", e.what());
334                 result = e.getErrorCode();
335         }
336         catch (...)
337         {
338                 _ERR("Error occur : unknown error\n");
339                 result = SCARD_ERROR_UNKNOWN;
340         }
341
342         CHANNEL_EXTERN_END;
343
344         return result;
345 }
346
347 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
348         unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
349 {
350         int result = SCARD_ERROR_OK;
351
352         if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
353                 return SCARD_ERROR_UNKNOWN;
354
355         CHANNEL_EXTERN_BEGIN;
356
357         try
358         {
359                 ByteArray temp, resp;
360
361                 temp.assign(command, cmd_len);
362                 channel->transmitSync(temp, resp);
363
364                 if (resp.size() > 0)
365                 {
366                         *response = (unsigned char *)calloc(resp.size(), sizeof(unsigned char));
367                         *resp_len = resp.size();
368                         memcpy(*response, resp.getBuffer(), *resp_len);
369                 }
370         }
371         catch (ExceptionBase &e)
372         {
373                 _ERR("Error occur : %s\n", e.what());
374                 result = e.getErrorCode();
375                 *resp_len = 0;
376         }
377         catch (...)
378         {
379                 _ERR("Error occur : unknown error\n");
380                 result = SCARD_ERROR_UNKNOWN;
381                 *resp_len = 0;
382         }
383
384         CHANNEL_EXTERN_END;
385
386         return result;
387 }
388
389 EXTERN_API int channel_is_basic_channel(channel_h handle, bool* is_basic_channel)
390 {
391         int result = SCARD_ERROR_OK;
392
393         CHANNEL_EXTERN_BEGIN;
394
395         try
396         {
397                 *is_basic_channel = channel->isBasicChannel();
398         }
399         catch (ExceptionBase &e)
400         {
401                 _ERR("Error occur : %s\n", e.what());
402                 result = e.getErrorCode();
403         }
404         catch (...)
405         {
406                 _ERR("Error occur : unknown error\n");
407                 result = SCARD_ERROR_UNKNOWN;
408         }
409
410         CHANNEL_EXTERN_END;
411
412         return result;
413 }
414
415 EXTERN_API int channel_is_closed(channel_h handle, bool* is_closed)
416 {
417         int result = SCARD_ERROR_OK;
418
419         CHANNEL_EXTERN_BEGIN;
420
421         try
422         {
423                 *is_closed = channel->isClosed();
424         }
425         catch (ExceptionBase &e)
426         {
427                 _ERR("Error occur : %s\n", e.what());
428                 result = e.getErrorCode();
429         }
430         catch (...)
431         {
432                 _ERR("Error occur : unknown error\n");
433                 result = SCARD_ERROR_UNKNOWN;
434         }
435
436         CHANNEL_EXTERN_END;
437
438         return result;
439 }
440
441 EXTERN_API int channel_get_select_response(channel_h handle,
442         unsigned char **buffer, size_t *length)
443 {
444         int result = SCARD_ERROR_OK;
445
446         CHANNEL_EXTERN_BEGIN;
447
448         try
449         {
450                 ByteArray response = channel->getSelectResponse();
451                 uint8_t* get_buffer = response.getBuffer();
452
453                 *length = response.size();
454
455                 if (*length > 0)
456                 {
457                         *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char));
458                         if(*buffer == NULL || get_buffer == NULL)
459                         {
460                                 *length = 0;
461                                 return SCARD_ERROR_NOT_ENOUGH_RESOURCE;
462                         }
463
464                         memcpy(*buffer, get_buffer, *length);
465                 }
466         }
467         catch (ExceptionBase &e)
468         {
469                 _ERR("Error occur : %s\n", e.what());
470                 result = e.getErrorCode();
471                 *length = 0;
472         }
473         catch (...)
474         {
475                 _ERR("Error occur : unknown error\n");
476                 result = SCARD_ERROR_UNKNOWN;
477                 *length = 0;
478         }
479
480         CHANNEL_EXTERN_END;
481
482         return result;
483 }
484
485 EXTERN_API int channel_get_transmit_response(channel_h handle,
486         unsigned char **buffer, size_t *length)
487 {
488         int result = SCARD_ERROR_OK;
489
490         CHANNEL_EXTERN_BEGIN;
491
492         try
493         {
494                 ByteArray response;
495
496                 response = channel->getTransmitResponse();
497
498                 *length = response.size();
499
500                 if (*length > 0)
501                 {
502                         *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char));
503                         memcpy(*buffer, response.getBuffer(), *length);
504                 }
505         }
506         catch (ExceptionBase &e)
507         {
508                 _ERR("Error occur : %s\n", e.what());
509                 result = e.getErrorCode();
510                 *length = 0;
511         }
512         catch (...)
513         {
514                 _ERR("Error occur : unknown error\n");
515                 result = SCARD_ERROR_UNKNOWN;
516                 *length = 0;
517         }
518
519         CHANNEL_EXTERN_END;
520
521         return result;
522 }
523
524 EXTERN_API int channel_get_session(channel_h handle, int *session_handle)
525 {
526         int result = SCARD_ERROR_OK;
527         session_h session = NULL;
528
529         CHANNEL_EXTERN_BEGIN;
530
531         try
532         {
533                 session = channel->getSession();
534                 *session_handle = (long)session;
535         }
536         catch (ExceptionBase &e)
537         {
538                 _ERR("Error occur : %s\n", e.what());
539                 result = e.getErrorCode();
540         }
541         catch (...)
542         {
543                 _ERR("Error occur : unknown error\n");
544                 result = SCARD_ERROR_UNKNOWN;
545         }
546
547         CHANNEL_EXTERN_END;
548
549         return result;
550 }
551
552 EXTERN_API int channel_select_next(channel_h handle, bool *pSuccess)
553 {
554         int result = SCARD_ERROR_OK;
555
556         CHANNEL_EXTERN_BEGIN;
557
558         try
559         {
560                 *pSuccess = channel->selectNext();
561         }
562         catch (ExceptionBase &e)
563         {
564                 _ERR("Error occur : %s\n", e.what());
565                 result = e.getErrorCode();
566         }
567         catch (...)
568         {
569                 _ERR("Error occur : unknown error\n");
570                 result = SCARD_ERROR_UNKNOWN;
571         }
572
573         CHANNEL_EXTERN_END;
574
575         return result;
576 }
577
578 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
579 {
580         unsigned int result = 0;
581
582         CHANNEL_EXTERN_BEGIN;
583         result = channel->getSelectResponse().size();
584         CHANNEL_EXTERN_END;
585
586         return result;
587 }
588
589 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
590 {
591         int result = -1;
592
593         CHANNEL_EXTERN_BEGIN;
594         result = channel->close((closeChannelCallback)callback, userParam);
595         CHANNEL_EXTERN_END;
596
597         return result;
598 }
599
600 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
601         unsigned int length, channel_transmit_cb callback, void *userParam)
602 {
603         int result = -1;
604
605         CHANNEL_EXTERN_BEGIN;
606         ByteArray temp;
607
608         temp.assign(command, length);
609         result = channel->transmit(temp, (transmitCallback)callback, userParam);
610         CHANNEL_EXTERN_END;
611
612         return result;
613 }
614
615 EXTERN_API void channel_destroy_instance(channel_h handle)
616 {
617         /* do nothing */
618 }
619
620 /* LCOV_EXCL_STOP */
621