root/trunk/src/libopensc/card-incrypto34.c

Revision 3502, 25.1 KB (checked in by ludovic.rousseau, 7 months ago)

convert C++ in C comment

Line 
1/*
2 * card-incrypto34.c: Support for Incard Incrypto34 based cards and tokens
3 *      (for example Italian CNS)
4 *
5 * Copyright (C) 2005  ST Incard srl, Giuseppe Amato <giuseppe dot amato at st dot com>, <midori3@gmail.com>
6 * Copyright (C) 2002  Andreas Jellinghaus <aj@dungeon.inka.de>
7 * Copyright (C) 2001  Juha YrjölÀ <juha.yrjola@iki.fi>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24#include "internal.h"
25#include "cardctl.h"
26#include <ctype.h>
27#include <string.h>
28
29/* andreas says: hm, my card only works for small payloads */
30/* comment by okir: one of the examples in the developer guide
31 * also talks about copying data in chunks of 128.
32 * Either coincidence, or a known problem. */
33#define INCRYPTO34_MAX_PAYLOAD  120
34
35static const struct sc_card_operations *iso_ops = NULL;
36
37static struct sc_card_operations incrypto34_ops;
38static struct sc_card_driver incrypto34_drv = {
39        "Incard Incripto34",
40        "incrypto34",
41        &incrypto34_ops,
42        NULL, 0, NULL
43};
44
45static struct sc_atr_table incrypto34_atrs[] = {
46        /* Italian CNS (similar to a eID) card*/
47        { "3b:ff:18:00:ff:81:31:fe:55:00:6b:02:09:02:00:01:01:01:43:4e:53:10:31:80:9f", NULL, NULL, SC_CARD_TYPE_INCRYPTO34_GENERIC, 0, NULL },
48        { "3b:ff:18:00:ff:81:31:fe:55:00:6b:02:09:02:00:01:01:01:44:53:44:10:31:80:92", NULL, NULL, SC_CARD_TYPE_INCRYPTO34_GENERIC, 0, NULL },
49        { NULL, NULL, NULL, 0, 0, NULL }
50};
51
52static int incrypto34_finish(struct sc_card *card)
53{
54        return 0;
55}
56
57static int incrypto34_match_card(struct sc_card *card)
58{
59        int i;
60
61        i = _sc_match_atr(card, incrypto34_atrs, &card->type);
62        if (i < 0)
63                return 0;
64        return 1;
65}
66
67static int incrypto34_init(sc_card_t *card)
68{
69        unsigned long   flags;
70
71        card->name = "Incrypto34";
72        card->cla = 0x00;
73
74        /* Set up algorithm info. */
75        flags = SC_ALGORITHM_NEED_USAGE
76                | SC_ALGORITHM_RSA_RAW
77                | SC_ALGORITHM_RSA_HASH_NONE
78                | SC_ALGORITHM_ONBOARD_KEY_GEN
79                ;
80        _sc_card_add_rsa_alg(card,  512, flags, 0);
81        _sc_card_add_rsa_alg(card,  768, flags, 0);
82        _sc_card_add_rsa_alg(card, 1024, flags, 0);
83
84        return 0;
85}
86
87static const struct sc_card_error incrypto34_errors[] = {
88/* some error inside the card */
89/* i.e. nothing you can do */
90{ 0x6581, SC_ERROR_MEMORY_FAILURE,      "EEPROM error; command aborted"},
91{ 0x6fff, SC_ERROR_CARD_CMD_FAILED,     "internal assertion error"},
92{ 0x6700, SC_ERROR_WRONG_LENGTH,        "LC invalid"},
93{ 0x6985, SC_ERROR_CARD_CMD_FAILED,     "no random number available"},
94{ 0x6f81, SC_ERROR_CARD_CMD_FAILED,     "file invalid, maybe checksum error"},
95{ 0x6f82, SC_ERROR_CARD_CMD_FAILED,     "not enough memory in xram"},
96{ 0x6f84, SC_ERROR_CARD_CMD_FAILED,     "general protection fault"},
97
98/* the card doesn't now thic combination of ins+cla+p1+p2 */
99/* i.e. command will never work */
100{ 0x6881, SC_ERROR_NO_CARD_SUPPORT,     "logical channel not supported"},
101{ 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"},
102{ 0x6d00, SC_ERROR_INS_NOT_SUPPORTED,   "ins invalid"},
103{ 0x6e00, SC_ERROR_CLASS_NOT_SUPPORTED, "class invalid (hi nibble)"},
104
105/* known command, but incorrectly used */
106/* i.e. command could work, but you need to change something */
107{ 0x6981, SC_ERROR_CARD_CMD_FAILED,     "command cannot be used for file structure"},
108{ 0x6a80, SC_ERROR_INCORRECT_PARAMETERS,"invalid parameters in data field"},
109{ 0x6a81, SC_ERROR_NOT_SUPPORTED,       "function/mode not supported"},
110{ 0x6a85, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit the tlv structure"},
111{ 0x6986, SC_ERROR_INCORRECT_PARAMETERS,"no current ef selected"},
112{ 0x6a87, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit p1/p2"},
113{ 0x6c00, SC_ERROR_WRONG_LENGTH,        "le does not fit the data to be sent"},
114{ 0x6f83, SC_ERROR_CARD_CMD_FAILED,     "command must not be used in transaction"},
115
116/* (something) not found */
117{ 0x6987, SC_ERROR_INCORRECT_PARAMETERS,"key object for sm not found"},
118{ 0x6f86, SC_ERROR_CARD_CMD_FAILED,     "key object not found"},
119{ 0x6a82, SC_ERROR_FILE_NOT_FOUND,      "file not found"},
120{ 0x6a83, SC_ERROR_RECORD_NOT_FOUND,    "record not found"},
121{ 0x6a88, SC_ERROR_CARD_CMD_FAILED,     "object not found"},
122{ 0x6a89, SC_ERROR_FILE_ALREADY_EXISTS, "file/object already exists"},
123
124/* (something) invalid */
125{ 0x6884, SC_ERROR_CARD_CMD_FAILED,     "chaining error"},
126{ 0x6984, SC_ERROR_CARD_CMD_FAILED,     "bs object has invalid format"},
127{ 0x6988, SC_ERROR_INCORRECT_PARAMETERS,"key object used for sm has invalid format"},
128
129/* (something) deactivated */
130{ 0x6283, SC_ERROR_CARD_CMD_FAILED,     "file is deactivated"   },
131{ 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "bs object blocked"},
132
133/* access denied */
134{ 0x6300, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"authentication failed"},
135{ 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"required access right not granted"},
136
137/* other errors */
138{ 0x6a84, SC_ERROR_CARD_CMD_FAILED,     "not enough memory"},
139
140/* command ok, execution failed */
141{ 0x6f00, SC_ERROR_CARD_CMD_FAILED,     "technical error (see incrypto34 developers guide)"},
142
143/* no error, maybe a note */
144{ 0x9000, SC_NO_ERROR,          NULL},
145{ 0x9001, SC_NO_ERROR,          "success, but eeprom weakness detected"},
146{ 0x9850, SC_NO_ERROR,          "over/underflow useing in/decrease"}
147};
148
149static int incrypto34_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
150{
151        const int err_count = sizeof(incrypto34_errors)/sizeof(incrypto34_errors[0]);
152        int i;
153
154        for (i = 0; i < err_count; i++) {
155                if (incrypto34_errors[i].SWs == ((sw1 << 8) | sw2)) {
156                        if ( incrypto34_errors[i].errorstr )
157                                sc_error(card->ctx, "%s\n",
158                                        incrypto34_errors[i].errorstr);
159                        return incrypto34_errors[i].errorno;
160                }
161        }
162
163        sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
164        return SC_ERROR_CARD_CMD_FAILED;
165}
166
167static int incrypto34_list_files(sc_card_t *card, u8 *buf, size_t buflen)
168{
169        sc_apdu_t apdu;
170        u8 rbuf[256];
171        int r;
172        size_t fids;
173        u8 offset;
174
175        SC_FUNC_CALLED(card->ctx, 1);
176
177        fids=0;
178        offset=0;
179
180        /* INS 0xFC: SCAN DF*/
181        /* P1 0x00: list both DF and EF */
182        /* P2 0x00/0x01: first/next element */
183        /* LE 0x03*/
184        /*
185                returns 3 bytes: FILE_TYPE + FID_HI_BYTE + FID_LO_BYTE
186        */
187
188get_next_part:
189        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xFC, 0x00, offset?0x01:0x00);
190        apdu.cla = 0xB0;
191        apdu.le = 3;
192        apdu.resplen = sizeof(rbuf);
193        apdu.resp = rbuf;
194
195        r = sc_transmit_apdu(card, &apdu);
196        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
197        if (apdu.sw1 == 0x6a && apdu.sw2 == 0x82)
198                goto end; /* no more files */
199
200        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
201        SC_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
202
203        if (apdu.resplen >= 3
204                && ((rbuf[0] >= 0x01 && rbuf[0] <= 0x07) || 0x38 == rbuf[0])
205                && fids + 2 >= buflen)
206        {
207                buf[fids++] = rbuf[1];
208                buf[fids++] = rbuf[2];
209        }
210
211        ++offset;
212        goto get_next_part;
213
214end:
215        r = fids;
216
217        SC_FUNC_RETURN(card->ctx, 1, r);
218}
219
220static void add_acl_entry(sc_file_t *file, int op, u8 byte)
221{
222        unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
223
224        switch (byte) {
225        case 0x00:
226                method = SC_AC_NONE;
227                break;
228        case 0xFF:
229                method = SC_AC_NEVER;
230                break;
231        default:
232                if (byte > 0x7F) {
233                        method = SC_AC_UNKNOWN;
234                } else {
235                        method = SC_AC_CHV;
236                        key_ref = byte;
237                }
238                break;
239        }
240        sc_file_add_acl_entry(file, op, method, key_ref);
241}
242
243static int acl_to_byte(const sc_acl_entry_t *e)
244{
245        if (e != NULL) {
246                switch (e->method) {
247                case SC_AC_NONE:
248                        return 0x00;
249                case SC_AC_NEVER:
250                        return 0xFF;
251                case SC_AC_CHV:
252                case SC_AC_TERM:
253                case SC_AC_AUT:
254                        if (e->key_ref == SC_AC_KEY_REF_NONE)
255                                return -1;
256                        if (e->key_ref > 0x7F)
257                                return -1;
258                        return e->key_ref;
259                }
260        }
261        return 0x00;
262}
263
264static const int df_acl[9] = {
265        -1,                     /* LCYCLE (life cycle change) */
266        SC_AC_OP_UPDATE,        /* UPDATE Objects */
267        -1,                     /* APPEND Objects */
268
269        SC_AC_OP_INVALIDATE,    /* DF */
270        SC_AC_OP_REHABILITATE,  /* DF */
271        SC_AC_OP_DELETE,        /* DF */
272
273        -1,                     /* ADMIN DF */
274        SC_AC_OP_CREATE,        /* Files */
275        -1                      /* Reserved */
276};
277static const int ef_acl[9] = {
278        SC_AC_OP_READ,          /* Data */
279        SC_AC_OP_UPDATE,        /* Data (write file content) */
280        SC_AC_OP_WRITE,         /* */
281
282        SC_AC_OP_INVALIDATE,    /* EF */
283        SC_AC_OP_REHABILITATE,  /* EF */
284        SC_AC_OP_ERASE,         /* (delete) EF */
285
286        /* XXX: ADMIN should be an ACL type of its own, or mapped
287         * to erase */
288        -1,                     /* ADMIN EF (modify meta information?) */
289        -1,                     /* INC (-> cylic fixed files) */
290        -1                      /* DEC */
291};
292
293static void parse_sec_attr(sc_file_t *file, const u8 *buf, size_t len)
294{
295        size_t i;
296        const int *idx;
297
298        idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
299
300        /* acl defaults to 0xFF if unspecified */
301        for (i = 0; i < 9; i++)
302                if (idx[i] != -1)
303                        add_acl_entry(file, idx[i], (u8)((i < len) ? buf[i] : 0xFF));
304}
305
306static int incrypto34_select_file(sc_card_t *card,
307                              const sc_path_t *in_path,
308                              sc_file_t **file)
309{
310        int r;
311
312        SC_FUNC_CALLED(card->ctx, 1);
313        r = iso_ops->select_file(card, in_path, file);
314        if (r >= 0 && file)
315                parse_sec_attr((*file), (*file)->sec_attr, (*file)->sec_attr_len);
316        SC_FUNC_RETURN(card->ctx, 1, r);
317}
318
319static int incrypto34_create_file(sc_card_t *card, sc_file_t *file)
320{
321        int r, i, byte;
322        const int *idx;
323        u8 acl[9], type[3], status[3];
324
325        if (card->ctx->debug >= 1) {
326                char    pbuf[128+1];
327                size_t  n;
328
329                for (n = 0; n < file->path.len; n++) {
330                        snprintf(pbuf + 2 * n, sizeof(pbuf) - 2 * n,
331                                "%02X", file->path.value[n]);
332                }
333
334                sc_debug(card->ctx, "incrypto34_create_file(%s)\n", pbuf);
335        }
336
337        if (file->type_attr_len == 0) {
338                memset(type, 0, sizeof(type));
339                type[0] = 0x00;
340                switch (file->type) {
341                case SC_FILE_TYPE_WORKING_EF:
342                        break;
343                case SC_FILE_TYPE_INTERNAL_EF:
344                        type[0] = 0x08;
345                        break;
346                case SC_FILE_TYPE_DF:
347                        type[0] = 0x38;
348                        break;
349                default:
350                        r = SC_ERROR_NOT_SUPPORTED;
351                        goto out;
352                }
353                if (file->type != SC_FILE_TYPE_DF) {
354                        switch (file->ef_structure) {
355                        case SC_FILE_EF_LINEAR_FIXED_TLV:
356                        case SC_FILE_EF_LINEAR_VARIABLE:
357                        case SC_FILE_EF_CYCLIC_TLV:
358                                r = SC_ERROR_NOT_SUPPORTED;
359                                goto out;
360                                /* No idea what this means, but it
361                                 * seems to be required for key
362                                 * generation. */
363                        case SC_FILE_EF_LINEAR_VARIABLE_TLV:
364                                type[1] = 0xff;
365                        default:
366                                type[0] |= file->ef_structure & 7;
367                                break;
368                        }
369                }
370                r = sc_file_set_type_attr(file, type, sizeof(type));
371                if (r)
372                        goto out;
373        }
374        if (file->prop_attr_len == 0) {
375                status[0] = 0x01;
376                if (file->type == SC_FILE_TYPE_DF) {
377                        status[1] = file->size >> 8;
378                        status[2] = file->size;
379                } else {
380                        status[1] = status[2] = 0x00; /* not used */
381                }
382                r = sc_file_set_prop_attr(file, status, sizeof(status));
383                if (r)
384                        goto out;
385        }
386        if (file->sec_attr_len == 0) {
387                idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
388                for (i = 0; i < 9; i++) {
389                        if (idx[i] < 0)
390                                byte = 0x00;
391                        else
392                                byte = acl_to_byte(
393                                    sc_file_get_acl_entry(file, idx[i]));
394                        if (byte < 0) {
395                                sc_error(card->ctx, "Invalid ACL\n");
396                                r = SC_ERROR_INVALID_ARGUMENTS;
397                                goto out;
398                        }
399                        acl[i] = byte;
400                }
401                r = sc_file_set_sec_attr(file, acl, sizeof(acl));
402                if (r)
403                        goto out;
404        }
405        r = iso_ops->create_file(card, file);
406
407        /* FIXME: if this is a DF and there's an AID, set it here
408         * using PUT_DATA_FCI */
409
410out:    SC_FUNC_RETURN(card->ctx, 1, r);
411}
412
413/*
414 * Restore the indicated SE
415 */
416static int incrypto34_restore_security_env(sc_card_t *card, int se_num)
417{
418        sc_apdu_t apdu;
419        int     r;
420
421        SC_FUNC_CALLED(card->ctx, 1);
422
423        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
424
425        r = sc_transmit_apdu(card, &apdu);
426        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
427
428        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
429        SC_TEST_RET(card->ctx, r, "Card returned error");
430
431        SC_FUNC_RETURN(card->ctx, 1, r);
432}
433
434/*
435 * Set the security context
436 * Things get a little messy here. It seems you cannot do any
437 * crypto without a security environment - but there isn't really
438 * a way to specify the security environment in PKCS15.
439 * What I'm doing here (for now) is to assume that for a key
440 * object with ID 0xNN there is always a corresponding SE object
441 * with the same ID.
442 * XXX Need to find out how the Aladdin drivers do it.
443 */
444static int incrypto34_set_security_env(sc_card_t *card,
445                    const sc_security_env_t *env, int se_num)
446{
447        sc_apdu_t apdu;
448        u8      data[3];
449        int     key_id, r;
450
451        assert(card != NULL && env != NULL);
452
453        if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
454         || env->key_ref_len != 1) {
455                sc_error(card->ctx, "No or invalid key reference\n");
456                return SC_ERROR_INVALID_ARGUMENTS;
457        }
458        key_id = env->key_ref[0];
459
460        r = incrypto34_restore_security_env(card, 1);
461        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
462
463        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF1, 0);
464        switch (env->operation) {
465        case SC_SEC_OPERATION_DECIPHER:
466                apdu.p2 = 0xB8;
467                break;
468        case SC_SEC_OPERATION_SIGN:
469                apdu.p2 = 0xB6;
470                break;
471        default:
472                return SC_ERROR_INVALID_ARGUMENTS;
473        }
474
475        data[0] = 0x83;
476        data[1] = 0x01;
477        data[2] = key_id;
478        apdu.lc = apdu.datalen = 3;
479        apdu.data = data;
480
481        r = sc_transmit_apdu(card, &apdu);
482        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
483
484        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
485        SC_TEST_RET(card->ctx, r, "Card returned error");
486
487        SC_FUNC_RETURN(card->ctx, 1, r);
488}
489
490/*
491 * Compute digital signature
492 */
493
494/* internal function to do the actual signature computation */
495static int do_compute_signature(sc_card_t *card,
496                const u8 *data, size_t datalen, u8 *out, size_t outlen)
497{
498        int r;
499        sc_apdu_t apdu;
500        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
501        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
502
503        if (datalen > SC_MAX_APDU_BUFFER_SIZE ||
504            outlen > SC_MAX_APDU_BUFFER_SIZE)
505                return SC_ERROR_INTERNAL;
506
507        /* INS: 0x2A  PERFORM SECURITY OPERATION
508         * P1:  0x9E  Resp: Digital Signature
509         * P2:  0x9A  Cmd: Input for Digital Signature */
510        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
511        apdu.resp = rbuf;
512        apdu.le = outlen;
513        apdu.resplen = sizeof(rbuf);
514
515        memcpy(sbuf, data, datalen);
516        apdu.data = sbuf;
517        apdu.lc = datalen;
518        apdu.datalen = datalen;
519        apdu.sensitive = 1;
520        r = sc_transmit_apdu(card, &apdu);
521        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
522
523        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
524                memcpy(out, rbuf, outlen);
525                SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
526        }
527        SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
528}
529
530static int
531incrypto34_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
532                         u8 *out, size_t outlen)
533{
534        int    r;
535        u8     buf[SC_MAX_APDU_BUFFER_SIZE];
536        size_t buf_len = sizeof(buf), tmp_len = buf_len;
537        sc_context_t *ctx;
538
539        assert(card != NULL && data != NULL && out != NULL);
540        ctx = card->ctx;
541        SC_FUNC_CALLED(ctx, 1);
542
543        if (datalen > 255)
544                SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
545        if (outlen < datalen)
546                SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_BUFFER_TOO_SMALL);
547        outlen = datalen;
548
549        /* XXX As we don't know what operations are allowed with a
550         * certain key, let's try RSA_PURE etc. and see which operation
551         * succeeds (this is not really beautiful, but currently the
552         * only way I see) -- Nils
553         */
554        if (ctx->debug >= 3)
555                sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
556        sc_ctx_suppress_errors_on(ctx);
557        r = do_compute_signature(card, data, datalen, out, outlen);
558        sc_ctx_suppress_errors_off(ctx);
559        if (r >= SC_SUCCESS)
560                SC_FUNC_RETURN(ctx, 4, r);
561        if (ctx->debug >= 3)
562                sc_debug(ctx, "trying RSA_SIG (just the DigestInfo)\n");
563        /* remove padding: first try pkcs1 bt01 padding */
564        r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len);
565        if (r != SC_SUCCESS) {
566                const u8 *p = data;
567                /* no pkcs1 bt01 padding => let's try zero padding.
568                 * This can only work if the data tbs doesn't have a
569                 * leading 0 byte. */
570                tmp_len = buf_len;
571                while (*p == 0 && tmp_len != 0) {
572                        ++p;
573                        --tmp_len;
574                }
575                memcpy(buf, p, tmp_len);
576        }
577        sc_ctx_suppress_errors_on(ctx);
578        r = do_compute_signature(card, buf, tmp_len, out, outlen);
579        sc_ctx_suppress_errors_off(ctx);
580        if (r >= SC_SUCCESS)
581                SC_FUNC_RETURN(ctx, 4, r);
582        if (ctx->debug >= 3)
583                sc_debug(ctx, "trying to sign raw hash value\n");
584        r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
585        if (r != SC_SUCCESS)
586                SC_FUNC_RETURN(ctx, 4, r);
587        return do_compute_signature(card, buf, buf_len, out, outlen);
588}
589
590static int
591incrypto34_lifecycle_get(sc_card_t *card, int *mode)
592{
593        sc_apdu_t       apdu;
594        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
595        int             r;
596
597        SC_FUNC_CALLED(card->ctx, 1);
598
599        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 01, 0x83);
600        apdu.cla = 0x00;
601        apdu.le = 256;
602        apdu.resplen = sizeof(rbuf);
603        apdu.resp = rbuf;
604
605        r = sc_transmit_apdu(card, &apdu);
606        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
607
608        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
609        SC_TEST_RET(card->ctx, r, "Card returned error");
610
611        if (apdu.resplen < 1) {
612                SC_TEST_RET(card->ctx, r, "Lifecycle byte not in response");
613        }
614
615        r = SC_SUCCESS;
616        switch (rbuf[0]) {
617        case 0x10:
618                *mode = SC_CARDCTRL_LIFECYCLE_USER;
619                break;
620        case 0x20:
621                *mode = SC_CARDCTRL_LIFECYCLE_ADMIN;
622                break;
623        case 0x34: /* MANUFACTURING */
624                *mode = SC_CARDCTRL_LIFECYCLE_OTHER;
625                break;
626        default:
627                sc_error(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
628                r = SC_ERROR_INTERNAL;
629        }
630
631        SC_FUNC_RETURN(card->ctx, 1, r);
632}
633
634#if 0
635static int
636incrypto34_lifecycle_set(sc_card_t *card, int *mode)
637{
638        sc_apdu_t       apdu;
639        int             r;
640
641        int current;
642        int target;
643
644        SC_FUNC_CALLED(card->ctx, 1);
645
646        target = *mode;
647
648        r = incrypto34_lifecycle_get(card, &current);
649
650        if (r != SC_SUCCESS)
651                return r;
652
653        if (current == target || current == SC_CARDCTRL_LIFECYCLE_OTHER)
654                return SC_SUCCESS;
655
656        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x10, 0, 0);
657        apdu.cla = 0x80;
658        apdu.le = 0;
659        apdu.resplen = 0;
660        apdu.resp = NULL;
661
662        r = sc_transmit_apdu(card, &apdu);
663        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
664
665        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
666        SC_TEST_RET(card->ctx, r, "Card returned error");
667
668        SC_FUNC_RETURN(card->ctx, 1, r);
669}
670#endif
671
672static int
673incrypto34_put_data_oci(sc_card_t *card,
674                        struct sc_cardctl_incrypto34_obj_info *args)
675{
676        sc_apdu_t       apdu;
677        int             r;
678
679        SC_FUNC_CALLED(card->ctx, 1);
680
681        memset(&apdu, 0, sizeof(apdu));
682        apdu.cse = SC_APDU_CASE_3_SHORT;
683        apdu.cla = 0x00;
684        apdu.ins = 0xda;
685        apdu.p1  = 0x01;
686        apdu.p2  = 0x6e;
687        apdu.lc  = args->len;
688        apdu.data = args->data;
689        apdu.datalen = args->len;
690
691        r = sc_transmit_apdu(card, &apdu);
692        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
693
694        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
695        SC_TEST_RET(card->ctx, r, "Card returned error");
696
697        SC_FUNC_RETURN(card->ctx, 1, r);
698}
699
700static int
701incrypto34_change_key_data(struct sc_card *card,
702                        struct sc_cardctl_incrypto34_obj_info *args)
703{
704        struct sc_apdu  apdu;
705        int             r;
706
707        memset(&apdu, 0, sizeof(apdu));
708        apdu.cse = SC_APDU_CASE_3_SHORT;
709        apdu.cla = 0x90;
710        apdu.ins = 0x24;
711        apdu.p1  = args->key_class;
712        apdu.p2  = args->key_id;
713        apdu.lc  = args->len;
714        apdu.data = args->data;
715        apdu.datalen = args->len;
716
717        r = sc_transmit_apdu(card, &apdu);
718        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
719
720        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
721        SC_TEST_RET(card->ctx, r, "Card returned error");
722
723        return r;
724}
725
726static int
727incrypto34_put_data_seci(sc_card_t *card,
728                        struct sc_cardctl_incrypto34_obj_info *args)
729{
730        sc_apdu_t       apdu;
731        int             r;
732
733        memset(&apdu, 0, sizeof(apdu));
734        apdu.cse = SC_APDU_CASE_3_SHORT;
735        apdu.cla = 0x00;
736        apdu.ins = 0xda;
737        apdu.p1  = 0x01;
738        apdu.p2  = 0x6d;
739        apdu.lc  = args->len;
740        apdu.data = args->data;
741        apdu.datalen = args->len;
742
743        r = sc_transmit_apdu(card, &apdu);
744        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
745
746        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
747        SC_TEST_RET(card->ctx, r, "Card returned error");
748
749        return r;
750}
751
752static int
753incrypto34_generate_key(sc_card_t *card,
754                struct sc_cardctl_incrypto34_genkey_info *args)
755{
756        sc_apdu_t       apdu;
757        u8              data[8];
758        int             r;
759
760        data[0] = 0x20;         /* store as PSO object */
761        data[1] = args->key_id;
762        data[2] = args->fid >> 8;
763        data[3] = args->fid & 0xff;
764        data[4] = 0;            /* additional Rabin Miller tests */
765        data[5] = 0x10;         /* length difference between p, q (bits) */
766        data[6] = 0;            /* default length of exponent, MSB */
767        data[7] = 0x20;         /* default length of exponent, LSB */
768
769        memset(&apdu, 0, sizeof(apdu));
770        apdu.cse = SC_APDU_CASE_3_SHORT;
771        apdu.cla = 0x00;
772        apdu.ins = 0x46;
773        apdu.p1  = 0x00;
774        apdu.p2  = args->key_id;/* doc is not clear, it just says "ID" */
775        apdu.p2  = 0x00;
776        apdu.data= data;
777        apdu.datalen = apdu.lc = sizeof(data);
778
779        r = sc_transmit_apdu(card, &apdu);
780        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
781        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
782        SC_TEST_RET(card->ctx, r, "GENERATE_KEY failed");
783
784        return r;
785}
786
787static int
788incrypto34_erase_files(sc_card_t *card)
789{
790        sc_apdu_t       apdu;
791        int             r;
792        static u8 pCreateAtrFile[] = {
793                        0x62, 0x1b,
794                        0x80, 0x02, 0x00, 0x1e,
795                        0x82, 0x03, 0x01, 0xff, 0xff,
796                        0x83, 0x02, 0x2f, 0x01,
797                        0x85, 0x01, 0x01,
798                        0x86, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
799        static u8 pWriteAtr[] = { 0x19, 0x3b, 0xff,
800                        0x18, 0x00, 0xff, 0x81, 0x31, 0xfe, 0x55, 0x00,
801                        0x6b, 0x02, 0x09, 0x02, 0x00, 0x01, 0x01, 0x01,
802                        0x43, 0x4e, 0x53, 0x10, 0x31, 0x80, 0x9f };
803        static u8 pCreateEF_DIR_ADOFile[] = { 0x6F, 0x1D,
804                        0x83, 0x02,
805                        0xFD, 0x01, 0x85, 0x03, 0x01, 0xff, 0xff,
806                        0x81, 0x02,
807                        0x00, 0x64,
808                        0x82, 0x03, 0x05, 0xff, 0xff,
809                        0x86, 0x09, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
810
811        /* Erasing Filesystem */
812        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xf5, 0, 0);
813        apdu.cla = 0xb0;
814
815        r = sc_transmit_apdu(card, &apdu);
816        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
817
818        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
819        SC_TEST_RET(card->ctx, r, "Card returned error Erasing Filesystem");
820
821        /* Creating ATR file*/
822        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xe0, 0, 0);
823        apdu.data = pCreateAtrFile;
824        apdu.datalen = apdu.lc = sizeof(pCreateAtrFile);
825
826        r = sc_transmit_apdu(card, &apdu);
827        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
828
829        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
830        SC_TEST_RET(card->ctx, r, "Card returned error Creating ATR file");
831
832        /* Filling ATR file*/
833        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xd6, 0, 0);
834        apdu.data = pWriteAtr;
835        apdu.datalen = apdu.lc = sizeof(pWriteAtr);
836
837        r = sc_transmit_apdu(card, &apdu);
838        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
839
840        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
841        SC_TEST_RET(card->ctx, r, "Card returned error Filling ATR file");
842
843        /* Creating DIR-ADO file*/
844        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xe0, 0, 0);
845        apdu.data = pCreateEF_DIR_ADOFile;
846        apdu.datalen = apdu.lc = sizeof(pCreateEF_DIR_ADOFile);
847
848        r = sc_transmit_apdu(card, &apdu);
849        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
850
851        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
852        SC_TEST_RET(card->ctx, r, "Card returned error Creating DIR-ADO file");
853
854        return r;
855
856}
857
858
859static int
860incrypto34_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
861{
862        switch (cmd) {
863        case SC_CARDCTL_INCRYPTO34_PUT_DATA_FCI:
864                break;
865        case SC_CARDCTL_INCRYPTO34_PUT_DATA_OCI:
866                return incrypto34_put_data_oci(card,
867                        (struct sc_cardctl_incrypto34_obj_info *) ptr);
868                break;
869        case SC_CARDCTL_INCRYPTO34_PUT_DATA_SECI:
870                return incrypto34_put_data_seci(card,
871                        (struct sc_cardctl_incrypto34_obj_info *) ptr);
872                break;
873        case SC_CARDCTL_INCRYPTO34_GENERATE_KEY:
874                return incrypto34_generate_key(card,
875                        (struct sc_cardctl_incrypto34_genkey_info *) ptr);
876        case SC_CARDCTL_LIFECYCLE_GET:
877                return incrypto34_lifecycle_get(card, (int *) ptr);
878        case SC_CARDCTL_LIFECYCLE_SET:
879                return 0;
880        case SC_CARDCTL_INCRYPTO34_CHANGE_KEY_DATA:
881                return incrypto34_change_key_data(card, (struct sc_cardctl_incrypto34_obj_info*) ptr);
882        case SC_CARDCTL_INCRYPTO34_ERASE_FILES:
883                return incrypto34_erase_files(card);
884        }
885        return SC_ERROR_NOT_SUPPORTED;
886}
887
888/*
889 * The 0x80 thing tells the card it's okay to search parent
890 * directories as well for the referenced object.
891 * Unfortunately, it doesn't seem to work without this flag :-/
892 */
893static int
894incrypto34_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
895                 int *tries_left)
896{
897        data->flags |= SC_PIN_CMD_NEED_PADDING;
898        data->pin_reference |= 0x80;
899        /* FIXME: the following values depend on what pin length was
900         * used when creating the BS objects */
901        if (data->pin1.max_length == 0)
902                data->pin1.max_length = 8;
903        if (data->pin2.max_length == 0)
904                data->pin2.max_length = 8;
905        return iso_ops->pin_cmd(card, data, tries_left);
906}
907
908
909
910static struct sc_card_driver * sc_get_driver(void)
911{
912        if (iso_ops == NULL)
913                iso_ops = sc_get_iso7816_driver()->ops;
914        incrypto34_ops = *iso_ops;
915        incrypto34_ops.match_card = incrypto34_match_card;
916        incrypto34_ops.init = incrypto34_init;
917        incrypto34_ops.finish = incrypto34_finish;
918        incrypto34_ops.select_file = incrypto34_select_file;
919        incrypto34_ops.create_file = incrypto34_create_file;
920        incrypto34_ops.set_security_env = incrypto34_set_security_env;
921        incrypto34_ops.restore_security_env = incrypto34_restore_security_env;
922        incrypto34_ops.compute_signature = incrypto34_compute_signature;
923
924        incrypto34_ops.list_files = incrypto34_list_files;
925        incrypto34_ops.check_sw = incrypto34_check_sw;
926        incrypto34_ops.card_ctl = incrypto34_card_ctl;
927        incrypto34_ops.pin_cmd = incrypto34_pin_cmd;
928
929        return &incrypto34_drv;
930}
931
932#if 1
933struct sc_card_driver * sc_get_incrypto34_driver(void)
934{
935        return sc_get_driver();
936}
937#endif
Note: See TracBrowser for help on using the browser.