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

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

convert C++ in C comment

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * card-oberthur.c: Support for Oberthur smart cards
3 *              CosmopolIC  v5;
4 *
5 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
6 * Copyright (C) 2003  Viktor Tarasov <vtarasov@idealx.com>, idealx <www.idealx.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 *
22 * best view with tabstop=4
23 */
24
25#include "internal.h"
26#include "cardctl.h"
27#include "pkcs15.h"
28
29#ifdef ENABLE_OPENSSL
30#include <stdlib.h>
31#include <string.h>
32#include <ctype.h>
33#include <openssl/sha.h>
34#include <openssl/evp.h>
35#include <openssl/rsa.h>
36#include <openssl/opensslv.h>
37
38/* keep OpenSSL 0.9.6 users happy ;-) */
39#if OPENSSL_VERSION_NUMBER < 0x00907000L
40#define DES_cblock                      des_cblock
41#define DES_key_schedule                des_key_schedule
42#define DES_set_key_unchecked(a,b)      des_set_key_unchecked(a,*b)
43#define DES_ecb_encrypt(a,b,c,d)        des_ecb_encrypt(a,b,*c,d)
44#endif
45
46#define NOT_YET 1
47
48static struct sc_atr_table oberthur_atrs[] = {
49        { "3B:7D:18:00:00:00:31:80:71:8E:64:77:E3:01:00:82:90:00", NULL,
50                        "Oberthur 64k v4/2.1.1", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
51        { "3B:7D:18:00:00:00:31:80:71:8E:64:77:E3:02:00:82:90:00", NULL,
52                        "Oberthur 64k v4/2.1.1", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
53        { "3B:7D:11:00:00:00:31:80:71:8E:64:77:E3:01:00:82:90:00", NULL,
54                        "Oberthur 64k v5", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
55        { "3B:7D:11:00:00:00:31:80:71:8E:64:77:E3:02:00:82:90:00", NULL,
56                        "Oberthur 64k v5/2.2.0", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
57        { "3B:7B:18:00:00:00:31:C0:64:77:E3:03:00:82:90:00", NULL,
58                        "Oberthur 64k CosmopolIC v5.2/2.2", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
59        { NULL, NULL, NULL, 0, 0, NULL }
60};
61
62struct auth_senv {
63        unsigned int algorithm;
64        int key_file_id;
65        size_t key_size;
66};
67typedef struct auth_senv auth_senv_t;
68
69struct auth_private_data {
70        unsigned char aid[SC_MAX_AID_SIZE];
71        int aid_len;
72       
73        struct sc_pin_cmd_pin pin_info;
74        auth_senv_t senv;
75       
76        long int sn;
77};
78typedef struct auth_private_data auth_private_data_t;
79
80struct auth_update_component_info {
81        enum SC_CARDCTL_OBERTHUR_KEY_TYPE  type;
82        unsigned int    component;
83        unsigned char   *data;
84        unsigned int    len;
85};
86typedef struct auth_update_component_info auth_update_component_info_t;
87
88
89static const unsigned char *aidAuthentIC_V5 =
90                (const u8 *)"\xA0\x00\x00\x00\x77\x01\x03\x03\x00\x00\x00\xF1\x00\x00\x00\x02";
91static const int lenAidAuthentIC_V5 = 16;
92static const char *nameAidAuthentIC_V5 = "AuthentIC v5";
93
94#define AUTH_PIN                1
95#define AUTH_PUK                2
96
97#define SC_OBERTHUR_MAX_ATTR_SIZE       8
98
99#define PUBKEY_512_ASN1_SIZE    0x4A
100#define PUBKEY_1024_ASN1_SIZE   0x8C
101#define PUBKEY_2048_ASN1_SIZE   0x10E
102
103static unsigned char rsa_der[PUBKEY_2048_ASN1_SIZE];
104static int rsa_der_len = 0;
105
106static sc_file_t *auth_current_ef = NULL,  *auth_current_df = NULL;
107static struct sc_card_operations auth_ops;
108static struct sc_card_operations *iso_ops;
109static struct sc_card_driver auth_drv = {
110        "Oberthur AuthentIC.v2/CosmopolIC.v4",
111        "oberthur",
112        &auth_ops,
113        NULL, 0, NULL
114};
115
116static int auth_get_pin_reference (sc_card_t *card,
117                int type, int reference, int cmd, int *out_ref);
118static int auth_read_component(sc_card_t *card,
119                enum SC_CARDCTL_OBERTHUR_KEY_TYPE type, int num,
120                unsigned char *out, size_t outlen);
121static int auth_verify(sc_card_t *card, unsigned int type,
122                int ref, const u8 *data, size_t data_len, int *tries_left);
123static int auth_create_reference_data (sc_card_t *card,
124                struct sc_cardctl_oberthur_createpin_info *args);
125static int auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial);
126static int auth_select_file(sc_card_t *card, const sc_path_t *in_path,
127                sc_file_t **file_out);
128
129#ifndef NOT_YET
130static int auth_sm_init (struct sc_card *card, struct sc_sm_info *sm_info,
131                int cmd, unsigned char *id, size_t id_len,
132                unsigned char *resp, size_t *resp_len);
133static int auth_sm_execute (struct sc_card *card, struct sc_sm_info *sm_info,
134                unsigned char *data, int data_len, unsigned char *out, size_t len);
135static int auth_sm_update_rsa (struct sc_card *card,
136                struct sc_cardctl_oberthur_updatekey_info *data);
137static int auth_sm_reset_pin (struct sc_card *card, int type, int ref,
138                const unsigned char *data, size_t len);
139static int auth_sm_read_binary (struct sc_card *card,
140                unsigned char *id, size_t id_len,
141                size_t offs, unsigned char *out, size_t len);
142static int auth_sm_release (struct sc_card *card, struct sc_sm_info *sm_info,
143                unsigned char *data, int data_len);
144#endif
145
146#if 0
147/* this function isn't used anywhere */
148static void _auth_print_acls(struct sc_card *card, struct sc_file *file)
149{
150        int ii, jj;   
151       
152        for (jj=0; jj < SC_MAX_AC_OPS; jj++)   {
153                const sc_acl_entry_t *acl = sc_file_get_acl_entry(file, jj);
154                       
155                for (ii=0; acl; acl = acl->next, ii++) {
156                        sc_debug(card->ctx, "%i-%i: acl : meth 0x%X, ref 0x%X",
157                                        jj, ii, acl->method, acl->key_ref);
158                }
159        }
160}
161#endif
162
163static int 
164auth_finish(sc_card_t *card)
165{
166        free(card->drv_data);
167        return SC_SUCCESS;
168}
169
170
171static int 
172auth_select_aid(sc_card_t *card)
173{
174        sc_apdu_t apdu;
175        unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
176        struct auth_private_data *data =  (struct auth_private_data *) card->drv_data;
177        int rv, ii;
178        unsigned char cm[7] = {0xA0,0x00,0x00,0x00,0x03,0x00,0x00};
179        sc_path_t tmp_path;
180
181        /* Select Card Manager (to deselect previously selected application) */
182        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C);
183        apdu.lc = sizeof(cm);
184        /* apdu.le = sizeof(cm)+4; */
185        apdu.le = 0;
186        apdu.data = cm;
187        apdu.datalen = sizeof(cm);
188        apdu.resplen = sizeof(apdu_resp);
189        apdu.resp = apdu_resp;
190
191        rv = sc_transmit_apdu(card, &apdu);
192        SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
193       
194        /* Get smart card serial number */
195        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x9F, 0x7F);
196        apdu.cla = 0x80;
197        apdu.le = 0x2D;
198        apdu.resplen = 0x30;
199        apdu.resp = apdu_resp;
200       
201        rv = sc_transmit_apdu(card, &apdu);
202        SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
203        card->serialnr.len = 4;
204        memcpy(card->serialnr.value, apdu.resp+15, 4);
205
206        for (ii=0, data->sn = 0; ii < 4; ii++)
207                data->sn += (int)(*(apdu.resp + 15 + ii)) << (3-ii)*8;
208       
209        sc_debug(card->ctx, "serial number %li/0x%lX\n", data->sn, data->sn);
210               
211        tmp_path.type = SC_PATH_TYPE_DF_NAME;
212        memcpy(tmp_path.value, aidAuthentIC_V5, lenAidAuthentIC_V5);
213        tmp_path.len = lenAidAuthentIC_V5;
214
215        rv = iso_ops->select_file(card, &tmp_path, NULL);
216        sc_debug(card->ctx, "rv %i\n", rv);
217        SC_TEST_RET(card->ctx, rv, "select parent failed");
218       
219        sc_format_path("3F00", &tmp_path);
220        rv = iso_ops->select_file(card, &tmp_path, &auth_current_df);
221        sc_debug(card->ctx, "rv %i\n", rv);
222        SC_TEST_RET(card->ctx, rv, "select parent failed");
223       
224        sc_format_path("3F00", &card->cache.current_path);
225        sc_file_dup(&auth_current_ef, auth_current_df);
226               
227        memcpy(data->aid, aidAuthentIC_V5, lenAidAuthentIC_V5);
228        data->aid_len = lenAidAuthentIC_V5;
229        card->name = nameAidAuthentIC_V5;
230
231        sc_debug(card->ctx, "return %i\n", rv);
232        SC_FUNC_RETURN(card->ctx, 1, rv);
233}
234
235static int 
236auth_match_card(sc_card_t *card)
237{
238        if (_sc_match_atr(card, oberthur_atrs, &card->type) < 0)
239                return 0;
240        else
241                return 1;
242}
243
244static int 
245auth_init(sc_card_t *card)
246{
247        int rv = 0;
248        unsigned long flags;
249        struct auth_private_data *data;
250        sc_path_t path;
251       
252        data = (struct auth_private_data *) malloc(sizeof(struct auth_private_data));
253        if (!data)
254                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
255        else
256                memset(data, 0, sizeof(struct auth_private_data));
257
258        card->cla = 0x00;
259        card->drv_data = data;
260
261        card->caps |= SC_CARD_CAP_RNG;
262        card->caps |= SC_CARD_CAP_USE_FCI_AC;
263
264        if (auth_select_aid(card))   {
265                sc_error(card->ctx, "Failed to initialize %s\n", card->name);
266                SC_TEST_RET(card->ctx, SC_ERROR_INVALID_CARD, "Failed to initialize");
267        }
268       
269        flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_PAD_ISO9796;
270        flags |= SC_ALGORITHM_RSA_HASH_NONE;
271        flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
272
273        _sc_card_add_rsa_alg(card, 512, flags, 0);
274        _sc_card_add_rsa_alg(card, 1024, flags, 0);
275        _sc_card_add_rsa_alg(card, 2048, flags, 0);
276#if 0
277        flags = SC_ALGORITHM_SKEY_CBC | SC_ALGORITHM_SKEY_ECB;
278        memset(&info, 0, sizeof(info));
279        info.algorithm = SC_ALGORITHM_DES;
280        info.flags = flags;
281        info.key_length = 64;
282        _sc_card_add_algorithm(card, &info);
283       
284        flags = SC_ALGORITHM_SKEY_CBC | SC_ALGORITHM_SKEY_ECB;
285        info.algorithm = SC_ALGORITHM_3DES;
286        info.flags = flags;
287        info.key_length = 192;
288        _sc_card_add_algorithm(card, &info);
289#endif
290
291        sc_format_path("3F00", &path);
292        rv = auth_select_file(card, &path, NULL);
293
294        SC_FUNC_RETURN(card->ctx, 1, rv);
295}
296
297
298static void 
299add_acl_entry(sc_card_t *card, sc_file_t *file, unsigned int op,
300                u8 acl_byte)
301{
302        if ((acl_byte & 0xE0) == 0x60)   {
303                sc_debug(card->ctx, "called; op 0x%X; SC_AC_PRO; ref 0x%X\n", op, acl_byte);
304                sc_file_add_acl_entry(file, op, SC_AC_PRO, acl_byte);
305                return;
306        }
307       
308        switch (acl_byte) {
309        case 0x00:
310                sc_file_add_acl_entry(file, op, SC_AC_NONE, SC_AC_KEY_REF_NONE);
311                break;
312        case 0x21:
313        case 0x22:
314        case 0x23:
315        case 0x24:
316        case 0x25:
317                sc_file_add_acl_entry(file, op, SC_AC_CHV, acl_byte & 0x0F);
318                break;
319        case 0xFF:
320                sc_file_add_acl_entry(file, op, SC_AC_NEVER, SC_AC_KEY_REF_NONE);
321                break;
322        default:
323                sc_file_add_acl_entry(file, op, SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE);
324                break;
325        }
326}
327
328
329static int 
330tlv_get(const unsigned char *msg, int len,
331                unsigned char tag,
332                unsigned char *ret, int *ret_len)
333{
334        int cur = 0;
335       
336        while (cur < len)  {
337                if (*(msg+cur)==tag)  {
338                        int ii, ln = *(msg+cur+1);
339               
340                        if (ln > *ret_len)   
341                                return SC_ERROR_WRONG_LENGTH;
342
343                        for (ii=0; ii<ln; ii++)
344                                *(ret + ii) = *(msg+cur+2+ii);
345                        *ret_len = ln;
346                       
347                        return SC_SUCCESS;
348                }
349               
350                cur += 2 + *(msg+cur+1);
351        }
352               
353        return SC_ERROR_INCORRECT_PARAMETERS;
354}
355
356
357static int
358auth_process_fci(struct sc_card *card, struct sc_file *file,
359            const unsigned char *buf, size_t buflen)
360{
361        unsigned char type, attr[SC_OBERTHUR_MAX_ATTR_SIZE];
362        int attr_len = sizeof(attr);
363       
364        SC_FUNC_CALLED(card->ctx, 1);
365        attr_len = sizeof(attr);
366        if (tlv_get(buf, buflen, 0x82, attr, &attr_len))
367                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
368        type = attr[0];
369       
370        attr_len = sizeof(attr);
371        if (tlv_get(buf, buflen, 0x83, attr, &attr_len))
372                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
373        file->id = attr[0]*0x100 + attr[1];
374       
375        attr_len = sizeof(attr);
376        if (tlv_get(buf, buflen, type==0x01 ? 0x80 : 0x85, attr, &attr_len))
377                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
378        if (attr_len<2 && type != 0x04)
379                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
380               
381        switch (type) {
382        case 0x01:
383                file->type = SC_FILE_TYPE_WORKING_EF;
384                file->ef_structure = SC_FILE_EF_TRANSPARENT;
385                file->size = attr[0]*0x100 + attr[1];
386                break;
387        case 0x04:
388                file->type = SC_FILE_TYPE_WORKING_EF;
389                file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
390                file->size = attr[0];
391                attr_len = sizeof(attr);
392                if (tlv_get(buf, buflen, 0x82, attr, &attr_len))
393                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
394                if (attr_len!=5)
395                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
396                file->record_length = attr[2]*0x100+attr[3];
397                file->record_count = attr[4];
398                break;
399        case 0x11:
400                file->type = SC_FILE_TYPE_INTERNAL_EF;
401                file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_DES;
402                file->size = attr[0]*0x100 + attr[1];
403                file->size /= 8;
404                break;
405        case 0x12:
406                file->type = SC_FILE_TYPE_INTERNAL_EF;
407                file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
408               
409                file->size = attr[0]*0x100 + attr[1];
410                if (file->size==512)
411                        file->size = PUBKEY_512_ASN1_SIZE;
412                else if (file->size==1024)
413                        file->size = PUBKEY_1024_ASN1_SIZE;
414                else if (file->size==2048)
415                        file->size = PUBKEY_2048_ASN1_SIZE;
416                else   {
417                        sc_error(card->ctx, "Not supported public key size: %i\n", file->size);
418                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
419                }
420                break;
421        case 0x14:
422                file->type = SC_FILE_TYPE_INTERNAL_EF;
423                file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT;
424                file->size = attr[0]*0x100 + attr[1];
425                break;
426        case 0x38:
427                file->type = SC_FILE_TYPE_DF;
428                file->size = attr[0];
429                sc_file_set_type_attr(file,attr,attr_len);
430                break;
431        default:
432                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
433        }
434       
435        attr_len = sizeof(attr);
436        if (tlv_get(buf, buflen, 0x86, attr, &attr_len))
437                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
438        if (attr_len<8)
439                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
440
441        if (file->type == SC_FILE_TYPE_DF) {
442                add_acl_entry(card, file, SC_AC_OP_CREATE, attr[0]);
443                add_acl_entry(card, file, SC_AC_OP_CRYPTO, attr[1]);
444                add_acl_entry(card, file, SC_AC_OP_LIST_FILES, attr[2]);
445                add_acl_entry(card, file, SC_AC_OP_DELETE, attr[3]);
446#ifndef NOT_YET         
447                add_acl_entry(card, file, SC_AC_OP_PIN_SET, attr[4]);
448                add_acl_entry(card, file, SC_AC_OP_PIN_CHANGE, attr[5]);
449                add_acl_entry(card, file, SC_AC_OP_PIN_RESET, attr[6]);
450#endif
451        }
452        else if (file->type == SC_FILE_TYPE_INTERNAL_EF)  { /* EF */
453                switch (file->ef_structure) {
454                case SC_CARDCTL_OBERTHUR_KEY_DES:
455                        add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
456#if 0
457                        add_acl_entry(card, file, SC_AC_OP_DECRYPT, attr[1]);
458                        add_acl_entry(card, file, SC_AC_OP_ENCRYPT, attr[2]);
459                        add_acl_entry(card, file, SC_AC_OP_CHECKSUM, attr[3]);
460                        add_acl_entry(card, file, SC_AC_OP_VERIFY, attr[4]);
461#else
462                        add_acl_entry(card, file, SC_AC_OP_READ, attr[1]);
463#endif
464                        break;
465                case SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC:
466                        add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
467#if 0
468                        add_acl_entry(card, file, SC_AC_OP_ENCRYPT, attr[2]);
469                        add_acl_entry(card, file, SC_AC_OP_VERIFY, attr[4]);
470#else
471                        add_acl_entry(card, file, SC_AC_OP_READ, attr[2]);
472#endif
473                        break;
474                case SC_CARDCTL_OBERTHUR_KEY_RSA_CRT:
475                        add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
476#if 0
477                        add_acl_entry(card, file, SC_AC_OP_DECRYPT, attr[1]);
478                        add_acl_entry(card, file, SC_AC_OP_SIGN, attr[3]);
479#else
480                        add_acl_entry(card, file, SC_AC_OP_READ, attr[1]);
481#endif
482                        break;
483                }
484        }
485        else   {
486                switch (file->ef_structure) {
487                case SC_FILE_EF_TRANSPARENT:
488                        add_acl_entry(card, file, SC_AC_OP_WRITE, attr[0]);
489                        add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[1]);
490                        add_acl_entry(card, file, SC_AC_OP_READ, attr[2]);
491                        add_acl_entry(card, file, SC_AC_OP_ERASE, attr[3]);
492                        break;
493                case SC_FILE_EF_LINEAR_VARIABLE:
494                        add_acl_entry(card, file, SC_AC_OP_WRITE, attr[0]);
495                        add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[1]);
496                        add_acl_entry(card, file, SC_AC_OP_READ, attr[2]);
497                        add_acl_entry(card, file, SC_AC_OP_ERASE, attr[3]);
498                        break;
499                }
500        }
501
502        file->status = SC_FILE_STATUS_ACTIVATED;
503        file->magic = SC_FILE_MAGIC;
504
505        SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
506}
507
508
509static int 
510auth_select_file(sc_card_t *card, const sc_path_t *in_path,
511                                 sc_file_t **file_out)
512{
513        int rv;
514        size_t offs, ii;
515        sc_path_t path;
516        sc_file_t *tmp_file = NULL;
517
518        SC_FUNC_CALLED(card->ctx, 1);
519        assert(card != NULL && in_path != NULL);
520
521        memcpy(&path, in_path, sizeof(sc_path_t));
522       
523        sc_debug(card->ctx, "in_path; type=%d, path=%s, out %p\n",
524                        in_path->type, sc_print_path(in_path), file_out);
525        sc_debug(card->ctx, "current path; type=%d, path=%s\n",
526                        auth_current_df->path.type, sc_print_path(&auth_current_df->path));
527        if (auth_current_ef)
528                sc_debug(card->ctx, "current file; type=%d, path=%s\n",
529                                auth_current_ef->path.type, sc_print_path(&auth_current_ef->path));
530
531        if (path.type == SC_PATH_TYPE_PARENT || path.type == SC_PATH_TYPE_FILE_ID)   {
532                if (auth_current_ef)
533                        sc_file_free(auth_current_ef);
534                auth_current_ef = NULL;
535               
536                rv = iso_ops->select_file(card, &path, &tmp_file);
537                SC_TEST_RET(card->ctx, rv, "select file failed");
538               
539                if (path.type == SC_PATH_TYPE_PARENT)   {
540                        memcpy(&tmp_file->path, &auth_current_df->path, sizeof(sc_path_t));
541                        if (tmp_file->path.len > 2)
542                                tmp_file->path.len -= 2;
543                       
544                        sc_file_free(auth_current_df);
545                        sc_file_dup(&auth_current_df, tmp_file);
546                }
547                else   {
548                        if (tmp_file->type == SC_FILE_TYPE_DF)   {
549                                sc_concatenate_path(&tmp_file->path, &auth_current_df->path, &path);
550                               
551                                sc_file_free(auth_current_df);
552                                sc_file_dup(&auth_current_df, tmp_file);
553                        }
554                        else   {
555                                if (auth_current_ef)   
556                                        sc_file_free(auth_current_ef);
557
558                                sc_file_dup(&auth_current_ef, tmp_file);
559                                sc_concatenate_path(&auth_current_ef->path, &auth_current_df->path, &path);
560                        }
561                }
562                if (file_out)
563                        sc_file_dup(file_out, tmp_file);
564       
565                sc_file_free(tmp_file);
566        }
567        else if (path.type == SC_PATH_TYPE_DF_NAME)   {
568                rv = iso_ops->select_file(card, &path, NULL);
569                if (rv)   {
570                        if (auth_current_ef)
571                                sc_file_free(auth_current_ef);
572                        auth_current_ef = NULL;
573                }
574                SC_TEST_RET(card->ctx, rv, "select file failed");
575        }
576        else   {
577                for (offs = 0; offs < path.len && offs < auth_current_df->path.len; offs += 2) 
578                        if (path.value[offs] != auth_current_df->path.value[offs] ||
579                                        path.value[offs + 1] != auth_current_df->path.value[offs + 1])
580                                break;
581
582                sc_debug(card->ctx, "offs %i\n", offs);
583                if (offs && offs < auth_current_df->path.len)   {
584                        size_t deep = auth_current_df->path.len - offs;
585
586                        sc_debug(card->ctx, "deep %i\n", deep);
587                        for (ii=0; ii<deep; ii+=2)   {
588                                sc_path_t tmp_path;
589
590                                memcpy(&tmp_path, &auth_current_df->path,  sizeof(sc_path_t));
591                                tmp_path.type = SC_PATH_TYPE_PARENT;
592                               
593                                rv = auth_select_file (card, &tmp_path, file_out);
594                                SC_TEST_RET(card->ctx, rv, "select file failed");
595                        }
596                }
597       
598                if (path.len - offs > 0)   {
599                        sc_path_t tmp_path;
600                       
601                        tmp_path.type = SC_PATH_TYPE_FILE_ID;
602                        tmp_path.len = 2;
603                       
604                        for (ii=0; ii < path.len - offs; ii+=2)   {
605                                memcpy(tmp_path.value, path.value + offs + ii, 2);
606                               
607                                rv = auth_select_file(card, &tmp_path, file_out);
608                                SC_TEST_RET(card->ctx, rv, "select file failed");
609                        }
610                }
611                else if (path.len - offs == 0 && file_out)  {
612                        if (sc_compare_path(&path, &auth_current_df->path))   
613                                sc_file_dup(file_out, auth_current_df);
614                        else  if (auth_current_ef)
615                                sc_file_dup(file_out, auth_current_ef);
616                        else
617                                SC_TEST_RET(card->ctx, SC_ERROR_INTERNAL, "No current EF");
618                }
619        }
620
621        SC_FUNC_RETURN(card->ctx, 1, 0);
622}
623
624
625static int 
626auth_list_files(sc_card_t *card, u8 *buf, size_t buflen)
627{
628        sc_apdu_t apdu;
629        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
630        int rv;
631       
632        SC_FUNC_CALLED(card->ctx, 1);
633        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x34, 0, 0);
634        apdu.cla = 0x80;
635        apdu.le = 0x40;
636        apdu.resplen = sizeof(rbuf);
637        apdu.resp = rbuf;
638       
639        rv = sc_transmit_apdu(card, &apdu);
640        SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
641       
642        rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
643        SC_TEST_RET(card->ctx, rv, "Card returned error");
644       
645        if (apdu.resplen == 0x100 && rbuf[0]==0 && rbuf[1]==0)
646                SC_FUNC_RETURN(card->ctx, 1, 0);
647       
648        buflen = buflen < apdu.resplen ? buflen : apdu.resplen;
649        memcpy(buf, rbuf, buflen);
650       
651        SC_FUNC_RETURN(card->ctx, 1, buflen);
652}
653
654
655static int 
656auth_delete_file(sc_card_t *card, const sc_path_t *path)
657{
658        int rv;
659        u8 sbuf[2];
660        sc_apdu_t apdu;
661
662        SC_FUNC_CALLED(card->ctx, 1);
663        if (card->ctx->debug >= 1) {
664                char pbuf[SC_MAX_PATH_STRING_SIZE];
665
666                rv = sc_path_print(pbuf, sizeof(pbuf), path);
667                if (rv != SC_SUCCESS)
668                        pbuf[0] = '\0';
669
670                sc_debug(card->ctx, "path; type=%d, path=%s\n", path->type, pbuf);
671        }
672
673        if (path->len < 2)   {
674                sc_error(card->ctx, "Invalid path length\n");
675                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
676        }
677       
678        if (path->len > 2)   {
679                sc_path_t parent = *path;
680
681                parent.len -= 2;
682                parent.type = SC_PATH_TYPE_PATH;
683                rv = auth_select_file(card, &parent, NULL);
684                SC_TEST_RET(card->ctx, rv, "select parent failed ");
685        }
686
687        sbuf[0] = path->value[path->len - 2];
688        sbuf[1] = path->value[path->len - 1];
689
690        if (memcmp(sbuf,"\x00\x00",2)==0 || (memcmp(sbuf,"\xFF\xFF",2)==0) ||
691                        memcmp(sbuf,"\x3F\xFF",2)==0)
692                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
693       
694        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x02, 0x00);
695        apdu.lc = 2;
696        apdu.datalen = 2;
697        apdu.data = sbuf;
698       
699        rv = sc_transmit_apdu(card, &apdu);
700        SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
701        if (apdu.sw1==0x6A && apdu.sw2==0x82)   {
702                /* Clean the DF contents.*/
703        sc_path_t tmp_path;
704                u8 lbuf[SC_MAX_APDU_BUFFER_SIZE];
705                int ii, len;
706               
707                tmp_path.type = SC_PATH_TYPE_FILE_ID;
708                memcpy(tmp_path.value, sbuf, 2);
709                tmp_path.len = 2;
710                rv = auth_select_file(card, &tmp_path, NULL);
711                SC_TEST_RET(card->ctx, rv, "select DF failed");
712               
713                len = auth_list_files(card, lbuf, sizeof(lbuf));
714                SC_TEST_RET(card->ctx, len, "list DF failed");
715               
716                for (ii=0; ii<len/2; ii++)   {
717                        sc_path_t tmp_path_x;
718
719                        tmp_path_x.type = SC_PATH_TYPE_FILE_ID;
720                        tmp_path_x.value[0] = *(lbuf + ii*2);
721                        tmp_path_x.value[1] = *(lbuf + ii*2 + 1);
722                        tmp_path_x.len = 2;
723
724                        rv = auth_delete_file(card, &tmp_path_x);
725                        SC_TEST_RET(card->ctx, rv, "delete failed");
726                }
727
728                tmp_path.type = SC_PATH_TYPE_PARENT;
729                rv = auth_select_file(card, &tmp_path, NULL);
730                SC_TEST_RET(card->ctx, rv, "select parent failed");
731               
732                apdu.p1 = 1;
733                rv = sc_transmit_apdu(card, &apdu);
734        }
735               
736        SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
737        rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
738
739        SC_FUNC_RETURN(card->ctx, 1, rv);
740}
741
742
743static int 
744acl_to_ac_byte(sc_card_t *card, const sc_acl_entry_t *e)
745{
746        if (e == NULL)
747                return -1;
748       
749        switch (e->method) {
750        case SC_AC_NONE:
751                SC_FUNC_RETURN(card->ctx, 1, 0);
752               
753        case SC_AC_CHV:
754                if (e->key_ref > 0 && e->key_ref < 6)
755                        SC_FUNC_RETURN(card->ctx, 1, (0x20 | e->key_ref));
756                else
757                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
758               
759        case SC_AC_PRO:
760                if (((e->key_ref & 0xE0) != 0x60) || ((e->key_ref & 0x18) == 0))
761                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
762                else
763                        SC_FUNC_RETURN(card->ctx, 1, e->key_ref);
764                                                                                       
765        case SC_AC_NEVER:
766                return 0xff;
767        }
768               
769        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
770}
771
772
773static int 
774encode_file_structure_V5(sc_card_t *card, const sc_file_t *file,
775                                 u8 *buf, size_t *buflen)
776{
777        u8 *p = buf;
778        int rv=0, size;
779        size_t ii;
780        unsigned char  ops[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
781
782        SC_FUNC_CALLED(card->ctx, 1);
783        sc_debug(card->ctx, "id %04X; size %i; type %i/%i\n",
784                        file->id, file->size, file->type, file->ef_structure);
785       
786        if (*buflen < 0x18)
787                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
788
789        p[0] = 0x62, p[1] = 0x16;
790        p[2] = 0x82, p[3] = 0x02;
791
792        rv = 0;
793        if (file->type == SC_FILE_TYPE_DF)  {
794                p[4] = 0x38;
795                p[5] = 0x00;
796        }
797        else  if (file->type == SC_FILE_TYPE_WORKING_EF)   {
798                switch (file->ef_structure) {
799                case SC_FILE_EF_TRANSPARENT:
800                        p[4] = 0x01;
801                        p[5] = 0x01;
802                        break;
803                case SC_FILE_EF_LINEAR_VARIABLE:
804                        p[4] = 0x04;
805                        p[5] = 0x01;
806                        break;
807                default:
808                        rv = SC_ERROR_INVALID_ARGUMENTS;
809                        break;
810                }
811        }
812        else if (file->type == SC_FILE_TYPE_INTERNAL_EF)  {
813                switch (file->ef_structure) {
814                case SC_CARDCTL_OBERTHUR_KEY_DES:
815                        p[4] = 0x11;
816                        p[5] = 0x00;
817                        break;
818                case SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC:
819                        p[4] = 0x12;
820                        p[5] = 0x00;
821                        break;
822                case SC_CARDCTL_OBERTHUR_KEY_RSA_CRT:
823                        p[4] = 0x14;
824                        p[5] = 0x00;
825                        break;
826                default:
827                        rv = -1;
828                        break;
829                }
830        }
831        else
832                rv = SC_ERROR_INVALID_ARGUMENTS;
833
834        if (rv)   {
835                sc_error(card->ctx, "Invalid EF structure %i/%i\n",
836                                file->type, file->ef_structure);
837                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
838        }
839       
840        p[6] = 0x83;
841        p[7] = 0x02;
842        p[8] = file->id >> 8;
843        p[9] = file->id & 0xFF;
844       
845        p[10] = 0x85;
846        p[11] = 0x02;
847
848        size = file->size;
849       
850        if (file->type == SC_FILE_TYPE_DF)   {
851                size &= 0xFF;
852        }
853        else if (file->type == SC_FILE_TYPE_INTERNAL_EF &&
854                        file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC)   {
855                sc_debug(card->ctx, "ef %s\n","SC_FILE_EF_RSA_PUBLIC");
856                if (file->size == PUBKEY_512_ASN1_SIZE || file->size == 512)
857                        size = 512;
858                else if (file->size == PUBKEY_1024_ASN1_SIZE || file->size == 1024)
859                        size = 1024;
860                else if (file->size == PUBKEY_2048_ASN1_SIZE || file->size == 2048)
861                        size = 2048;
862                else   {
863                        sc_error(card->ctx, "incorrect RSA size %X\n", file->size);
864                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
865                }
866        }
867        else if (file->type == SC_FILE_TYPE_INTERNAL_EF &&
868                        file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_DES)   {
869                if (file->size == 8 || file->size == 64)
870                        size = 64;
871                else if (file->size == 16 || file->size == 128)
872                        size = 128;
873                else if (file->size == 24 || file->size == 192)
874                        size = 192;
875                else   {
876                        sc_error(card->ctx, "incorrect DES size %X\n", file->size);
877                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
878                }
879        }
880
881        p[12] = (size >> 8) & 0xFF;
882        p[13] = size & 0xFF;
883       
884        p[14] = 0x86;
885        p[15] = 0x08;
886       
887        if (file->type == SC_FILE_TYPE_DF) {
888                ops[0] = SC_AC_OP_CREATE;
889                ops[1] = SC_AC_OP_CRYPTO;
890                ops[2] = SC_AC_OP_LIST_FILES;
891                ops[3] = SC_AC_OP_DELETE;
892#ifndef NOT_YET         
893                ops[4] = SC_AC_OP_PIN_SET;  /* SC_AC_OP_SET_REFERENCE */
894                ops[5] = SC_AC_OP_PIN_CHANGE;  /* SC_AC_OP_CHANGE_REFERENCE */
895                ops[6] = SC_AC_OP_PIN_RESET;  /* SC_AC_OP_RESET_COUNTER */
896#else
897                ops[4] = SC_AC_OP_LIST_FILES;  /* SC_AC_OP_SET_REFERENCE */
898                ops[5] = SC_AC_OP_LIST_FILES;  /* SC_AC_OP_CHANGE_REFERENCE */
899                ops[6] = SC_AC_OP_LIST_FILES;  /* SC_AC_OP_RESET_COUNTER */                                             
900#endif
901        }
902        else if (file->type == SC_FILE_TYPE_WORKING_EF)   {
903                if (file->ef_structure == SC_FILE_EF_TRANSPARENT)   {
904                        sc_debug(card->ctx, "SC_FILE_EF_TRANSPARENT\n");
905                        ops[0] = SC_AC_OP_WRITE;
906                        ops[1] = SC_AC_OP_UPDATE;
907                        ops[2] = SC_AC_OP_READ;
908                        ops[3] = SC_AC_OP_ERASE;
909                }
910                else if (file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE)  {
911                        sc_debug(card->ctx, "SC_FILE_EF_LINEAR_VARIABLE\n");
912                        ops[0] = SC_AC_OP_WRITE;
913                        ops[1] = SC_AC_OP_UPDATE;
914                        ops[2] = SC_AC_OP_READ;
915                        ops[3] = SC_AC_OP_ERASE;
916                }
917        }
918        else   if (file->type == SC_FILE_TYPE_INTERNAL_EF)   {
919                if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_DES)  {
920                        sc_debug(card->ctx, "EF_DES\n");
921                        ops[0] = SC_AC_OP_UPDATE;
922                        ops[1] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_DECRYPT */
923                        ops[2] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_ENCRYPT */
924                        ops[3] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_CHECKSUM */
925                        ops[4] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_CHECKSUM */
926                }
927                else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC)  {
928                        sc_debug(card->ctx, "EF_RSA_PUBLIC\n");
929                        ops[0] = SC_AC_OP_UPDATE;
930                        ops[2] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_ENCRYPT */
931                        ops[4] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_SIGN */
932                }
933                else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT)  {
934                        sc_debug(card->ctx, "EF_RSA_PRIVATE\n");
935                        ops[0] = SC_AC_OP_UPDATE;
936                        ops[1] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_ENCRYPT */
937                        ops[3] = SC_AC_OP_CRYPTO;  /* SC_AC_OP_SIGN */
938                }
939        }
940       
941