Show
Ignore:
Timestamp:
04/18/08 14:08:23 (9 months ago)
Author:
alonbl
Message:

ruToken fixups

http://www.opensc-project.org/pipermail/opensc-devel/2008-April/011057.html

By Aktiv Co. Aleksey Samsonov

Files:
1 modified

Legend:

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

    r3463 r3478  
    11/* 
    2  *  card-rutoken.c: Support for ruToken cards 
     2 *  card-rutoken.c: Support for Rutoken cards 
    33 * 
    44 * Copyright (C) 2007  Pavel Mironchik <rutoken@rutoken.ru> 
    … …  
    1919 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    2020*/ 
    21 #include "internal.h" 
    22 #include "cardctl.h" 
    23 #include <sys/types.h> 
    24 #include <ctype.h> 
    25 #include <string.h> 
    26 #include <stdlib.h> 
    27 #include "pkcs15.h" 
     21 
     22#ifdef HAVE_CONFIG_H 
     23#include <config.h> 
     24#endif 
    2825#if defined(HAVE_INTTYPES_H) 
    2926#include <inttypes.h> 
    … …  
    3633#warning no uint32_t type available, please contact opensc-devel@opensc-project.org 
    3734#endif 
    38  
    39 #define BIG_ENDIAN_RUTOKEN 
     35#include <sys/types.h> 
     36#include <ctype.h> 
     37#include <string.h> 
     38#include <stdlib.h> 
     39#include "opensc.h" 
     40#include "pkcs15.h" 
     41#include "internal.h" 
     42#include "cardctl.h" 
    4043 
    4144#ifdef ENABLE_OPENSSL 
    … …  
    4649#include <openssl/x509.h> 
    4750#include <openssl/err.h> 
    48 #include "rutoken.h" 
    4951#endif 
    5052 
    51 #define FDESCR_DF           0x38    /*00111000b*/ 
     53#define FDESCR_DF           0x38 /*00111000b*/ 
    5254#define FDESCR_EF           0x01 
    53  
    54 #define ID_RESERVED_CURDF   0x3FFF      /*Reserved ID for current DF*/ 
    55  
    56 #ifdef BIG_ENDIAN_RUTOKEN 
    57 #define MF_PATH             "\x3F\x00" 
    58 #else 
    59 #define MF_PATH             "\x00\x3F" 
    60 #endif 
     55#define ID_RESERVED_CURDF   0x3FFF /*Reserved ID for current DF*/ 
    6156 
    6257struct auth_senv { 
    … …  
    7166}; 
    7267 
    73 static const struct sc_card_operations *iso_ops = NULL; 
    74  
    7568static struct sc_card_operations rutoken_ops; 
    7669 
    7770static struct sc_card_driver rutoken_drv = { 
    78         "ruToken driver", 
     71        "Rutoken driver", 
    7972        "rutoken", 
    8073        &rutoken_ops, 
    … …  
    8780}; 
    8881 
    89 const char *hexdump(const void *data, size_t len) 
     82static const char *hexdump(const void *data, size_t len) 
    9083{ 
    9184        static char string[1024]; 
    … …  
    107100        SC_FUNC_CALLED(card->ctx, 1); 
    108101        free(card->drv_data); 
    109         return 0; 
     102        SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); 
    110103} 
    111104 
    112105static int rutoken_match_card(sc_card_t *card) 
    113106{ 
    114         int i; 
    115  
    116         SC_FUNC_CALLED(card->ctx, 1); 
    117  
    118         i = _sc_match_atr(card, rutoken_atrs, &card->type); 
    119         if (i < 0) 
    120                 return 0; 
    121  
    122         sc_debug(card->ctx, "atr recognized as ruToken\n"); 
    123         return 1; 
    124 } 
    125  
    126 static int rutoken_init(sc_card_t *card) 
    127 { 
    128         int ret = SC_ERROR_MEMORY_FAILURE; 
    129         unsigned int flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; 
    130                                 /* SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_SHA1 
    131                                 | SC_ALGORITHM_RSA_HASH_MD5_SHA1 
    132                                 | SC_ALGORITHM_RSA_PAD_NONE */ 
     107        SC_FUNC_CALLED(card->ctx, 1); 
     108        if (_sc_match_atr(card, rutoken_atrs, &card->type) >= 0) 
     109        { 
     110                sc_debug(card->ctx, "ATR recognized as Rutoken\n"); 
     111                SC_FUNC_RETURN(card->ctx, 1, 1); 
     112        } 
     113        SC_FUNC_RETURN(card->ctx, 1, 0); 
     114} 
     115 
     116static int token_init(sc_card_t *card, const char *card_name) 
     117{ 
     118        unsigned int flags; 
    133119        sc_algorithm_info_t info; 
    134120 
    135         SC_FUNC_CALLED(card->ctx, 1); 
    136  
    137         card->name = "rutoken card"; 
    138         card->drv_data = malloc(sizeof(auth_senv_t)); 
     121        SC_FUNC_CALLED(card->ctx, 3); 
     122 
     123        card->name = card_name; 
    139124        card->caps |= SC_CARD_CAP_RSA_2048 | SC_CARD_CAP_NO_FCI | SC_CARD_CAP_RNG; 
    140         if (card->drv_data) 
    141         { 
    142                 memset(card->drv_data, 0, sizeof(auth_senv_t)); 
    143                 ret = SC_NO_ERROR; 
    144         } 
    145         /* add algorithm  
    146         TODO: may nid som other flag  */ 
    147  
     125        card->drv_data = calloc(1, sizeof(auth_senv_t)); 
     126        if (card->drv_data == NULL) 
     127                SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_OUT_OF_MEMORY); 
     128 
     129        flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; 
    148130        _sc_card_add_rsa_alg(card, 256, flags, 0); 
    149131        _sc_card_add_rsa_alg(card, 512, flags, 0); 
    … …  
    151133        _sc_card_add_rsa_alg(card, 1024, flags, 0); 
    152134        _sc_card_add_rsa_alg(card, 2048, flags, 0); 
    153         flags = SC_ALGORITHM_GOST_CRYPT_PZ | SC_ALGORITHM_GOST_CRYPT_GAMM 
    154                 | SC_ALGORITHM_GOST_CRYPT_GAMMOS; 
     135 
    155136        memset(&info, 0, sizeof(info)); 
    156137        info.algorithm = SC_ALGORITHM_GOST; 
    157         info.flags = flags; 
     138        info.flags = SC_ALGORITHM_GOST_CRYPT_PZ | SC_ALGORITHM_GOST_CRYPT_GAMM 
     139                | SC_ALGORITHM_GOST_CRYPT_GAMMOS; 
    158140        info.key_length = 32; 
    159         if (_sc_card_add_algorithm(card, &info) < 0) 
    160             return -1; 
    161         return ret; 
     141        _sc_card_add_algorithm(card, &info); 
     142 
     143        SC_FUNC_RETURN(card->ctx, 3, SC_SUCCESS); 
     144} 
     145 
     146static int rutoken_init(sc_card_t *card) 
     147{ 
     148        int ret; 
     149 
     150        SC_FUNC_CALLED(card->ctx, 1); 
     151        ret = token_init(card, "Rutoken card"); 
     152        SC_FUNC_RETURN(card->ctx, 1, ret); 
    162153} 
    163154 
    164155static const struct sc_card_error rutoken_errors[] = { 
    165156 
    166         { 0x6300, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    167         { 0x63C1, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    168         { 0x63C2, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    169         { 0x63C3, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    170         { 0x63C4, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    171         { 0x63C5, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    172         { 0x63C6, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    173         { 0x63C7, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    174         { 0x63C8, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    175         { 0x63C9, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    176         { 0x63Ca, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    177         { 0x63Cb, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    178         { 0x63Cc, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    179         { 0x63Cd, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    180         { 0x63Ce, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    181         { 0x63Cf, SC_ERROR_PIN_CODE_INCORRECT,"authentication failed"},  
    182  
    183         { 0x6400, SC_ERROR_CARD_CMD_FAILED,"Aborting"},  
    184  
    185         { 0x6500, SC_ERROR_MEMORY_FAILURE,      "Memory failure"},  
    186         { 0x6581, SC_ERROR_MEMORY_FAILURE,      "Memory failure"},  
    187  
    188         { 0x6700, SC_ERROR_WRONG_LENGTH,        "Lc or Le invalid"},  
    189  
    190         { 0x6883, SC_ERROR_CARD_CMD_FAILED,     "The finishing command of a chain is expected"},  
    191  
    192         { 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"required access right not granted"},  
    193         { 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "bs object blocked"},  
    194         { 0x6985, SC_ERROR_CARD_CMD_FAILED,     "command not allowed (unsuitable conditions)"},  
    195         { 0x6986, SC_ERROR_INCORRECT_PARAMETERS,"no current ef selected"},  
    196  
    197         { 0x6a80, SC_ERROR_INCORRECT_PARAMETERS,"invalid parameters in data field"},  
    198         { 0x6a81, SC_ERROR_NOT_SUPPORTED,       "function/mode not supported"},  
    199         { 0x6a82, SC_ERROR_FILE_NOT_FOUND,      "file (DO) not found"},  
    200         { 0x6a84, SC_ERROR_CARD_CMD_FAILED,     "not enough memory"},  
    201         { 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"},  
    202         { 0x6a89, SC_ERROR_FILE_ALREADY_EXISTS,"file (DO) already exists"},  
    203  
    204         { 0x6b00, SC_ERROR_INCORRECT_PARAMETERS,"Out of file length"},  
    205  
    206         { 0x6c00, SC_ERROR_WRONG_LENGTH,        "le does not fit the data to be sent"},  
    207  
    208         { 0x6d00, SC_ERROR_INS_NOT_SUPPORTED,   "ins invalid (not supported)"},  
     157        { 0x6300, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     158        { 0x63C1, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed. One tries left"},  
     159        { 0x63C2, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed. Two tries left"},  
     160        { 0x63C3, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     161        { 0x63C4, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     162        { 0x63C5, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     163        { 0x63C6, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     164        { 0x63C7, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     165        { 0x63C8, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     166        { 0x63C9, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     167        { 0x63CA, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     168        { 0x63CB, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     169        { 0x63CC, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     170        { 0x63CD, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     171        { 0x63CE, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     172        { 0x63CF, SC_ERROR_PIN_CODE_INCORRECT,  "Authentication failed"},  
     173 
     174        { 0x6400, SC_ERROR_CARD_CMD_FAILED,     "Aborting"},  
     175 
     176        { 0x6500, SC_ERROR_MEMORY_FAILURE,      "Memory failure"},  
     177        { 0x6581, SC_ERROR_MEMORY_FAILURE,      "Memory failure"},  
     178 
     179        { 0x6700, SC_ERROR_WRONG_LENGTH,        "Lc or Le invalid"},  
     180 
     181        { 0x6883, SC_ERROR_CARD_CMD_FAILED,     "The finishing command of a chain is expected"},  
     182 
     183        { 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED, "Required access right not granted"},  
     184        { 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "DO blocked"},  
     185        { 0x6985, SC_ERROR_CARD_CMD_FAILED,     "Command not allowed (unsuitable conditions)"},  
     186        { 0x6986, SC_ERROR_INCORRECT_PARAMETERS,"No current EF selected"},  
     187 
     188        { 0x6A80, SC_ERROR_INCORRECT_PARAMETERS,"Invalid parameters in data field"},  
     189        { 0x6A81, SC_ERROR_NOT_SUPPORTED,       "Function/mode not supported"},  
     190        { 0x6A82, SC_ERROR_FILE_NOT_FOUND,      "File (DO) not found"},  
     191        { 0x6A84, SC_ERROR_CARD_CMD_FAILED,     "Not enough memory space in the token"},  
     192        { 0x6A86, SC_ERROR_INCORRECT_PARAMETERS,"P1 or P2 invalid"},  
     193        { 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "File (DO) already exists"},  
     194 
     195        { 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Out of maximum file length"},  
     196 
     197        { 0x6C00, SC_ERROR_WRONG_LENGTH,        "Le does not fit the data to be sent"},  
     198 
     199        { 0x6D00, SC_ERROR_INS_NOT_SUPPORTED,   "Ins invalid (not supported)"},  
    209200 
    210201        /* Own class of an error*/ 
    211         { 0x6f01, SC_ERROR_CARD_CMD_FAILED,     "ruToken has the exchange protocol which is not supported by the USB-driver (newer, than in the driver)"}, 
    212         { 0x6f83, SC_ERROR_CARD_CMD_FAILED,     "Infringement of the exchange protocol with ruToken is revealed"}, 
    213         { 0x6f84, SC_ERROR_CARD_CMD_FAILED,     "ruToken is busy by processing of other command"}, 
    214         { 0x6f85, SC_ERROR_CARD_CMD_FAILED,     "In the current folder the maximum quantity of file system objects is already created."}, 
    215         { 0x6f86, SC_ERROR_CARD_CMD_FAILED,     "The token works not with access rights 'Visitor'"}, 
    216  
    217         { 0x9000, SC_NO_ERROR,          NULL} 
     202        { 0x6F01, SC_ERROR_CARD_CMD_FAILED,     "Rutoken has the exchange protocol which is not supported by the USB-driver (newer, than in the driver)"},  
     203        { 0x6F83, SC_ERROR_CARD_CMD_FAILED,     "Infringement of the exchange protocol with Rutoken is revealed"},  
     204        { 0x6F84, SC_ERROR_CARD_CMD_FAILED,     "Rutoken is busy by processing of other command"},  
     205        { 0x6F85, SC_ERROR_CARD_CMD_FAILED,     "In the current folder the maximum quantity of file system objects is already created"},  
     206        { 0x6F86, SC_ERROR_CARD_CMD_FAILED,     "Invalid access right. Already login"},  
     207 
     208        { 0x9000, SC_NO_ERROR,                  NULL} 
    218209}; 
    219210 
    220 int rutoken_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2) 
    221 { 
    222         const int err_count = sizeof(rutoken_errors)/sizeof(rutoken_errors[0]); 
    223         int i; 
    224  
    225         sc_debug(card->ctx, "sw1 = %x, sw2 = %x", sw1, sw2); 
    226                                  
    227         for (i = 0; i < err_count; i++) { 
     211static int rutoken_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2) 
     212{ 
     213        size_t i; 
     214 
     215        for (i = 0; i < sizeof(rutoken_errors)/sizeof(rutoken_errors[0]); ++i) { 
    228216                if (rutoken_errors[i].SWs == ((sw1 << 8) | sw2)) { 
    229217                        if ( rutoken_errors[i].errorstr ) 
    230                                 sc_debug(card->ctx, rutoken_errors[i].errorstr); 
    231                         /*SC_FUNC_RETURN(card->ctx, 1, rutoken_errors[i].errorno);*/ 
     218                                sc_error(card->ctx, "%s\n", rutoken_errors[i].errorstr); 
     219                        sc_debug(card->ctx, "sw1 = %x, sw2 = %x", sw1, sw2); 
    232220                        return rutoken_errors[i].errorno; 
    233221                } 
    234222        } 
    235  
    236         sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2); 
    237         SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_CARD_CMD_FAILED); 
     223        sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2); 
     224        return SC_ERROR_CARD_CMD_FAILED; 
    238225} 
    239226 
    240227static int rutoken_dir_up(sc_card_t *card) 
    241228{ 
    242     u8 rbuf[256]; 
    243     int r = 0; 
    244     sc_apdu_t apdu; 
    245     SC_FUNC_CALLED(card->ctx, 1); 
    246         /*sc_debug(card->ctx, "\n\tpath = %s\n\ttype = %d", hexdump(path, pathlen), in_path->type); 
    247         prepare & transmit APDU 
    248         00 a4 00 04 20 - first*/ 
    249     sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA4, 0x03, 0x00); 
    250     apdu.cla = 0x00; 
    251     apdu.resplen = 256; 
    252     apdu.resp = rbuf; 
    253     apdu.le = 256; 
    254     r = sc_transmit_apdu(card, &apdu); 
    255     SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 
    256     sc_debug(card->ctx, "rbuf = %s len %d", hexdump(apdu.resp, apdu.resplen), apdu.resplen); 
    257     sc_debug(card->ctx, "sw1 = %x, sw2 = %x", apdu.sw1, apdu.sw2); 
    258     return 0; 
    259 } 
    260  
    261 /* make little endian path from normal path. 
    262    return 1 if right len, otherwise 0  */ 
    263 static int make_le_path(u8 *hPath, size_t len) 
    264 { 
    265 #ifdef BIG_ENDIAN_RUTOKEN 
    266         /*   we don't need it any more  */ 
    267         return 1; 
    268 #else 
    269         int i, ret = (len > 1) && !(len & 1);  /*  && (len <= SC_MAX_PATH_SIZE);  */ 
    270         if (ret) 
    271         { 
    272                 for(i = 0; i < len; i += 2) 
    273                 { 
    274                         u8 b = hPath[i]; 
    275                         hPath[i] = hPath[i+1]; 
    276                         hPath[i+1] =  b; 
    277                 } 
    278         } 
    279         return ret; 
    280 #endif 
     229        u8 rbuf[256]; 
     230        sc_apdu_t apdu; 
     231        int ret; 
     232 
     233        SC_FUNC_CALLED(card->ctx, 3); 
     234 
     235        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA4, 0x03, 0x00); 
     236        apdu.cla = 0x00; 
     237        apdu.resplen = sizeof(rbuf); 
     238        apdu.resp = rbuf; 
     239        apdu.le = sizeof(rbuf); 
     240 
     241        ret = sc_transmit_apdu(card, &apdu); 
     242        SC_TEST_RET(card->ctx, ret, "APDU transmit failed"); 
     243        ret = sc_check_sw(card, apdu.sw1, apdu.sw2); 
     244        SC_FUNC_RETURN(card->ctx, 3, ret); 
    281245} 
    282246 
    … …  
    285249        u8 rbuf[256]; 
    286250        u8 previd[2]; 
    287         int r = 0, len=0; 
    288         sc_apdu_t apdu; 
    289  
    290         SC_FUNC_CALLED(card->ctx, 1); 
    291         /*  sc_debug(card->ctx, "\n\tpath = %s\n\ttype = %d", hexdump(path, pathlen), in_path->type);  */ 
    292         /*  prepare & transmit APDU  */ 
    293         /*   00 a4 00 04 20 - first  */ 
    294          
    295         sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA4, 0x00, 0x00); 
    296         apdu.cla = 0x00; 
    297         apdu.resplen = 256; 
    298         apdu.resp = rbuf; 
    299         apdu.le = 256; 
    300         r = sc_transmit_apdu(card, &apdu); 
    301         SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 
    302         sc_debug(card->ctx, "rbuf = %s len %d", hexdump(apdu.resp, apdu.resplen), apdu.resplen); 
    303         sc_debug(card->ctx, "sw1 = %x, sw2 = %x", apdu.sw1, apdu.sw2); 
    304         if((apdu.sw1 == 0x6a) ) 
    305         { 
    306                 /* empty dir  */ 
    307             return 0; 
    308         } 
    309         /*  todo: add check buflen  */ 
    310         /*  save first file(dir) ID  */ 
    311         memcpy(buf+len, rbuf+6, 2); 
    312         memcpy(previd, rbuf+6, 2); 
    313         len += 2; 
    314         if(rbuf[4] == FDESCR_DF) 
    315             rutoken_dir_up(card); 
    316          
    317         /*  00 a4 00 02 02 prev id - next  */ 
    318         while(1) 
    319         { 
    320             sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x06); 
    321             apdu.cla = 0x00; 
    322             apdu.lc = 2; 
    323             apdu.data = previd; 
    324             apdu.datalen = 2; 
    325             apdu.resplen = 256; 
    326             apdu.resp = rbuf; 
    327             apdu.le = 256; 
    328             r = sc_transmit_apdu(card, &apdu); 
    329             SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 
    330             sc_debug(card->ctx, "rbuf = %s len %d", hexdump(apdu.resp, apdu.resplen), apdu.resplen); 
    331             sc_debug(card->ctx, "sw1 = %x, sw2 = %x", apdu.sw1, apdu.sw2); 
    332             if((apdu.sw1 == 0x6a) ) 
    333             { 
    334                     /*  end list  */ 
    335                         break; 
    336             } 
    337                 /*  todo: add check buflen  */ 
    338             /*  save first file(dir) ID  */ 
    339             memcpy(buf+len, rbuf+6, 2); 
    340             memcpy(previd, rbuf+6, 2); 
    341             len += 2; 
    342             if(rbuf[4] == FDESCR_DF) 
     251        sc_apdu_t apdu; 
     252        size_t len = 0; 
     253        int ret, first = 1; 
     254 
     255        SC_FUNC_CALLED(card->ctx, 1); 
     256        while (1) 
     257        { 
     258                if (first) 
     259                        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA4, 0x00, 0x00); 
     260                else 
     261                { 
     262                        /*  00 a4 00 02 02 prev id - next  */ 
     263                        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x02); 
     264                        apdu.lc = sizeof(previd); 
     265                        apdu.data = previd; 
     266                        apdu.datalen = sizeof(previd); 
     267                } 
     268                apdu.cla = 0x00; 
     269                apdu.resplen = sizeof(rbuf); 
     270                apdu.resp = rbuf; 
     271                apdu.le = sizeof(rbuf); 
     272                ret = sc_transmit_apdu(card, &apdu); 
     273                SC_TEST_RET(card->ctx, ret, "APDU transmit failed"); 
     274 
     275                if (apdu.sw1 == 0x6A  &&  apdu.sw2 == 0x82) 
     276                        break; /*  if (first) "end list" else "empty dir"  */ 
     277 
     278                ret = sc_check_sw(card, apdu.sw1, apdu.sw2); 
     279                SC_TEST_RET(card->ctx, ret, "Get list files failed"); 
     280 
     281                /*  save first file(dir) ID  */ 
     282                if (len + 2 <= buflen) 
     283                { 
     284                        buf[len++] = rbuf[6]; 
     285                        buf[len++] = rbuf[7]; 
     286                } 
     287                memcpy(previd, rbuf+6, sizeof(previd)); 
     288                if (rbuf[4] == FDESCR_DF) 
    343289                        rutoken_dir_up(card); 
    344         } 
    345         make_le_path(buf, len); 
    346         return len; 
     290                first = 0; 
     291        } 
     292        SC_FUNC_RETURN(card->ctx, 1, len); 
    347293} 
    348294 
    349295static void rutoken_process_fcp(sc_card_t *card, u8 *pIn, sc_file_t *file) 
    350296{ 
    351 #ifdef BIG_ENDIAN_RUTOKEN 
    352297        file->size = pIn[3] + ((uint16_t)pIn[2])*256; 
    353298        file->id = pIn[7] + ((uint16_t)pIn[6])*256; 
    354 #else 
    355         file->size = pIn[2] + ((uint16_t)pIn[3])*256; 
    356         file->id = pIn[6] + ((uint16_t)pIn[7])*256; 
    357 #endif 
    358299 
    359300        if (pIn[4] == FDESCR_DF) 
    … …  
    367308        } 
    368309        sc_file_set_sec_attr(file, pIn + 17, SEC_ATTR_SIZE); 
     310 
     311        if (file->sec_attr  &&  file->sec_attr_len == SEC_ATTR_SIZE 
     312#ifndef SET_ACL_FOR_EF_LENLESS8_RUTOKEN 
     313/* 
     314 * No set ACL for EF: 
     315 *  PrKDF_path: "3F00FF000001" - SC_PKCS15_PRKDF 
     316 *  PuKDF_path: "3F00FF000002" - SC_PKCS15_PUKDF 
     317 *  CDF_path:   "3F00FF000003" - SC_PKCS15_CDF 
     318 *  DODF_path:  "3F00FF000004" - SC_PKCS15_DODF 
     319 *  (see files: src/libopensc/pkcs15-rutoken.c, src/pkcs15init/rutoken.profile) 
     320 */ 
     321                        && (file->type != SC_FILE_TYPE_WORKING_EF || file->path.len >= 8) 
     322#endif 
     323        ) 
     324        { 
     325                sc_file_add_acl_entry(file, SC_AC_OP_SELECT, 
     326                                SC_AC_NONE, SC_AC_KEY_REF_NONE); 
     327                if (file->sec_attr[0] & 0x40) /* if AccessMode.6 */ 
     328                { 
     329                        sc_debug(card->ctx, "SC_AC_OP_DELETE %i %i", 
     330                                        (int)(*(int8_t*)&file->sec_attr[1 +6]), 
     331                                        file->sec_attr[1+7 +6]); 
     332                        sc_file_add_acl_entry(file, SC_AC_OP_DELETE, 
     333                                        (int)(*(int8_t*)&file->sec_attr[1 +6]), 
     334                                        file->sec_attr[1+7 +6]); 
     335                } 
     336                if (file->sec_attr[0] & 0x01) /* if AccessMode.0 */ 
     337                { 
     338                        sc_debug(card->ctx, (file->type == SC_FILE_TYPE_DF) ? 
     339                                        "SC_AC_OP_CREATE %i %i" : "SC_AC_OP_READ %i %i", 
     340                                        (int)(*(int8_t*)&file->sec_attr[1 +0]), 
     341                                        file->sec_attr[1+7 +0]); 
     342                        sc_file_add_acl_entry(file, 
     343                                        (file->type == SC_FILE_TYPE_DF) ? 
     344                                        SC_AC_OP_CREATE : SC_AC_OP_READ, 
     345                                        (int)(*(int8_t*)&file->sec_attr[1 +0]), 
     346                                        file->sec_attr[1+7 +0]); 
     347                } 
     348                if (file->type == SC_FILE_TYPE_DF) 
     349                { 
     350                        sc_file_add_acl_entry(file, SC_AC_OP_LIST_FILES, 
     351                                        SC_AC_NONE, SC_AC_KEY_REF_NONE); 
     352                } 
     353                else 
     354                        if (file->sec_attr[0] & 0x02) /* if AccessMode.1 */ 
     355                        { 
     356                                sc_debug(card->ctx, "SC_AC_OP_UPDATE %i %i", 
     357                                                (int)(*(int8_t*)&file->sec_attr[1 +1]), 
     358                                                file->sec_attr[1+7 +1]); 
     359                                sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, 
     360                                                (int)(*(int8_t*)&file->sec_attr[1 +1]), 
     361                                                file->sec_attr[1+7 +1]); 
     362                                sc_debug(card->ctx, "SC_AC_OP_WRITE %i %i", 
     363                                                (int)(*(int8_t*)&file->sec_attr[1 +1]), 
     364                                                file->sec_attr[1+7 +1]); 
     365                                sc_file_add_acl_entry(file, SC_AC_OP_WRITE, 
     366                                                (int)(*(int8_t*)&file->sec_attr[1 +1]), 
     367                                                file->sec_attr[1+7 +1]); 
     368                        } 
     369        } 
    369370} 
    370371 
    371372static int rutoken_select_file(sc_card_t *card, 
    372                               const sc_path_t *in_path, 
    373                               sc_file_t **file) 
    374 { 
    375         int ret = SC_ERROR_INVALID_ARGUMENTS; 
     373                        const sc_path_t *in_path, sc_file_t **file) 
     374{ 
     375        int ret; 
    376376        u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; 
    377         int pathlen = in_path->len; 
     377        int pathlen; 
    378378        u8 buf[SC_MAX_APDU_BUFFER_SIZE]; 
    379379        sc_apdu_t apdu; 
    380380 
    381381        SC_FUNC_CALLED(card->ctx, 1); 
    382  
     382        if (!in_path || in_path->len < 2) 
     383                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); 
     384 
     385        pathlen = in_path->len; 
    383386        memcpy(path, in_path->value, pathlen); 
    384387 
    385         sc_debug(card->ctx, "\n\tpath = %s\n\ttype = %d", hexdump(path, pathlen), in_path->type); 
    386         /*      prepare & transmit APDU  */ 
    387         if (make_le_path(path, pathlen))  
    388         { 
    389                 sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); 
    390                  
    391                 switch (in_path->type) 
    392                 { 
    393                 case SC_PATH_TYPE_FILE_ID: 
    394                         if (pathlen == 2)       /*  select file in current df  */ 
     388        sc_debug(card->ctx, "\n\tpath = %s\n\ttype = %d", 
     389                        hexdump(path, pathlen), in_path->type); 
     390 
     391        ret = SC_ERROR_INVALID_ARGUMENTS; 
     392        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); 
     393        switch (in_path->type) 
     394        { 
     395        case SC_PATH_TYPE_FILE_ID: 
     396                if (pathlen == 2) /*  select file in current df  */ 
     397                { 
     398                        apdu.p1 = 2; 
     399                        ret = SC_SUCCESS; 
     400                } 
     401                break; 
     402        case SC_PATH_TYPE_PATH: 
     403                apdu.p1 = 8; 
     404                if (path[0] == 0x3F  && path[1] == 0x00) 
     405                { 
     406                        if (pathlen == 2) /* select MF  */ 
    395407                        { 
    396                                 apdu.p1 = 2; 
    397                                 ret = SC_SUCCESS; 
     408                                apdu.p1 = 0; 
     409                        }  
     410                        else /* select DF  */ 
     411                        { 
     412                                path += 2; 
     413                                pathlen -= 2; 
    398414                        } 
    399                         break; 
    400                 case SC_PATH_TYPE_PATH: 
    401                         apdu.p1 = 8; 
    402                         if (memcmp(path, MF_PATH, 2) == 0) 
    403                         { 
    404                                 if (pathlen == 2) /* select MF  */ 
    405                                 { 
    406                                         apdu.p1 = 0; 
    407                                 }  
    408                                 else    /* select DF  */ 
    409                                 { 
    410                                         path += 2; 
    411                                         pathlen -= 2; 
    412                                 } 
    413                         } 
    414                         ret = SC_SUCCESS; 
    415                         break; 
    416                 default: 
    417                         ret = SC_ERROR_NOT_SUPPORTED; 
    418                         break; 
    419Â