Changeset 3310

Show
Ignore:
Timestamp:
01/03/08 08:59:14 (12 months ago)
Author:
ludovic.rousseau
Message:

new patch for ruToken support

Thanks to Andrew V. Stepanov
http://www.opensc-project.org/pipermail/opensc-devel/2007-December/010631.html

Location:
trunk/src
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/libopensc/Makefile.am

    r3304 r3310  
    3737        pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ 
    3838        pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ 
    39         compression.c p15card-helper.c pkcs15-rutoken.c 
     39        pkcs15-rutoken.c pkcs15-prkey-rutoken.c \ 
     40        compression.c p15card-helper.c 
    4041libopensc_la_LDFLAGS = -version-info @OPENSC_LT_CURRENT@:@OPENSC_LT_REVISION@:@OPENSC_LT_AGE@ 
    4142libopensc_la_LIBADD = @LIBSCCONF@ $(OPENSSL_LIBS) $(OPENCT_LIBS) $(PCSC_LIBS) $(LTLIB_LIBS) 
  • trunk/src/libopensc/card-rutoken.c

    r3304 r3310  
    2121#include "internal.h" 
    2222#include "cardctl.h" 
     23#include <sys/types.h> 
    2324#include <ctype.h> 
    2425#include <string.h> 
     
    3738#endif 
    3839 
    39  
    40  
    4140#define FDESCR_DF           0x38    /*00111000b*/ 
    4241#define FDESCR_EF           0x01 
     
    4443#define ID_RESERVED_CURDF   0x3FFF      /*Reserved ID for current DF*/ 
    4544 
    46 int get_prkey_from_bin(u8* data, int len, struct sc_pkcs15_prkey **key); 
     45#ifdef HAVE_OPENSSL 
     46int get_prkey_from_bin(const u8 *data, size_t len, struct sc_pkcs15_prkey **key); 
     47#endif 
    4748 
    4849#ifdef BIG_ENDIAN_RUTOKEN 
     
    5152#define MF_PATH             "\x00\x3F" 
    5253#endif 
     54 
    5355struct auth_senv { 
    5456        unsigned int algorithm; 
    55         int key_file_id; 
    56         size_t key_size; 
    57         unsigned int algorithm_flags; 
    58         sc_path_t path; 
    5957}; 
    6058typedef struct auth_senv auth_senv_t; 
    6159 
    6260static const sc_SecAttrV2_t default_sec_attr = { 
    63         0x40,  
    64         0, 0, 0, 0, 0, 0, 1, 
    65         0, 0, 0, 0, 0, 0, 2 
     61        0x42, 
     62        0, 1, 0, 0, 0, 0, 1, 
     63        0, 2, 0, 0, 0, 0, 2 
    6664}; 
    6765 
    6866static const struct sc_card_operations *iso_ops = NULL; 
    6967 
    70 struct sc_card_operations rutoken_ops; 
     68static struct sc_card_operations rutoken_ops; 
     69 
    7170static struct sc_card_driver rutoken_drv = { 
    7271        "ruToken driver", 
     
    8180}; 
    8281 
    83 static int make_le_path(u8 *hPath, size_t len); 
    84 static int rutoken_get_do_info(sc_card_t *card, sc_DO_INFO_t * pInfo); 
    85  
    8682const char *hexdump(const void *data, size_t len) 
    8783{ 
     
    124120{ 
    125121        int ret = SC_ERROR_MEMORY_FAILURE; 
    126 #ifdef DEBUG 
    127         /*  if(!card->ctx->debug) card->ctx->debug = 1;  */ 
    128 #endif 
    129         SC_FUNC_CALLED(card->ctx, 1); 
     122 
     123        SC_FUNC_CALLED(card->ctx, 1); 
     124 
    130125        card->name = "rutoken card"; 
    131126        card->drv_data = malloc(sizeof(auth_senv_t)); 
     
    138133        /* add algorithm  
    139134        TODO: may nid som other flag  */ 
    140         unsigned int flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; /* SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_RSA_HASH_MD5_SHA1 | SC_ALGORITHM_RSA_PAD_NONE*/ 
     135        unsigned int flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; 
     136                                /* SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_SHA1 
     137                                | SC_ALGORITHM_RSA_HASH_MD5_SHA1 
     138                                | SC_ALGORITHM_RSA_PAD_NONE */ 
    141139 
    142140        _sc_card_add_rsa_alg(card, 256, flags, 0); 
     
    146144        _sc_card_add_rsa_alg(card, 2048, flags, 0); 
    147145        sc_algorithm_info_t info; 
    148         flags = SC_ALGORITHM_GOST_CRYPT_PZ | SC_ALGORITHM_GOST_CRYPT_GAMM | SC_ALGORITHM_GOST_CRYPT_GAMMOS; 
     146        flags = SC_ALGORITHM_GOST_CRYPT_PZ | SC_ALGORITHM_GOST_CRYPT_GAMM 
     147                | SC_ALGORITHM_GOST_CRYPT_GAMMOS; 
    149148        memset(&info, 0, sizeof(info)); 
    150149        info.algorithm = SC_ALGORITHM_GOST; 
     
    221220        for (i = 0; i < err_count; i++) { 
    222221                if (rutoken_errors[i].SWs == ((sw1 << 8) | sw2)) { 
    223                         if ( rutoken_errors[i].errorstr ) sc_debug(card->ctx, rutoken_errors[i].errorstr); 
     222                        if ( rutoken_errors[i].errorstr ) 
     223                                sc_debug(card->ctx, rutoken_errors[i].errorstr); 
    224224                        /*SC_FUNC_RETURN(card->ctx, 1, rutoken_errors[i].errorno);*/ 
    225225                        return rutoken_errors[i].errorno; 
     
    231231} 
    232232 
    233 int rutoken_dir_up(sc_card_t *card) 
     233static int rutoken_dir_up(sc_card_t *card) 
    234234{ 
    235235    u8 rbuf[256]; 
     
    252252} 
    253253 
     254/* make little endian path from normal path. 
     255   return 1 if right len, otherwise 0  */ 
     256static int make_le_path(u8 *hPath, size_t len) 
     257{ 
     258#ifdef BIG_ENDIAN_RUTOKEN 
     259        /*   we don't need it any more  */ 
     260        return 1; 
     261#else 
     262        int i, ret = (len > 1) && !(len & 1);  /*  && (len <= SC_MAX_PATH_SIZE);  */ 
     263        if (ret) 
     264        { 
     265                for(i = 0; i < len; i += 2) 
     266                { 
     267                        u8 b = hPath[i]; 
     268                        hPath[i] = hPath[i+1]; 
     269                        hPath[i+1] =  b; 
     270                } 
     271        } 
     272        return ret; 
     273#endif 
     274} 
    254275 
    255276static int rutoken_list_files(sc_card_t *card, u8 *buf, size_t buflen) 
     
    288309         
    289310        /*  00 a4 00 02 02 prev id - next  */ 
    290         while(1){ 
     311        while(1) 
     312        { 
    291313            sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x06); 
    292314            apdu.cla = 0x00; 
     
    318340} 
    319341 
    320 /*  make little endian path from normal path. 
    321   return 1 if right len, otherwise 0  */ 
    322 static int make_le_path(u8 *hPath, size_t len) 
    323 { 
    324 #ifdef BIG_ENDIAN_RUTOKEN 
    325         /*   we don't need it any more  */ 
    326   return 1; 
    327 #else 
    328         int i, ret = (len > 1) && !(len & 1);  /*  && (len <= SC_MAX_PATH_SIZE);  */ 
    329         if (ret) 
    330         { 
    331                 for(i = 0; i < len; i += 2) 
    332                 { 
    333                         u8 b = hPath[i]; 
    334                         hPath[i] = hPath[i+1]; 
    335                         hPath[i+1] =  b; 
    336                 } 
    337         } 
    338         return ret; 
    339 #endif 
    340 } 
    341  
    342 void rutoken_process_fcp(sc_card_t *card, u8 *pIn, sc_file_t *file) 
     342static void rutoken_process_fcp(sc_card_t *card, u8 *pIn, sc_file_t *file) 
    343343{ 
    344344#ifdef BIG_ENDIAN_RUTOKEN 
     
    466466{ 
    467467        int ret = SC_ERROR_NOT_SUPPORTED; 
    468  
    469468        return ret; 
    470469} 
    471470*/ 
    472471 
    473 static int rutoken_construct_fcp(sc_card_t *card, const sc_file_t *file, 
    474         u8 *out) 
     472static int rutoken_construct_fcp(sc_card_t *card, const sc_file_t *file, u8 *out) 
    475473{ 
    476474        SC_FUNC_CALLED(card->ctx, 1); 
     
    494492                out[4] = 0x01; 
    495493                /*   set the length (write to wBodyLen)  */ 
    496                 /*  *((unsigned short int*)(out) + 1) = (unsigned short int)file->size; */ 
    497494#ifdef BIG_ENDIAN_RUTOKEN 
    498495                out[2] = file->size / 256; 
     
    508505        } 
    509506        /*   set file ID  */ 
    510         /*  *((unsigned short int*)(out) + 3) = (unsigned short int)file->id;  */ 
    511507#ifdef BIG_ENDIAN_RUTOKEN 
    512508        out[6] = file->id / 256; 
     
    522518                memcpy(out + 17, &default_sec_attr, SEC_ATTR_SIZE); 
    523519         
    524          
    525520        SC_FUNC_RETURN(card->ctx, 1, SC_NO_ERROR); 
    526521} 
     
    579574} 
    580575 
     576static int rutoken_verify(sc_card_t *card, unsigned int type, int ref_qualifier, 
     577                        const u8 *data, size_t data_len, int *tries_left) 
     578{ 
     579        int ret = SC_ERROR_CARD_CMD_FAILED; 
     580        sc_apdu_t apdu; 
     581 
     582        SC_FUNC_CALLED(card->ctx, 1); 
     583        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, ref_qualifier); 
     584        apdu.lc = data_len; 
     585        apdu.datalen = data_len; 
     586        apdu.data = data; 
     587        if(sc_transmit_apdu(card, &apdu) >= 0) 
     588        { 
     589                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     590                if(ret == SC_ERROR_PIN_CODE_INCORRECT  &&  tries_left) 
     591                { 
     592                        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 
     593                                        ref_qualifier); 
     594                        ret = sc_transmit_apdu(card, &apdu); 
     595                        if(ret >= 0) 
     596                        { 
     597                                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     598                                if(ret == SC_ERROR_PIN_CODE_INCORRECT) 
     599                                        *tries_left = (int)(apdu.sw2 & 0x0f); 
     600                        } 
     601                } 
     602        } 
     603        SC_FUNC_RETURN(card->ctx, 1, ret); 
     604} 
     605 
    581606static int rutoken_logout(sc_card_t *card) 
    582607{ 
     
    585610        sc_path_t path; 
    586611 
     612        SC_FUNC_CALLED(card->ctx, 1); 
    587613        sc_format_path("3F00", &path); 
    588614        if (rutoken_select_file(card, &path, NULL) == SC_SUCCESS) 
     
    596622} 
    597623 
     624static int rutoken_change_reference_data(sc_card_t *card, unsigned int type, 
     625                        int ref_qualifier, const u8 *old, size_t oldlen, 
     626                        const u8 *newref, size_t newlen, int *tries_left) 
     627{ 
     628        int left; 
     629        int ret = SC_ERROR_CARD_CMD_FAILED; 
     630        sc_apdu_t apdu; 
     631 
     632        SC_FUNC_CALLED(card->ctx, 1); 
     633         
     634        if(old && oldlen) 
     635        { 
     636                sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, ref_qualifier); 
     637                if(sc_transmit_apdu(card, &apdu) >= 0 
     638                                &&  apdu.sw1 != 0x90  &&  apdu.sw2 != 0x00) 
     639                { 
     640                        rutoken_logout(card); 
     641                        rutoken_verify(card, type, ref_qualifier, old, oldlen, &left); 
     642                } 
     643        } 
     644        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x01, ref_qualifier); 
     645        apdu.lc = newlen; 
     646        apdu.datalen = newlen; 
     647        apdu.data = newref; 
     648        if(sc_transmit_apdu(card, &apdu) >= 0) 
     649        { 
     650                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     651                if(ret == SC_ERROR_PIN_CODE_INCORRECT  &&  tries_left) 
     652                        *tries_left = (int)(apdu.sw2 & 0x0f); 
     653        } 
     654        SC_FUNC_RETURN(card->ctx, 1, ret); 
     655} 
     656 
     657static int rutoken_reset_retry_counter(sc_card_t *card, unsigned int type, 
     658                        int ref_qualifier, const u8 *puk, size_t puklen, 
     659                        const u8 *newref, size_t newlen) 
     660{ 
     661#ifdef FORCE_VERIFY_RUTOKEN 
     662        int left; 
     663#endif 
     664        int ret = SC_ERROR_CARD_CMD_FAILED; 
     665        sc_apdu_t apdu; 
     666 
     667        SC_FUNC_CALLED(card->ctx, 1); 
     668#ifdef FORCE_VERIFY_RUTOKEN 
     669        if(puk && puklen) 
     670        { 
     671                sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, ref_qualifier); 
     672                if(sc_transmit_apdu(card, &apdu) >= 0 
     673                                &&  apdu.sw1 != 0x90  &&  apdu.sw2 != 0x00) 
     674                { 
     675                        rutoken_logout(card); 
     676                        rutoken_verify(card, type, ref_qualifier, puk, puklen, &left); 
     677                } 
     678        } 
     679#endif 
     680        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2c, 0x03, ref_qualifier); 
     681        if(sc_transmit_apdu(card, &apdu) >= 0) 
     682                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     683        SC_FUNC_RETURN(card->ctx, 1, ret); 
     684} 
     685 
    598686static int rutoken_restore_security_env(sc_card_t *card, int se_num) 
    599687{ 
    600688        int ret = SC_ERROR_CARD_CMD_FAILED; 
    601689        sc_apdu_t apdu; 
    602         SC_FUNC_CALLED(card->ctx, 1); 
    603          
     690 
     691        SC_FUNC_CALLED(card->ctx, 1); 
    604692        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 3, se_num); 
    605693        if(sc_transmit_apdu(card, &apdu) >= 0) 
    606694                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
    607  
    608         SC_FUNC_RETURN(card->ctx, 1, ret); 
    609 } 
    610  
    611 int rutoken_set_security_env(sc_card_t *card, 
     695        SC_FUNC_RETURN(card->ctx, 1, ret); 
     696} 
     697 
     698static int rutoken_set_security_env(sc_card_t *card,  
    612699                         const sc_security_env_t *env, 
    613700                         int se_num) 
     
    621708        if(env->algorithm == SC_ALGORITHM_RSA) 
    622709        { 
    623                 const char PRK_DF[] = "3F0000000000FF001001"; 
    624                 sc_debug(card->ctx, "RSA\n"); 
    625710                senv->algorithm = SC_ALGORITHM_RSA_RAW; 
    626                 if(env->operation == SC_SEC_OPERATION_DECIPHER || env->operation == SC_SEC_OPERATION_SIGN) 
    627                 { 
    628                         sc_format_path(PRK_DF, &senv->path); 
    629                         sc_append_path(&senv->path, &env->file_ref); 
    630                 } 
    631                 else ret = SC_ERROR_INVALID_ARGUMENTS; 
    632711                return ret; 
    633712        } 
    634713        else 
    635714                senv->algorithm = SC_ALGORITHM_GOST; 
     715 
    636716        if (env->key_ref_len != 1) 
    637717        { 
     
    672752                        ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
    673753        } 
    674         /*  set driver data  */ 
    675         if (ret == SC_NO_ERROR) 
    676         { 
    677                 /*  TODO: add check  */ 
    678                 senv->algorithm = SC_ALGORITHM_GOST; 
    679                 senv->algorithm_flags = env->algorithm_flags; 
    680                 senv->key_file_id = env->key_ref[0]; 
    681                 senv->key_size = 256; 
    682         } 
    683         SC_FUNC_RETURN(card->ctx, 1, ret); 
    684 } 
    685  
    686 void rutoken_set_do_hdr(u8 *data, sc_DOHdrV2_t *pHdr) 
     754        SC_FUNC_RETURN(card->ctx, 1, ret); 
     755} 
     756 
     757static void rutoken_set_do_hdr(u8 *data, sc_DOHdrV2_t *pHdr) 
    687758{ 
    688759        if(data) 
    689760        { 
     761#ifdef BIG_ENDIAN_RUTOKEN 
     762                data[0] = (u8)(pHdr->wDOBodyLen / 0x100); 
     763                data[1] = (u8)(pHdr->wDOBodyLen % 0x100); 
     764#else 
    690765                data[0] = (u8)(pHdr->wDOBodyLen % 0x100); 
    691766                data[1] = (u8)(pHdr->wDOBodyLen / 0x100); 
     767#endif 
    692768                data[2] = (u8)(pHdr->OTID.byObjectType); 
    693769                data[3] = (u8)(pHdr->OTID.byObjectID); 
     
    699775                memcpy(data + 17, pHdr->SA_V2, SEC_ATTR_SIZE); 
    700776        } 
    701 } 
    702  
    703 void rutoken_set_do(u8 *data, sc_DO_V2_t * pDO) 
    704 { 
    705         rutoken_set_do_hdr(data, &pDO->HDR); 
    706         memcpy(data + SC_RUTOKEN_DO_HDR_LEN, pDO->abyDOBody, pDO->HDR.wDOBodyLen); 
    707777} 
    708778 
     
    762832        else 
    763833        { 
    764                 rutoken_set_do(data, pDO); 
     834                rutoken_set_do_hdr(data, &pDO->HDR); 
     835                memcpy(data + SC_RUTOKEN_DO_HDR_LEN, pDO->abyDOBody, pDO->HDR.wDOBodyLen); 
    765836                 
    766837                sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xda, 0x01, 0x62); 
     
    865936                   u8 * out, size_t outlen, int p1, int p2, int isIV) 
    866937{ 
    867         sc_apdu_t apdu; 
    868         int rv = SC_NO_ERROR; 
    869          
    870         sc_debug(card->ctx,": crgram_len %i;  outlen %i\n", crgram_len, outlen); 
    871         if (!out || !outlen)  
     938        const size_t cipher_chunk = 248;  /* cipher_chunk <= SC_MAX_APDU_BUFFER_SIZE  */ 
     939        size_t len, outlen_tail = outlen; 
     940        u8 *buf; 
     941        int ret; 
     942        sc_apdu_t apdu; 
     943         
     944        SC_FUNC_CALLED(card->ctx, 1); 
     945        sc_debug(card->ctx, ": crgram_len %i; outlen %i\n", crgram_len, outlen); 
     946 
     947        if (!out) 
    872948                return SC_ERROR_INVALID_ARGUMENTS; 
     949        if (crgram_len < 16 || ((crgram_len) % 8)) 
     950                return SC_ERROR_WRONG_LENGTH; 
     951 
     952        buf = malloc(cipher_chunk); 
     953        if (!buf) 
     954                return SC_ERROR_OUT_OF_MEMORY; 
    873955         
    874956        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, p1, p2); 
    875          
    876         apdu.resp = (u8*)malloc(SC_MAX_APDU_BUFFER_SIZE); 
    877         if (!apdu.resp) 
    878                 return SC_ERROR_OUT_OF_MEMORY; 
    879         apdu.resplen = SC_MAX_APDU_BUFFER_SIZE; 
    880         if (crgram_len < 16 || ((crgram_len) % 8))   
    881                 rv = SC_ERROR_WRONG_LENGTH; 
    882         size_t cur_len = 0; 
    883         unsigned char is_first = 1; 
    884         unsigned int cur_data_len;       
    885          
    886         while( (rv == SC_NO_ERROR) && (cur_len != crgram_len) && (outlen > cur_len)) 
    887         { 
    888                 cur_data_len = (crgram_len - cur_len) % 248; 
    889                 if(!cur_data_len) cur_data_len = 248; 
    890                  
    891                 apdu.data = crgram + cur_len; 
    892                 apdu.lc = apdu.datalen = cur_data_len; 
    893                 apdu.cla = crgram_len - cur_len - cur_data_len > 0 ? 0x10 : 0x00; 
    894                 apdu.le = apdu.resplen = 248; 
    895                  
    896                 if((rv = sc_transmit_apdu(card, &apdu)) >= 0 && 
    897                    (rv = rutoken_check_sw(card, apdu.sw1, apdu.sw2)) == SC_NO_ERROR)  
     957        do 
     958        { 
     959                len = (crgram_len > cipher_chunk) ? cipher_chunk : crgram_len; 
     960                apdu.lc = len; 
     961                apdu.datalen = len; 
     962                apdu.data = crgram; 
     963                crgram += len; 
     964                crgram_len -= len; 
     965 
     966                apdu.cla = (crgram_len == 0) ? 0x00 : 0x10; 
     967                apdu.le = len; 
     968                apdu.resplen = len; 
     969                apdu.resp = buf; 
     970         
     971                if (sc_transmit_apdu(card, &apdu) >= 0) 
     972                        ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     973                else 
     974                        ret = SC_ERROR_CARD_CMD_FAILED; 
     975                if (ret == SC_NO_ERROR) 
    898976                { 
    899                         if(isIV && is_first) 
     977                        if (isIV) 
    900978                        { 
    901                                 /*  break initialization vector  */ 
    902                                 memcpy(out, apdu.resp + 8, apdu.resplen - 8); 
    903                                 out += apdu.resplen - 8; 
    904                                 cur_len += apdu.resplen; 
    905                                 is_first = 0; 
     979                                apdu.resp += 8; 
     980                                apdu.resplen -= 8; 
     981                                isIV = 0; 
    906982                        } 
     983                        if (apdu.resplen > outlen_tail) 
     984                                ret = SC_ERROR_BUFFER_TOO_SMALL; 
    907985                        else 
    908986                        { 
    909                                 /*  memcpy(out + cur_len, apdu.resp, apdu.resplen);  */ 
    910987                                memcpy(out, apdu.resp, apdu.resplen); 
    911                                 cur_len += apdu.resplen; 
    912988                                out += apdu.resplen; 
     989                                outlen_tail -= apdu.resplen; 
    913990                        } 
    914991                } 
    915         } 
    916         if (rv == SC_NO_ERROR) rv = (cur_len == crgram_len) ? isIV ? cur_len - 8 : cur_len : SC_ERROR_BUFFER_TOO_SMALL; 
    917          
    918         if (apdu.resp) 
    919                 free(apdu.resp); 
    920          
    921         sc_debug(card->ctx, "return decipher len %d\n", rv); 
    922         return rv; 
     992        } while (ret == SC_NO_ERROR  &&  crgram_len != 0); 
     993         
     994        free(buf); 
     995         
     996        sc_debug(card->ctx, "len out cipher %d\n", outlen - outlen_tail); 
     997        if (ret == SC_NO_ERROR) 
     998                ret = (outlen_tail == 0) ? (int)outlen : SC_ERROR_WRONG_LENGTH; 
     999 
     1000        SC_FUNC_RETURN(card->ctx, 1, ret); 
    9231001} 
    9241002 
    9251003/*  Launcher for chipher  */ 
    926 static int rutoken_decipher(sc_card_t *card, struct sc_rutoken_decipherinfo *ptr) 
    927 { 
    928         return rutoken_cipher_p(card, ptr->inbuf, ptr->inlen, ptr->outbuf, ptr->outlen, 0x80, 0x86, 1); 
    929 } 
    930  
    931 /*  Launcher for chipher  */ 
    932  
    933 static int rutoken_encipher(sc_card_t *card, struct sc_rutoken_decipherinfo *ptr) 
    934 { 
    935         return rutoken_cipher_p(card, ptr->inbuf, ptr->inlen, ptr->outbuf, ptr->outlen, 0x86, 0x80, 0); 
    936 } 
    937  
    938 int rutoken_read_file(sc_card_t *card, sc_path_t *path, u8 **out, int *len) 
     1004 
     1005static int rutoken_cipher_gost(sc_card_t *card,  
     1006                struct sc_rutoken_decipherinfo *ptr, char is_enchiper) 
     1007{ 
     1008        int ret; 
     1009 
     1010        if (is_enchiper) 
     1011                ret = rutoken_cipher_p(card, ptr->inbuf, ptr->inlen,  
     1012                                ptr->outbuf, ptr->outlen, 0x86, 0x80, 0); 
     1013        else 
     1014                ret = rutoken_cipher_p(card, ptr->inbuf, ptr->inlen,  
     1015                                ptr->outbuf, ptr->outlen, 0x80, 0x86, 1); 
     1016        if (ret > 0) 
     1017        { 
     1018                if ((size_t)ret == ptr->outlen) 
     1019                        ret = SC_SUCCESS; 
     1020                else 
     1021                        ret = SC_ERROR_INTERNAL; /* SC_ERROR_DECRYPT_FAILED; */ 
     1022        } 
     1023        return ret; 
     1024 
     1025} 
     1026 
     1027static int rutoken_compute_mac_gost(sc_card_t *card,  
     1028                        const u8 *in, size_t ilen,  
     1029                        u8 *out, size_t olen) 
     1030{ 
     1031        const size_t signing_chunk = 248; 
     1032        size_t len; 
     1033        int ret; 
     1034        sc_apdu_t apdu; 
     1035 
     1036        SC_FUNC_CALLED(card->ctx, 1); 
     1037 
     1038        if (!in || !out || olen != 4 || ilen == 0) 
     1039                return SC_ERROR_INVALID_ARGUMENTS; 
     1040        do 
     1041        { 
     1042                sc_format_apdu(card, &apdu, 
     1043                                ilen > signing_chunk ? 
     1044                                SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 
     1045                                0x2A, 0x90, 0x80); 
     1046                len = (ilen > signing_chunk) ? signing_chunk : ilen; 
     1047                apdu.lc = len; 
     1048                apdu.datalen = len; 
     1049                apdu.data = in; 
     1050                in += len; 
     1051                ilen -= len; 
     1052                if (ilen == 0) 
     1053        { 
     1054                        apdu.cla = 0x00; 
     1055                        apdu.le = olen; 
     1056                        apdu.resplen = olen; 
     1057                        apdu.resp = out; 
     1058        } 
     1059        else 
     1060                        apdu.cla = 0x10; 
     1061                if (sc_transmit_apdu(card, &apdu) >= 0) 
     1062                        ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     1063                else 
     1064                        ret = SC_ERROR_CARD_CMD_FAILED; 
     1065        } while (ret == SC_NO_ERROR  &&  ilen != 0); 
     1066         
     1067        SC_FUNC_RETURN(card->ctx, 1, ret); 
     1068} 
     1069         
     1070/*  RSA emulation  */ 
     1071 
     1072#ifdef HAVE_OPENSSL 
     1073 
     1074static int rutoken_get_current_fileid(sc_card_t *card, u8 id[2]) 
     1075{ 
     1076        sc_apdu_t apdu; 
     1077        int ret = SC_ERROR_CARD_CMD_FAILED; 
     1078 
     1079        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x11); 
     1080        apdu.resp = id; 
     1081        apdu.resplen = sizeof(id); 
     1082        apdu.le = 2; 
     1083        if(sc_transmit_apdu(card, &apdu) >= 0) 
     1084                ret = rutoken_check_sw(card, apdu.sw1, apdu.sw2); 
     1085        SC_FUNC_RETURN(card->ctx, 1, ret); 
     1086}</