source: trunk/src/ct/client.c @ 963

Revision 963, 9.9 KB checked in by aj, 5 years ago (diff)

indent changes only.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Communication with ifd handler
3 *
4 * Copyright (C) 2003 Olaf Kirch <okir@suse.de>
5 */
6
7#ifdef HAVE_CONFIG_H
8#include <config.h>
9#endif
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <signal.h>
14#include <errno.h>
15#include <limits.h>
16#include <openct/openct.h>
17#include <openct/socket.h>
18#include <openct/tlv.h>
19#include <openct/error.h>
20#include <openct/path.h>
21#include <openct/protocol.h>
22
23struct ct_handle {
24        ct_socket_t *sock;
25        unsigned int index;     /* reader index */
26        unsigned int card[OPENCT_MAX_SLOTS];    /* card seq */
27        const ct_info_t *info;
28};
29
30static void ct_args_int(ct_buf_t *, ifd_tag_t, unsigned int);
31static void ct_args_string(ct_buf_t *, ifd_tag_t, const char *);
32static void ct_args_opaque(ct_buf_t *, ifd_tag_t,
33                           const unsigned char *, size_t);
34
35/*
36 * Get reader info
37 */
38int ct_reader_info(unsigned int reader, ct_info_t * result)
39{
40        const ct_info_t *info;
41        int rc;
42
43        if ((rc = ct_status(&info)) < 0 || reader > (unsigned int)rc)
44                return -1;
45
46        /* Make sure the server process is alive */
47        if (info[reader].ct_pid == 0
48            || (kill(info[reader].ct_pid, 0) < 0 && errno == ESRCH))
49                return -1;
50
51        *result = info[reader];
52        return 0;
53}
54
55/*
56 * Connect to a reader manager
57 */
58ct_handle *ct_reader_connect(unsigned int reader)
59{
60        const ct_info_t *info;
61        char path[PATH_MAX];
62        char file[PATH_MAX];
63        ct_handle *h;
64        int rc, len;
65
66        len = PATH_MAX;
67
68        snprintf(file, PATH_MAX, "%d", reader);
69        if (!ct_format_path(path, PATH_MAX, file)) {
70                return NULL;
71        }
72
73        if ((rc = ct_status(&info)) < 0 || reader > (unsigned int)rc)
74                return NULL;
75
76        if (!(h = (ct_handle *) calloc(1, sizeof(*h))))
77                return NULL;
78
79        if (!(h->sock = ct_socket_new(CT_SOCKET_BUFSIZ))) {
80                free(h);
81                return NULL;
82        }
83        if (ct_socket_connect(h->sock, path) < 0) {
84                ct_reader_disconnect(h);
85                return NULL;
86        }
87
88        h->info = info + reader;
89        return h;
90}
91
92/*
93 * Disconnect from reader manager
94 */
95void ct_reader_disconnect(ct_handle * h)
96{
97        if (h->sock)
98                ct_socket_free(h->sock);
99        memset(h, 0, sizeof(*h));
100        free(h);
101}
102
103/*
104 * Retrieve reader status
105 */
106int ct_reader_status(ct_handle * h, ct_info_t * info)
107{
108        *info = *h->info;
109        return 0;
110}
111
112#if 0
113/*
114 * Print something to the reader's display
115 */
116int ct_reader_output(ct_handle * h, const char *message)
117{
118        unsigned char buffer[256];
119        ct_buf_t args, resp;
120
121        ct_buf_init(&args, buffer, sizeof(buffer));
122        ct_buf_init(&resp, buffer, sizeof(buffer));
123
124        ct_buf_putc(&args, CT_CMD_OUTPUT);
125        ct_buf_putc(&args, CT_UNIT_READER);
126
127        /* Add arguments if given */
128        if (message)
129                ct_args_string(&args, CT_TAG_MESSAGE, message);
130
131        return ct_socket_call(h->sock, &args, &resp);
132}
133#endif
134
135/*
136 * Get card status
137 */
138int ct_card_status(ct_handle * h, unsigned int slot, int *status)
139{
140        const ct_info_t *info;
141        unsigned int seq;
142
143        info = h->info;
144        if (slot > info->ct_slots)
145                return IFD_ERROR_INVALID_ARG;
146
147        seq = info->ct_card[slot];
148
149        *status = 0;
150        if (seq != 0) {
151                *status = IFD_CARD_PRESENT;
152                if (seq != h->card[slot])
153                        *status |= IFD_CARD_STATUS_CHANGED;
154        }
155
156        h->card[slot] = seq;
157        return 0;
158}
159
160/*
161 * Reset the card - this is the same as "request icc" without parameters
162 */
163int ct_card_reset(ct_handle * h, unsigned int slot, void *atr, size_t atr_len)
164{
165        return ct_card_request(h, slot, 0, NULL, atr, atr_len);
166}
167
168int ct_card_request(ct_handle * h, unsigned int slot,
169                    unsigned int timeout, const char *message,
170                    void *atr, size_t atr_len)
171{
172        ct_tlv_parser_t tlv;
173        unsigned char buffer[256];
174        ct_buf_t args, resp;
175        int rc;
176
177        ct_buf_init(&args, buffer, sizeof(buffer));
178        ct_buf_init(&resp, buffer, sizeof(buffer));
179
180        ct_buf_putc(&args, CT_CMD_RESET);
181        ct_buf_putc(&args, slot);
182
183        /* Add arguments if given */
184        if (timeout)
185                ct_args_int(&args, CT_TAG_TIMEOUT, timeout);
186        if (message)
187                ct_args_string(&args, CT_TAG_MESSAGE, message);
188
189        rc = ct_socket_call(h->sock, &args, &resp);
190        if (rc < 0)
191                return rc;
192
193        if ((rc = ct_tlv_parse(&tlv, &resp)) < 0)
194                return rc;
195
196        /* Get the ATR. There may be no ATR if the card is synchronous */
197        rc = ct_tlv_get_bytes(&tlv, CT_TAG_ATR, atr, atr_len);
198        if (rc < 0)
199                rc = 0;
200
201        return rc;
202}
203
204#if 0
205int ct_card_eject(ct_handle * h, unsigned int slot,
206                  unsigned int timeout, const char *message)
207{
208        unsigned char buffer[256];
209        ct_buf_t args, resp;
210
211        ct_buf_init(&args, buffer, sizeof(buffer));
212        ct_buf_init(&resp, buffer, sizeof(buffer));
213
214        ct_buf_putc(&args, CT_CMD_EJECT_ICC);
215        ct_buf_putc(&args, slot);
216
217        /* Add arguments if given */
218        if (timeout)
219                ct_args_int(&args, CT_TAG_TIMEOUT, timeout);
220        if (message)
221                ct_args_string(&args, CT_TAG_MESSAGE, message);
222
223        return ct_socket_call(h->sock, &args, &resp);
224}
225#endif
226
227int ct_card_set_protocol(ct_handle * h, unsigned int slot,
228                         unsigned int protocol)
229{
230        unsigned char buffer[256];
231        ct_buf_t args, resp;
232
233        ct_buf_init(&args, buffer, sizeof(buffer));
234        ct_buf_init(&resp, buffer, sizeof(buffer));
235
236        ct_buf_putc(&args, CT_CMD_SET_PROTOCOL);
237        ct_buf_putc(&args, slot);
238        ct_args_int(&args, CT_TAG_PROTOCOL, protocol);
239        return ct_socket_call(h->sock, &args, &resp);
240}
241
242/*
243 * Transceive an APDU
244 */
245int ct_card_transact(ct_handle * h, unsigned int slot,
246                     const void *send_data, size_t send_len,
247                     void *recv_buf, size_t recv_size)
248{
249        ct_tlv_parser_t tlv;
250        unsigned char buffer[CT_SOCKET_BUFSIZ];
251        ct_buf_t args, resp;
252        int rc;
253
254        ct_buf_init(&args, buffer, sizeof(buffer));
255        ct_buf_init(&resp, buffer, sizeof(buffer));
256
257        ct_buf_putc(&args, CT_CMD_TRANSACT);
258        ct_buf_putc(&args, slot);
259
260        ct_args_opaque(&args, CT_TAG_CARD_REQUEST,
261                       (const unsigned char *)send_data, send_len);
262
263        rc = ct_socket_call(h->sock, &args, &resp);
264        if (rc < 0)
265                return rc;
266
267        if ((rc = ct_tlv_parse(&tlv, &resp)) < 0)
268                return rc;
269
270        /* Get the ATR */
271        return ct_tlv_get_bytes(&tlv, CT_TAG_CARD_RESPONSE,
272                                recv_buf, recv_size);
273}
274
275/*
276 * Read from a synchronous card
277 */
278int ct_card_read_memory(ct_handle * h, unsigned int slot,
279                        unsigned short address, void *recv_buf, size_t recv_len)
280{
281        ct_tlv_parser_t tlv;
282        unsigned char buffer[CT_SOCKET_BUFSIZ];
283        ct_buf_t args, resp;
284        int rc;
285
286        ct_buf_init(&args, buffer, sizeof(buffer));
287        ct_buf_init(&resp, buffer, sizeof(buffer));
288
289        ct_buf_putc(&args, CT_CMD_MEMORY_READ);
290        ct_buf_putc(&args, slot);
291
292        ct_args_int(&args, CT_TAG_ADDRESS, address);
293        ct_args_int(&args, CT_TAG_COUNT, recv_len);
294
295        rc = ct_socket_call(h->sock, &args, &resp);
296        if (rc < 0)
297                return rc;
298
299        if ((rc = ct_tlv_parse(&tlv, &resp)) < 0)
300                return rc;
301
302        return ct_tlv_get_bytes(&tlv, CT_TAG_DATA, recv_buf, recv_len);
303}
304
305int ct_card_write_memory(ct_handle * h, unsigned int slot,
306                         unsigned short address,
307                         const void *send_buf, size_t send_len)
308{
309        unsigned char buffer[CT_SOCKET_BUFSIZ];
310        ct_buf_t args, resp;
311        int rc;
312
313        ct_buf_init(&args, buffer, sizeof(buffer));
314        ct_buf_init(&resp, buffer, sizeof(buffer));
315
316        ct_buf_putc(&args, CT_CMD_MEMORY_WRITE);
317        ct_buf_putc(&args, slot);
318
319        ct_args_int(&args, CT_TAG_ADDRESS, address);
320        ct_args_opaque(&args, CT_TAG_DATA, (const unsigned char *)send_buf,
321                       send_len);
322
323        rc = ct_socket_call(h->sock, &args, &resp);
324        if (rc < 0)
325                return rc;
326
327        return 0;
328}
329
330/*
331 * Verify PIN
332 */
333int ct_card_verify(ct_handle * h, unsigned int slot,
334                   unsigned int timeout, const char *prompt,
335                   unsigned int pin_encoding,
336                   unsigned int pin_length,
337                   unsigned int pin_offset,
338                   const void *send_buf, size_t send_len,
339                   void *recv_buf, size_t recv_len)
340{
341        unsigned char buffer[256];
342        ct_buf_t args, resp;
343        ct_tlv_builder_t builder;
344        ct_tlv_parser_t parser;
345        unsigned char control = 0x00;
346        int rc;
347
348        ct_buf_init(&args, buffer, sizeof(buffer));
349        ct_buf_init(&resp, recv_buf, recv_len);
350
351        ct_buf_putc(&args, CT_CMD_PERFORM_VERIFY);
352        ct_buf_putc(&args, slot);
353
354        if (timeout)
355                ct_args_int(&args, CT_TAG_TIMEOUT, timeout);
356        if (prompt)
357                ct_args_string(&args, CT_TAG_MESSAGE, prompt);
358
359        ct_tlv_builder_init(&builder, &args, 1);
360        ct_tlv_put_tag(&builder, CT_TAG_PIN_DATA);
361
362        /* Build the control byte */
363        if (pin_encoding == IFD_PIN_ENCODING_ASCII)
364                control |= 0x01;
365        else if (pin_encoding != IFD_PIN_ENCODING_BCD)
366                return IFD_ERROR_INVALID_ARG;
367        if (pin_length)
368                control |= pin_length << 4;
369        ct_tlv_add_byte(&builder, control);
370
371        /* Offset is 1 based */
372        ct_tlv_add_byte(&builder, pin_offset + 1);
373        ct_tlv_add_bytes(&builder, (const unsigned char *)send_buf, send_len);
374
375        rc = ct_socket_call(h->sock, &args, &resp);
376        if (rc < 0)
377                return rc;
378
379        if ((rc = ct_tlv_parse(&parser, &resp)) < 0)
380                return rc;
381
382        /* Get the ATR */
383        return ct_tlv_get_bytes(&parser,
384                                CT_TAG_CARD_RESPONSE, recv_buf, recv_len);
385}
386
387/*
388 * Lock/unlock a card
389 */
390int ct_card_lock(ct_handle * h, unsigned int slot, int type,
391                 ct_lock_handle * res)
392{
393        ct_tlv_parser_t tlv;
394        unsigned char buffer[256];
395        ct_buf_t args, resp;
396        int rc;
397
398        ct_buf_init(&args, buffer, sizeof(buffer));
399        ct_buf_init(&resp, buffer, sizeof(buffer));
400
401        ct_buf_putc(&args, CT_CMD_LOCK);
402        ct_buf_putc(&args, slot);
403
404        ct_args_int(&args, CT_TAG_LOCKTYPE, type);
405
406        rc = ct_socket_call(h->sock, &args, &resp);
407        if (rc < 0)
408                return rc;
409
410        if ((rc = ct_tlv_parse(&tlv, &resp)) < 0)
411                return rc;
412
413        if (ct_tlv_get_int(&tlv, CT_TAG_LOCK, res) == 0)
414                return IFD_ERROR_GENERIC;
415
416        return 0;
417}
418
419int ct_card_unlock(ct_handle * h, unsigned int slot, ct_lock_handle lock)
420{
421        unsigned char buffer[256];
422        ct_buf_t args, resp;
423
424        ct_buf_init(&args, buffer, sizeof(buffer));
425        ct_buf_init(&resp, buffer, sizeof(buffer));
426
427        ct_buf_putc(&args, CT_CMD_UNLOCK);
428        ct_buf_putc(&args, slot);
429
430        ct_args_int(&args, CT_TAG_LOCK, lock);
431
432        return ct_socket_call(h->sock, &args, &resp);
433}
434
435/*
436 * Add arguments when calling a resource manager function
437 */
438static void ct_args_int(ct_buf_t * bp, ifd_tag_t tag, unsigned int value)
439{
440        ct_tlv_builder_t builder;
441
442        ct_tlv_builder_init(&builder, bp, 1);
443        ct_tlv_put_int(&builder, tag, value);
444}
445
446static void ct_args_string(ct_buf_t * bp, ifd_tag_t tag, const char *value)
447{
448        ct_tlv_builder_t builder;
449
450        ct_tlv_builder_init(&builder, bp, 1);
451        ct_tlv_put_string(&builder, tag, value);
452}
453
454static void ct_args_opaque(ct_buf_t * bp, ifd_tag_t tag,
455                           const unsigned char *value, size_t len)
456{
457        ct_tlv_builder_t builder;
458
459        ct_tlv_builder_init(&builder, bp, 1);
460        ct_tlv_put_opaque(&builder, tag, value, len);
461}
Note: See TracBrowser for help on using the repository browser.