Changeset 3309

Show
Ignore:
Timestamp:
12/28/07 19:18:57 (11 months ago)
Author:
pk
Message:

support for TCOS3

Location:
trunk/src
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/libopensc/card-tcos.c

    r3085 r3309  
    11/* 
    2  * card-tcos.c: Support for TCOS 2.0 cards 
     2 * card-tcos.c: Support for TCOS cards 
    33 * 
     4 * Copyright (C) 2007  Peter Koch <Koch@smartcard-auth.de> 
     5 * Copyright (C) 2002  g10 Code GmbH 
    46 * Copyright (C) 2001  Juha YrjölÀ <juha.yrjola@iki.fi> 
    5  * Copyright (C) 2002  g10 Code GmbH 
    67 * 
    78 * This library is free software; you can redistribute it and/or 
     
    2930 
    3031static struct sc_atr_table tcos_atrs[] = { 
    31         /* SLE44 */ 
    32         { "3B:BA:13:00:81:31:86:5D:00:64:05:0A:02:01:31:80:90:00:8B", NULL, NULL, SC_CARD_TYPE_TCOS_GENERIC, 0, NULL }, 
    33         /* SLE66S */ 
    34         { "3B:BA:14:00:81:31:86:5D:00:64:05:14:02:02:31:80:90:00:91", NULL, NULL, SC_CARD_TYPE_TCOS_GENERIC, 0, NULL }, 
    35         /* SLE66CX320P */ 
    36         { "3B:BA:96:00:81:31:86:5D:00:64:05:60:02:03:31:80:90:00:66", NULL, NULL, SC_CARD_TYPE_TCOS_GENERIC, 0, NULL }, 
    37         /* SLE66CX322P */ 
    38         { "3B:BA:96:00:81:31:86:5D:00:64:05:7B:02:03:31:80:90:00:7D", NULL, NULL, SC_CARD_TYPE_TCOS_GENERIC, 0, NULL }, 
     32        /* Infineon SLE44 */ 
     33        { "3B:BA:13:00:81:31:86:5D:00:64:05:0A:02:01:31:80:90:00:8B", NULL, NULL, SC_CARD_TYPE_TCOS_V2, 0, NULL }, 
     34        /* Infineon SLE66S */ 
     35        { "3B:BA:14:00:81:31:86:5D:00:64:05:14:02:02:31:80:90:00:91", NULL, NULL, SC_CARD_TYPE_TCOS_V2, 0, NULL }, 
     36        /* Infineon SLE66CX320P */ 
     37        { "3B:BA:96:00:81:31:86:5D:00:64:05:60:02:03:31:80:90:00:66", NULL, NULL, SC_CARD_TYPE_TCOS_V2, 0, NULL }, 
     38        /* Infoneon SLE66CX322P */ 
     39        { "3B:BA:96:00:81:31:86:5D:00:64:05:7B:02:03:31:80:90:00:7D", NULL, NULL, SC_CARD_TYPE_TCOS_V2, 0, NULL }, 
     40        /* Philips P5CT072 */ 
     41        { "3B:BF:96:00:81:31:FE:5D:00:64:04:11:03:01:31:C0:73:F7:01:D0:00:90:00:7D", NULL, NULL, SC_CARD_TYPE_TCOS_V3, 0, NULL }, 
    3942        { NULL, NULL, NULL, 0, 0, NULL } 
    4043}; 
     
    4245static struct sc_card_operations tcos_ops; 
    4346static struct sc_card_driver tcos_drv = { 
    44         "TCOS 2.0", 
     47        "TCOS 3.0", 
    4548        "tcos", 
    4649        &tcos_ops, 
     
    5255typedef struct tcos_data_st { 
    5356        unsigned int pad_flags; 
    54         unsigned int sign_with_def_env; 
     57        unsigned int next_sign; 
    5558} tcos_data; 
     59 
    5660 
    5761static int tcos_finish(sc_card_t *card) 
     
    6064        return 0; 
    6165} 
     66 
    6267 
    6368static int tcos_match_card(sc_card_t *card) 
     
    7176} 
    7277 
     78 
    7379static int tcos_init(sc_card_t *card) 
    7480{ 
     
    7682 
    7783        tcos_data *data = (tcos_data *) malloc(sizeof(tcos_data)); 
    78         if (!data) 
    79                 return SC_ERROR_OUT_OF_MEMORY; 
     84        if (!data) return SC_ERROR_OUT_OF_MEMORY; 
    8085 
    8186        card->name = "TCOS"; 
     
    9095        _sc_card_add_rsa_alg(card, 768, flags, 0); 
    9196        _sc_card_add_rsa_alg(card, 1024, flags, 0); 
     97 
     98        if (card->type == SC_CARD_TYPE_TCOS_V3) { 
     99                card->caps |= SC_CARD_CAP_RSA_2048|SC_CARD_CAP_APDU_EXT; 
     100                _sc_card_add_rsa_alg(card, 1280, flags, 0); 
     101                _sc_card_add_rsa_alg(card, 1536, flags, 0); 
     102                _sc_card_add_rsa_alg(card, 1792, flags, 0); 
     103                _sc_card_add_rsa_alg(card, 2048, flags, 0); 
     104        } 
    92105 
    93106        return 0; 
     
    217230 
    218231 
    219  
    220232static unsigned int map_operations (int commandbyte ) 
    221233{ 
    222   unsigned int op = (unsigned int)-1; 
    223  
    224   switch ( (commandbyte & 0xfe) ) 
    225     { 
    226     case 0xe2: /* append record */   op = SC_AC_OP_UPDATE; break; 
    227     case 0x24: /* change password */ op = SC_AC_OP_UPDATE; break; 
    228     case 0xe0: /* create */          op = SC_AC_OP_CREATE; break; 
    229     case 0xe4: /* delete */          op = SC_AC_OP_DELETE; break; 
    230     case 0xe8: /* exclude sfi */     op = SC_AC_OP_WRITE; break; 
    231     case 0x82: /* external auth */   op = SC_AC_OP_READ; break; 
    232     case 0xe6: /* include sfi */     op = SC_AC_OP_WRITE; break; 
    233     case 0x88: /* internal auth */   op = SC_AC_OP_READ; break; 
    234     case 0x04: /* invalidate */      op = SC_AC_OP_INVALIDATE; break; 
    235     case 0x2a: /* perform sec. op */ op = SC_AC_OP_SELECT; break; 
    236     case 0xb0: /* read binary */     op = SC_AC_OP_READ; break; 
    237     case 0xb2: /* read record */     op = SC_AC_OP_READ; break; 
    238     case 0x44: /* rehabilitate */    op = SC_AC_OP_REHABILITATE; break; 
    239     case 0xa4: /* select */          op = SC_AC_OP_SELECT; break; 
    240     case 0xee: /* set permanent */   op = SC_AC_OP_CREATE; break; 
    241     case 0x2c: /* unblock password */op = SC_AC_OP_WRITE; break; 
    242     case 0xd6: /* update binary */   op = SC_AC_OP_WRITE; break; 
    243     case 0xdc: /* update record */   op = SC_AC_OP_WRITE; break; 
    244     case 0x20: /* verify password */ op = SC_AC_OP_SELECT; break; 
    245     case 0x60: /* admin group */     op = SC_AC_OP_CREATE; break; 
    246     } 
    247   return op; 
    248 } 
    249  
    250  
     234        unsigned int op = (unsigned int)-1; 
     235 
     236        switch ( (commandbyte & 0xfe) ) { 
     237                case 0xe2: /* append record */   op = SC_AC_OP_UPDATE; break; 
     238                case 0x24: /* change password */ op = SC_AC_OP_UPDATE; break; 
     239                case 0xe0: /* create */          op = SC_AC_OP_CREATE; break; 
     240                case 0xe4: /* delete */          op = SC_AC_OP_DELETE; break; 
     241                case 0xe8: /* exclude sfi */     op = SC_AC_OP_WRITE; break; 
     242                case 0x82: /* external auth */   op = SC_AC_OP_READ; break; 
     243                case 0xe6: /* include sfi */     op = SC_AC_OP_WRITE; break; 
     244                case 0x88: /* internal auth */   op = SC_AC_OP_READ; break; 
     245                case 0x04: /* invalidate */      op = SC_AC_OP_INVALIDATE; break; 
     246                case 0x2a: /* perform sec. op */ op = SC_AC_OP_SELECT; break; 
     247                case 0xb0: /* read binary */     op = SC_AC_OP_READ; break; 
     248                case 0xb2: /* read record */     op = SC_AC_OP_READ; break; 
     249                case 0x44: /* rehabilitate */    op = SC_AC_OP_REHABILITATE; break; 
     250                case 0xa4: /* select */          op = SC_AC_OP_SELECT; break; 
     251                case 0xee: /* set permanent */   op = SC_AC_OP_CREATE; break; 
     252                case 0x2c: /* unblock password */op = SC_AC_OP_WRITE; break; 
     253                case 0xd6: /* update binary */   op = SC_AC_OP_WRITE; break; 
     254                case 0xdc: /* update record */   op = SC_AC_OP_WRITE; break; 
     255                case 0x20: /* verify password */ op = SC_AC_OP_SELECT; break; 
     256                case 0x60: /* admin group */     op = SC_AC_OP_CREATE; break; 
     257        } 
     258        return op; 
     259} 
    251260 
    252261 
     
    320329} 
    321330 
    322 /* Arghh. duplicated from iso7816.c */ 
    323 static void tcos_process_fci(sc_context_t *ctx, sc_file_t *file, 
    324                              const u8 *buf, size_t buflen) 
    325 { 
    326         size_t taglen, len = buflen; 
    327         const u8 *tag = NULL, *p = buf; 
    328  
    329         if (ctx->debug >= 3) 
    330                 sc_debug(ctx, "processing FCI bytes\n"); 
    331         tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); 
    332         if (tag != NULL && taglen == 2) { 
    333                 file->id = (tag[0] << 8) | tag[1]; 
    334                 if (ctx->debug >= 3) 
    335                         sc_debug(ctx, "  file identifier: 0x%02X%02X\n", tag[0], 
    336                                tag[1]); 
    337         } 
    338         tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen); 
    339         if (tag != NULL && taglen >= 2) { 
    340                 int bytes = (tag[0] << 8) + tag[1]; 
    341                 if (ctx->debug >= 3) 
    342                         sc_debug(ctx, "  bytes in file: %d\n", bytes); 
    343                 file->size = bytes; 
    344         } 
    345         if (tag == NULL) { 
    346                 tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen); 
    347                 if (tag != NULL && taglen >= 2) { 
    348                         int bytes = (tag[0] << 8) + tag[1]; 
    349                         if (ctx->debug >= 3) 
    350                                 sc_debug(ctx, "  bytes in file: %d\n", bytes); 
    351                         file->size = bytes; 
    352                 } 
    353         } 
    354         tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); 
    355         if (tag != NULL) { 
    356                 if (taglen > 0) { 
    357                         unsigned char byte = tag[0]; 
    358                         const char *type; 
    359  
    360                         file->shareable = byte & 0x40 ? 1 : 0; 
    361                         if (ctx->debug >= 3) 
    362                                 sc_debug(ctx, "  shareable: %s\n", 
    363                                        (byte & 0x40) ? "yes" : "no"); 
    364                         file->ef_structure = byte & 0x07; 
    365                         switch ((byte >> 3) & 7) { 
    366                         case 0: 
    367                                 type = "working EF"; 
    368                                 file->type = SC_FILE_TYPE_WORKING_EF; 
    369                                 break; 
    370                         case 1: 
    371                                 type = "internal EF"; 
    372                                 file->type = SC_FILE_TYPE_INTERNAL_EF; 
    373                                 break; 
    374                         case 7: 
    375                                 type = "DF"; 
    376                                 file->type = SC_FILE_TYPE_DF; 
    377                                 break; 
    378                         default: 
    379                                 type = "unknown"; 
    380                                 break; 
    381                         } 
    382                         if (ctx->debug >= 3) { 
    383                                 sc_debug(ctx, "  type: %s\n", type); 
    384                                 sc_debug(ctx, "  EF structure: %d\n", 
    385                                        byte & 0x07); 
    386                         } 
    387                 } 
    388         } 
    389         tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen); 
    390         if (tag != NULL && taglen > 0 && taglen <= 16) { 
    391                 char name[17]; 
    392                 size_t i; 
    393  
    394                 memcpy(file->name, tag, taglen); 
    395                 file->namelen = taglen; 
    396  
    397                 for (i = 0; i < taglen; i++) { 
    398                         if (isalnum(tag[i]) || ispunct(tag[i]) 
    399                             || isspace(tag[i])) 
    400                                 name[i] = tag[i]; 
    401                         else 
    402                                 name[i] = '?'; 
    403                 } 
    404                 name[taglen] = 0; 
    405                 if (ctx->debug >= 3) 
    406                         sc_debug(ctx, "File name: %s\n", name); 
    407         } 
    408         tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen); 
    409         if (tag != NULL && taglen) { 
    410                 sc_file_set_prop_attr(file, tag, taglen);  
    411         } else 
    412                 file->prop_attr_len = 0; 
    413         tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen); 
    414         if (tag != NULL && taglen) { 
    415                 sc_file_set_prop_attr(file, tag, taglen);  
    416         } 
    417         tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen); 
    418         if (tag != NULL && taglen) { 
    419                 sc_file_set_sec_attr(file, tag, taglen);  
    420         } 
    421         file->magic = SC_FILE_MAGIC; 
    422 } 
    423  
    424  
    425 /* This is a special version of the standard select_file which is 
    426    needed to cope with some starngeness in APDU construction.  It is 
    427    probably better to have this specfic for TCOS, so that support for 
    428    other cards does not break. */ 
    429 static int hacked_iso7816_select_file(sc_card_t *card, 
    430                                       const sc_path_t *in_path, 
    431                                       sc_file_t **file_out) 
     331 
     332static int tcos_select_file(sc_card_t *card, 
     333                            const sc_path_t *in_path, 
     334                            sc_file_t **file_out) 
    432335{ 
    433336        sc_context_t *ctx; 
    434337        sc_apdu_t apdu; 
    435         u8 buf[SC_MAX_APDU_BUFFER_SIZE]; 
    436         u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; 
    437         int r, pathlen; 
    438         sc_file_t *file = NULL; 
     338        sc_file_t *file=NULL; 
     339        u8 buf[SC_MAX_APDU_BUFFER_SIZE], pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; 
     340        int i, r, pathlen; 
    439341 
    440342        assert(card != NULL && in_path != NULL); 
    441         ctx = card->ctx; 
     343        ctx=card->ctx; 
    442344        memcpy(path, in_path->value, in_path->len); 
    443345        pathlen = in_path->len; 
    444346 
    445         sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); 
     347        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0x04); 
    446348         
    447349        switch (in_path->type) { 
    448350        case SC_PATH_TYPE_FILE_ID: 
    449                 apdu.p1 = 0; 
    450                 if (pathlen != 2) 
    451                         return SC_ERROR_INVALID_ARGUMENTS; 
     351                if (pathlen != 2) return SC_ERROR_INVALID_ARGUMENTS; 
     352        case SC_PATH_TYPE_FROM_CURRENT: 
     353                apdu.p1 = 9; 
    452354                break; 
    453355        case SC_PATH_TYPE_DF_NAME: 
     
    456358        case SC_PATH_TYPE_PATH: 
    457359                apdu.p1 = 8; 
    458                 if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) { 
    459                         if (pathlen == 2) {     /* only 3F00 supplied */ 
    460                                 apdu.p1 = 0; 
    461                                 break; 
    462                         } 
    463                         path += 2; 
    464                         pathlen -= 2; 
    465                 } 
     360                if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) path += 2, pathlen -= 2; 
     361                if (pathlen == 0) apdu.p1 = 0; 
     362                break; 
     363        case SC_PATH_TYPE_PARENT: 
     364                apdu.p1 = 3; 
     365                pathlen = 0; 
    466366                break; 
    467367        default: 
    468                 SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); 
    469         } 
    470         apdu.p2 = 0;            /* first record, return FCI */ 
     368                SC_FUNC_RETURN(ctx, 2, SC_ERROR_INVALID_ARGUMENTS); 
     369        } 
     370        if( pathlen == 0 ) apdu.cse = SC_APDU_CASE_2_SHORT; 
     371 
    471372        apdu.lc = pathlen; 
    472373        apdu.data = path; 
     
    476377                apdu.resp = buf; 
    477378                apdu.resplen = sizeof(buf); 
    478                 apdu.le = 255; /* 256 will be represented as 0 which 
    479                                   conflicts with the apdu sanity check */ 
     379                apdu.le = 256; 
    480380        } else { 
    481                 apdu.resp = buf; 
    482                 apdu.resplen = sizeof(buf); 
    483                 apdu.le = 255;  
    484                 /* does not work apdu.cse = SC_APDU_CASE_3_SHORT;*/ 
    485         } 
    486         if (!apdu.lc) /* never send an empty lc */ 
    487           apdu.cse = SC_APDU_CASE_2_SHORT; 
     381                apdu.resplen = 0; 
     382                apdu.le = 0;  
     383                apdu.p2 = 0x0C;  
     384                apdu.cse = (pathlen == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT; 
     385        } 
    488386 
    489387        r = sc_transmit_apdu(card, &apdu); 
    490         SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 
    491         if (file_out == NULL) { 
    492                 if (apdu.sw1 == 0x61) 
    493                         SC_FUNC_RETURN(card->ctx, 2, 0); 
    494                 SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2)); 
    495         } 
    496  
     388        SC_TEST_RET(ctx, r, "APDU transmit failed"); 
    497389        r = sc_check_sw(card, apdu.sw1, apdu.sw2); 
    498         if (r) 
    499                 SC_FUNC_RETURN(card->ctx, 2, r); 
    500  
    501         switch (apdu.resp[0]) { 
    502         case 0x6F: 
    503                 file = sc_file_new(); 
    504                 if (file == NULL) 
    505                         SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY); 
    506                 file->path = *in_path; 
    507                 if (apdu.resp[1] <= apdu.resplen) 
    508                         tcos_process_fci(card->ctx, file, 
    509                                          apdu.resp+2, apdu.resp[1]); 
    510                 *file_out = file; 
    511                 break; 
    512         case 0x00:      /* proprietary coding */ 
    513                 SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); 
    514         default: 
    515                 SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); 
    516         } 
     390        if (r || file_out == NULL) SC_FUNC_RETURN(ctx, 2, r); 
     391 
     392        if (apdu.resplen < 1 || apdu.resp[0] != 0x62){ 
     393                sc_debug(ctx, "received invalid template %02X\n", apdu.resp[0]); 
     394                SC_FUNC_RETURN(ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); 
     395        } 
     396 
     397        file = sc_file_new(); 
     398        if (file == NULL) SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); 
     399        file->path = *in_path; 
     400 
     401        for(i=2; i+1<apdu.resplen && i+1+apdu.resp[i+1]<apdu.resplen; i+=2+apdu.resp[i+1]){ 
     402                int j, len=apdu.resp[i+1]; 
     403                unsigned char type=apdu.resp[i], *d=apdu.resp+i+2; 
     404 
     405                switch (type) { 
     406                case 0x80: 
     407                case 0x81: 
     408                        file->size=0; 
     409                        for(j=0; j<len; ++j) file->size = (file->size<<8) | d[j]; 
     410                        break; 
     411                case 0x82: 
     412                        file->shareable = (d[0] & 0x40) ? 1 : 0; 
     413                        file->ef_structure = d[0] & 7; 
     414                        switch ((d[0]>>3) & 7) { 
     415                        case 0: file->type = SC_FILE_TYPE_WORKING_EF; break; 
     416                        case 7: file->type = SC_FILE_TYPE_DF; break; 
     417                        default: 
     418                                sc_debug(ctx, "invalid file type %02X in file descriptor\n", d[0]); 
     419                                SC_FUNC_RETURN(ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); 
     420                        } 
     421                        break; 
     422                case 0x83: 
     423                        file->id = (d[0]<<8) | d[1]; 
     424                        break; 
     425                case 0x84: 
     426                        memcpy(file->name, d, len); 
     427                        file->namelen = len; 
     428                        break; 
     429                case 0x86: 
     430                        sc_file_set_sec_attr(file, d, len);  
     431                        break; 
     432                default: 
     433                        if (len>0) sc_file_set_prop_attr(file, d, len);  
     434                } 
     435        } 
     436        file->magic = SC_FILE_MAGIC; 
     437        *file_out = file; 
     438 
     439        parse_sec_attr(card, file, file->sec_attr, file->sec_attr_len); 
     440 
    517441        return 0; 
    518442} 
    519443 
    520444 
    521  
    522 static int tcos_select_file(sc_card_t *card, 
    523                             const sc_path_t *in_path, 
    524                             sc_file_t **file) 
    525 { 
    526         int r; 
    527          
    528         /*r = iso_ops->select_file(card, in_path, file);*/ 
    529         r = hacked_iso7816_select_file(card, in_path, file); 
    530         if (r) 
    531                 return r; 
    532  
    533         if (file) { 
    534                 parse_sec_attr(card, (*file), (*file)->sec_attr, 
    535                                (*file)->sec_attr_len); 
    536         } 
    537  
    538         return 0; 
    539 } 
    540  
    541445static int tcos_list_files(sc_card_t *card, u8 *buf, size_t buflen) 
    542446{ 
     447        sc_context_t *ctx; 
    543448        sc_apdu_t apdu; 
    544         u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; 
    545         u8 p1s[2] = { 0x01, 0x02 }; 
    546         int r, i, count = 0; 
    547  
    548         for (i = 0; i < 2; i++) { 
    549                 sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, p1s[i], 0); 
     449        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], p1; 
     450        int r, count = 0; 
     451 
     452        assert(card != NULL); 
     453        ctx = card->ctx; 
     454 
     455        for (p1=1; p1<=2; p1++) { 
     456                sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, p1, 0); 
    550457                apdu.cla = 0x80; 
    551458                apdu.resp = rbuf; 
     
    553460                apdu.le = 256; 
    554461                r = sc_transmit_apdu(card, &apdu); 
    555                 SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 
     462                SC_TEST_RET(ctx, r, "APDU transmit failed"); 
     463                if (apdu.sw1==0x6A && (apdu.sw2==0x82 || apdu.sw2==0x88)) continue; 
    556464                r = sc_check_sw(card, apdu.sw1, apdu.sw2); 
    557                 if (r == SC_ERROR_FILE_NOT_FOUND) 
    558                         continue; 
    559                 SC_TEST_RET(card->ctx, r, "Card returned error"); 
    560                 if (apdu.resplen > buflen) 
    561                         return SC_ERROR_BUFFER_TOO_SMALL; 
     465                SC_TEST_RET(ctx, r, "List Dir failed"); 
     466                if (apdu.resplen > buflen) return SC_ERROR_BUFFER_TOO_SMALL; 
     467                if(ctx->debug >= 3) sc_debug(ctx, "got %d %s-FileIDs\n", apdu.resplen/2, p1==1 ? "DF" : "EF"); 
     468 
    562469                memcpy(buf, apdu.resp, apdu.resplen); 
    563470                buf += apdu.resplen; 
     
    567474        return count; 
    568475} 
    569  
    570476 
    571477 
     
    594500} 
    595501 
    596 /* Crypto operations */ 
    597  
    598  
    599 /* TCOS has two kind of RSA-keys: signature-keys and encryption-keys 
    600    signature-keys: can be used for sign-operations only and can be used 
    601      only within the default security environment. hence must be 
    602      stored as local key 0, a SetSecEnv-cmd must not be used (if you 
    603      do - even with default parameters - it will fail with 6A88) 
    604    encryption-keys: can be used for both sign- and decipher-operations, 
    605      can be used within any security environment, a SetSecEnv-cmd 
    606      must be used (even if you want to use the default security environment 
    607      you must a SetSecEnv-cmd with default parameters) 
    608    Unfortunately we cannot find out wether the referenced key is a 
    609    signature-key or encryption-key when this routine is called. Therefore 
    610    we have a problem if the key-reference is 0x80. If the referenced key 
    611    was a signature-key a SetSecEnv must not be used, if the key was an 
    612    encryption-key it must be used. 
    613    Therefore we suppress error-messages in this case, try a SetSecEnv-cmd 
    614    with default parameters and watch out for 6A88-responses [pk_opensc@web.de] 
    615 */ 
    616 static int tcos_set_security_env(sc_card_t *card, 
    617                                  const sc_security_env_t *env, 
    618                                  int se_num) 
     502 
     503static int tcos_set_security_env(sc_card_t *card, const sc_security_env_t *env, int se_num) 
    619504{ 
    620505        sc_context_t *ctx; 
    621506        sc_apdu_t apdu; 
    622507        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE], *p; 
    623         int r, sign_with_def_env=0; 
     508        int r, default_key, tcos3; 
     509        tcos_data *data; 
    624510 
    625511        assert(card != NULL && env != NULL); 
    626512        ctx = card->ctx; 
    627  
    628         if (se_num) SC_FUNC_RETURN(ctx, 1, SC_ERROR_INVALID_ARGUMENTS); 
    629  
    630         if(ctx->debug >= 3) sc_debug(ctx, "Security Environment Ref=%d:%02X\n", env->key_ref_len, *env->key_ref); 
    631         if(env->operation == SC_SEC_OPERATION_SIGN && 
    632            (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || (env->key_ref_len==1 && *env->key_ref==0x80)) 
    633         ){ 
    634                 if (ctx->debug >= 3) sc_debug(ctx, "Sign-Operation with Default Security Environment\n"); 
    635                 sign_with_def_env=1; 
    636         } 
    637  
    638         sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); 
    639         switch (env->operation) { 
    640         case SC_SEC_OPERATION_DECIPHER: 
    641         case SC_SEC_OPERATION_SIGN: 
    642                 apdu.p1 = 0xC1; 
    643                 apdu.p2 = 0xB8; 
    644                 /* save padding flags and default secEnv indictor */ 
    645                 ((tcos_data *)card->drv_data)->pad_flags = env->algorithm_flags; 
    646                 ((tcos_data *)card->drv_data)->sign_with_def_env = sign_with_def_env; 
    647                 break; 
    648         default: 
    649                 return SC_ERROR_INVALID_ARGUMENTS; 
    650         } 
    651  
    652         apdu.le = 0; 
     513        tcos3=(card->type==SC_CARD_TYPE_TCOS_V3); 
     514        data=(tcos_data *)card->drv_data; 
     515 
     516        if (se_num || (env->operation!=SC_SEC_OPERATION_DECIPHER && env->operation!=SC_SEC_OPERATION_SIGN)){ 
     517                SC_FUNC_RETURN(ctx, 1, SC_ERROR_INVALID_ARGUMENTS); 
     518        } 
     519        if(ctx->debug >= 3){ 
     520                if(!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)) sc_debug(ctx, "No Key-Reference in SecEnvironment\n"); 
     521                else sc_debug(ctx, "Key-Reference %02X (len=%d)\n", env->key_ref[0], env->key_ref_len); 
     522        } 
     523        // Key-Reference 0x80 ?? 
     524        default_key= !(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || (env->key_ref_len==1 && env->key_ref[0]==0x80); 
     525        if(ctx->debug>=3){ 
     526                sc_debug(ctx, "TCOS3:%d PKCS1:%d\n", tcos3, !!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)); 
     527        } 
     528 
     529        data->pad_flags = env->algorithm_flags; 
     530        data->next_sign = default_key; 
     531 
     532        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, tcos3 ? 0x41 : 0xC1, 0xB8); 
    653533        p = sbuf; 
    654         if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) { 
    655                 *p++ = 0x80;    /* algorithm reference */ 
    656                 *p++ = 0x01; 
    657                 *p++ = env->algorithm_ref & 0xFF; 
    658         } 
     534        *p++=0x80; *p++=0x01; *p++=tcos3 ? 0x0A : 0x10; 
    659535        if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { 
    660536                *p++ = (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) ? 0x83 : 0x84; 
     
    663539                p += env->key_ref_len; 
    664540        } 
    665         r = p - sbuf; 
    666         apdu.lc = r; 
    667         apdu.datalen = r; 
    668541        apdu.data = sbuf; 
    669         apdu.resplen = 0; 
    670  
    671         if (apdu.datalen != 0) { 
    672                 r = sc_transmit_apdu(card, &apdu); 
    673                 if (r) { 
    674                         sc_perror(ctx, r, "APDU transmit failed"); 
    675                         return r; 
    676                 } 
    677                 if (sign_with_def_env && apdu.sw1==0x6A && apdu.sw2==0x88) return 0; 
    678                 ((tcos_data *)card->drv_data)->sign_with_def_env = sign_with_def_env = 0; 
    679  
    680                 r = sc_check_sw(card, apdu.sw1, apdu.sw2); 
    681                 if (r) { 
    682                         sc_perror(ctx, r, "Card returned error"); 
    683                         return r; 
    684                 } 
    685         } 
     542        apdu.lc = apdu.datalen = (p - sbuf); 
     543 
     544        if ((r=sc_transmit_apdu(card, &apdu))) { 
     545                sc_perror(ctx, r, "APDU transmit failed"); 
     546                return r;