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