"Fossies" - the Fresh Open Source Software Archive

Member "opensc-0.22.0/src/libopensc/card-entersafe.c" (10 Aug 2021, 46814 Bytes) of package /linux/privat/opensc-0.22.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "card-entersafe.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.20.0_vs_0.21.0.

    1 /*
    2  * This library is free software; you can redistribute it and/or
    3  * modify it under the terms of the GNU Lesser General Public
    4  * License as published by the Free Software Foundation; either
    5  * version 2.1 of the License, or (at your option) any later version.
    6  *
    7  * This library is distributed in the hope that it will be useful,
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   10  * Lesser General Public License for more details.
   11  *
   12  * You should have received a copy of the GNU Lesser General Public
   13  * License along with this library; if not, write to the Free Software
   14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   15  */
   16 
   17 /* Initially written by Weitao Sun (weitao@ftsafe.com) 2008 */
   18 
   19 #if HAVE_CONFIG_H
   20 #include "config.h"
   21 #endif
   22 #ifdef ENABLE_OPENSSL   /* empty file without openssl */
   23 
   24 #include <stdlib.h>
   25 #include <string.h>
   26 
   27 #include <openssl/evp.h>
   28 
   29 #include "internal.h"
   30 #include "asn1.h"
   31 #include "cardctl.h"
   32 
   33 static const struct sc_atr_table entersafe_atrs[] = {
   34     { 
   35          "3b:0f:00:65:46:53:05:19:05:71:df:00:00:00:00:00:00", 
   36          "ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff:00:00:00:00:00:00", 
   37          "ePass3000", SC_CARD_TYPE_ENTERSAFE_3K, 0, NULL },
   38     { 
   39          "3b:9f:95:81:31:fe:9f:00:65:46:53:05:30:06:71:df:00:00:00:80:6a:82:5e",
   40          "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:00:00:00:00",
   41          "FTCOS/PK-01C", SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, 0, NULL },
   42      { 
   43         "3b:fc:18:00:00:81:31:80:45:90:67:46:4a:00:64:18:14:00:00:00:00:02",
   44         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
   45         "EJAVA/PK-01C", SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C, 0, NULL },
   46     {
   47         "3b:7c:18:00:00:90:67:46:4a:20:28:8c:58:00:00:00:00",
   48         "ff:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff",
   49         "EJAVA/PK-01C-T0",SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0,0,NULL},
   50     {
   51         "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:21:28:8C:58:00:00:00:00:B7",
   52         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
   53         "EJAVA/H10CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1,0,NULL},
   54     {
   55         "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:20:25:c3:30:00:00:00:00",
   56         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:00:00:00:00",
   57         "EJAVA/D11CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1,0,NULL},
   58     {
   59         "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:00:6A:04:24:00:00:00:00:20",
   60         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
   61         "EJAVA/C21C/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1,0,NULL},
   62     {
   63         "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:00:68:08:04:00:00:00:00:0E",
   64         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
   65         "EJAVA/A22CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1,0,NULL},
   66     {
   67         "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:10:27:61:30:00:00:00:00:0C",
   68         "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
   69         "EJAVA/A40CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1,0,NULL},
   70     {
   71         "3b:fc:18:00:00:81:31:80:45:90:67:46:4a:00:68:08:06:00:00:00:00:0c",
   72         "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:00:00:00",
   73         "FTCOS/PK-01C", SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, 0, NULL },
   74     { NULL, NULL, NULL, 0, 0, NULL }
   75 };
   76 
   77 static struct sc_card_operations entersafe_ops;
   78 static struct sc_card_operations *iso_ops = NULL;
   79 
   80 static struct sc_card_driver entersafe_drv = {
   81     "entersafe",
   82     "entersafe",
   83     &entersafe_ops,
   84     NULL, 0, NULL
   85 };
   86 
   87 static u8 trans_code_3k[] =
   88 {
   89      0x01,0x02,0x03,0x04,
   90      0x05,0x06,0x07,0x08,
   91 };
   92 
   93 static u8 trans_code_ftcos_pk_01c[] =
   94 {
   95      0x92,0x34,0x2E,0xEF,
   96      0x23,0x40,0x4F,0xD1,
   97 };
   98 
   99 static u8 init_key[] =
  100 {
  101      1,  2,  3,  4, 
  102      5,  6,  7,  8, 
  103      9,  10, 11, 12, 
  104      13, 14, 15, 16,
  105 };
  106 
  107 static u8 key_maintain[] =
  108 {
  109      0x12, 0x34, 0x56, 0x78, 
  110      0x21, 0x43, 0x65, 0x87, 
  111      0x11, 0x22, 0xaa, 0xbb,
  112      0x33, 0x44, 0xcd, 0xef
  113 };
  114 
  115 static void entersafe_reverse_buffer(u8* buff,size_t size)
  116 {
  117      u8 t;
  118      u8 * end=buff+size-1;
  119 
  120      while(buff<end)
  121      {
  122           t = *buff;
  123           *buff = *end;
  124           *end=t;
  125           ++buff;
  126           --end;
  127      }
  128 }
  129 
  130 static int entersafe_select_file(sc_card_t *card,
  131                                  const sc_path_t *in_path,
  132                                  sc_file_t **file_out);
  133 
  134 /* the entersafe part */
  135 static int entersafe_match_card(sc_card_t *card)
  136 {
  137     int i;
  138     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  139 
  140     i = _sc_match_atr(card, entersafe_atrs, &card->type);
  141     if (i < 0)
  142         return 0;       
  143 
  144     return 1;
  145 }
  146 
  147 static int entersafe_init(sc_card_t *card)
  148 {
  149     unsigned int flags;
  150 
  151     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  152 
  153     card->name = "entersafe";
  154     card->cla  = 0x00;
  155     card->drv_data = NULL;
  156 
  157     flags =SC_ALGORITHM_ONBOARD_KEY_GEN
  158          | SC_ALGORITHM_RSA_RAW
  159          | SC_ALGORITHM_RSA_HASH_NONE;
  160 
  161     _sc_card_add_rsa_alg(card, 512, flags, 0);
  162     _sc_card_add_rsa_alg(card, 768, flags, 0);
  163     _sc_card_add_rsa_alg(card,1024, flags, 0);
  164     _sc_card_add_rsa_alg(card,2048, flags, 0);
  165 
  166     card->caps = SC_CARD_CAP_RNG; 
  167 
  168     /* we need read_binary&friends with max 224 bytes per read */
  169     card->max_send_size = 224;
  170     card->max_recv_size = 224;
  171     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
  172 }
  173 
  174 static int entersafe_gen_random(sc_card_t *card,u8 *buff,size_t size)
  175 {
  176      int r=SC_SUCCESS;
  177      u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]={0};
  178      sc_apdu_t apdu;
  179 
  180     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  181    
  182      sc_format_apdu(card,&apdu,SC_APDU_CASE_2_SHORT,0x84,0x00,0x00);
  183      apdu.resp=rbuf;
  184      apdu.le=size;
  185      apdu.resplen=sizeof(rbuf);
  186 
  187      r=sc_transmit_apdu(card,&apdu);
  188      LOG_TEST_RET(card->ctx, r, "entersafe gen random failed");
  189 
  190      if(apdu.resplen!=size)
  191           LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
  192      memcpy(buff,rbuf,size);
  193 
  194      LOG_FUNC_RETURN(card->ctx, r);
  195 }
  196 
  197 static int entersafe_cipher_apdu(sc_card_t *card, sc_apdu_t *apdu,
  198                                  u8 *key, size_t keylen,
  199                                  u8 *buff, size_t buffsize)
  200 {
  201      EVP_CIPHER_CTX * ctx = NULL;
  202      u8 iv[8]={0};
  203      int len;
  204 
  205     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  206 
  207      assert(card);
  208      assert(apdu);
  209      assert(key);
  210      assert(buff);
  211 
  212      /* padding as 0x80 0x00 0x00...... */
  213      memset(buff,0,buffsize);
  214      buff[0]=apdu->lc;
  215      memcpy(buff+1,apdu->data,apdu->lc);
  216      buff[apdu->lc+1]=0x80;
  217 
  218      ctx = EVP_CIPHER_CTX_new();
  219      if (ctx == NULL)
  220          LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
  221      EVP_CIPHER_CTX_set_padding(ctx,0);
  222 
  223      if(keylen == 8)
  224           EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, key, iv);
  225      else if (keylen == 16) 
  226           EVP_EncryptInit_ex(ctx, EVP_des_ede(), NULL, key, iv);
  227      else
  228           LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
  229      
  230      len = apdu->lc;
  231      if(!EVP_EncryptUpdate(ctx, buff, &len, buff, buffsize)){
  232           sc_log(card->ctx,  "entersafe encryption error.");
  233           LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
  234      }
  235      apdu->lc = len;
  236 
  237      EVP_CIPHER_CTX_free(ctx);
  238 
  239      if(apdu->lc!=buffsize)
  240      {
  241           sc_log(card->ctx,  "entersafe build cipher apdu failed.");
  242           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INTERNAL);
  243      }
  244 
  245      apdu->data=buff;
  246      apdu->datalen=apdu->lc;
  247 
  248      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
  249 }
  250 
  251 static int entersafe_mac_apdu(sc_card_t *card, sc_apdu_t *apdu,
  252                               u8 * key,size_t keylen,
  253                               u8 * buff,size_t buffsize)
  254 {
  255      int r;
  256      u8 iv[8];
  257      u8 *tmp=0,*tmp_rounded=NULL;
  258      size_t tmpsize=0,tmpsize_rounded=0;
  259      int outl=0;
  260      EVP_CIPHER_CTX * ctx = NULL;
  261 
  262     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  263 
  264      assert(card);
  265      assert(apdu);
  266      assert(key);
  267      assert(buff);
  268 
  269      if(apdu->cse != SC_APDU_CASE_3_SHORT)
  270           return SC_ERROR_INTERNAL;
  271      if(keylen!=8 && keylen!=16)
  272           return SC_ERROR_INTERNAL;
  273 
  274      r=entersafe_gen_random(card,iv,sizeof(iv));
  275      LOG_TEST_RET(card->ctx,r,"entersafe gen random failed");
  276 
  277      /* encode the APDU in the buffer */
  278      if ((r=sc_apdu_get_octets(card->ctx, apdu, &tmp, &tmpsize,SC_PROTO_RAW)) != SC_SUCCESS)
  279           goto out;
  280 
  281      /* round to 8 */
  282      tmpsize_rounded=(tmpsize/8+1)*8;
  283 
  284      tmp_rounded = malloc(tmpsize_rounded);
  285      if (tmp_rounded == NULL)
  286      {
  287           r =  SC_ERROR_OUT_OF_MEMORY;
  288           goto out;
  289      }
  290      
  291      /*build content and padded buffer by 0x80 0x00 0x00..... */
  292      memset(tmp_rounded,0,tmpsize_rounded);
  293      memcpy(tmp_rounded,tmp,tmpsize);
  294      tmp_rounded[4]+=4;
  295      tmp_rounded[tmpsize]=0x80;
  296 
  297      /* block_size-1 blocks*/
  298      ctx = EVP_CIPHER_CTX_new();
  299      if (ctx == NULL) {
  300         r =  SC_ERROR_OUT_OF_MEMORY;
  301         goto out;
  302      }
  303      EVP_CIPHER_CTX_set_padding(ctx,0);
  304      EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv);
  305 
  306      if(tmpsize_rounded>8){
  307           if(!EVP_EncryptUpdate(ctx,tmp_rounded,&outl,tmp_rounded,tmpsize_rounded-8)){
  308                r = SC_ERROR_INTERNAL;
  309                goto out;               
  310           }
  311      }
  312      /* last block */
  313      if(keylen==8)
  314      {
  315           if(!EVP_EncryptUpdate(ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
  316                r = SC_ERROR_INTERNAL;
  317                goto out;               
  318           }
  319      }
  320      else
  321      {
  322           EVP_EncryptInit_ex(ctx, EVP_des_ede_cbc(), NULL, key,tmp_rounded+outl-8);
  323           if(!EVP_EncryptUpdate(ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
  324                r = SC_ERROR_INTERNAL;
  325                goto out;               
  326           }
  327      }
  328 
  329      memcpy(buff,apdu->data,apdu->lc);
  330      /* use first 4 bytes of last block as mac value*/
  331      memcpy(buff+apdu->lc,tmp_rounded+tmpsize_rounded-8,4);
  332      apdu->data=buff;
  333      apdu->lc+=4;
  334      apdu->datalen=apdu->lc;
  335 
  336 out:
  337      if(tmp)
  338           free(tmp);
  339      if(tmp_rounded)
  340           free(tmp_rounded);
  341      if  (ctx)
  342         EVP_CIPHER_CTX_free(ctx);
  343 
  344      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
  345 }
  346 
  347 static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
  348                                    u8 * key, size_t keylen,
  349                                    int cipher,int mac)
  350 {
  351      u8 *cipher_data=0,*mac_data=0;
  352      size_t cipher_data_size,mac_data_size;
  353      int blocks;
  354      int r=SC_SUCCESS;
  355      u8 *sbuf=NULL;
  356      size_t ssize=0;
  357 
  358      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  359 
  360      assert(card);
  361      assert(apdu);
  362 
  363      if((cipher||mac) && (!key||(keylen!=8 && keylen!=16)))
  364           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  365 
  366      r = sc_apdu_get_octets(card->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
  367      if (r == SC_SUCCESS)
  368           sc_apdu_log(card->ctx, sbuf, ssize, 1);
  369      if(sbuf)
  370           free(sbuf);
  371 
  372      if(cipher)
  373      {
  374           blocks=(apdu->lc+2)/8+1;
  375           cipher_data_size=blocks*8;
  376           cipher_data=malloc(cipher_data_size);
  377           if(!cipher_data)
  378           {
  379                r = SC_ERROR_OUT_OF_MEMORY;
  380                goto out;
  381           }
  382 
  383           if((r = entersafe_cipher_apdu(card,apdu,key,keylen,cipher_data,cipher_data_size))<0)
  384                goto out;
  385      }
  386      if(mac)
  387      {   
  388           mac_data_size=apdu->lc+4;
  389           mac_data=malloc(mac_data_size);
  390           if(!mac_data)
  391           {
  392                r = SC_ERROR_OUT_OF_MEMORY;
  393                goto out;
  394           }
  395           r = entersafe_mac_apdu(card,apdu,key,keylen,mac_data,mac_data_size);
  396           if(r < 0)
  397                goto out;
  398      }
  399      
  400      r = sc_transmit_apdu(card,apdu);
  401 
  402 out:
  403      if(cipher_data)
  404           free(cipher_data);
  405      if(mac_data)
  406           free(mac_data);
  407 
  408      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
  409 }
  410 
  411 static int entersafe_read_binary(sc_card_t *card,
  412                                  unsigned int idx, u8 *buf, size_t count,
  413                                  unsigned long flags)
  414 {
  415     sc_apdu_t apdu;
  416     u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
  417     int r;
  418 
  419     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  420 
  421     assert(count <= card->max_recv_size);
  422     sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0,
  423                (idx >> 8) & 0xFF, idx & 0xFF);
  424 
  425     apdu.cla=idx > 0x7fff ? 0x80:0x00;
  426     apdu.le = count;
  427     apdu.resplen = count;
  428     apdu.resp = recvbuf;
  429 
  430     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
  431     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  432     if (apdu.resplen == 0)
  433         SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
  434     memcpy(buf, recvbuf, apdu.resplen);
  435 
  436     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen);
  437 }
  438 
  439 static int entersafe_update_binary(sc_card_t *card,
  440                                    unsigned int idx, const u8 *buf,
  441                                    size_t count, unsigned long flags)
  442 {
  443     sc_apdu_t apdu;
  444     int r;
  445 
  446     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  447 
  448     assert(count <= card->max_send_size);
  449 
  450     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
  451                (idx >> 8) & 0xFF, idx & 0xFF);
  452     apdu.cla=idx > 0x7fff ? 0x80:0x00;
  453     apdu.lc = count;
  454     apdu.datalen = count;
  455     apdu.data = buf;
  456 
  457     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
  458     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  459     LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
  460             "Card returned error");
  461     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
  462 }
  463 
  464 
  465 static int entersafe_process_fci(struct sc_card *card, struct sc_file *file,
  466                           const u8 *buf, size_t buflen)
  467 {
  468      int r;
  469 
  470      assert(file);
  471      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  472 
  473      r = iso_ops->process_fci(card,file,buf,buflen);
  474      LOG_TEST_RET(card->ctx, r, "Process fci failed");
  475 
  476      if(file->namelen)
  477      {
  478           file->type = SC_FILE_TYPE_DF;
  479           file->ef_structure = SC_FILE_EF_UNKNOWN;
  480      }
  481      else
  482      {
  483           file->type = SC_FILE_TYPE_WORKING_EF;
  484           file->ef_structure = SC_FILE_EF_TRANSPARENT;
  485      }
  486 
  487      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
  488 }
  489 
  490 static int entersafe_select_fid(sc_card_t *card,
  491                                 unsigned int id_hi, unsigned int id_lo,
  492                                 sc_file_t **file_out)
  493 {
  494     int r;
  495     sc_file_t *file = NULL;
  496     sc_path_t path;
  497 
  498     memset(&path, 0, sizeof(sc_path_t));
  499 
  500     path.type=SC_PATH_TYPE_FILE_ID;
  501     path.value[0]=id_hi;
  502     path.value[1]=id_lo;
  503     path.len=2;
  504 
  505     r = iso_ops->select_file(card,&path,&file);
  506     if (r < 0)
  507         sc_file_free(file);
  508     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  509 
  510     /* update cache */
  511     if (file->type == SC_FILE_TYPE_DF) {
  512          card->cache.current_path.type = SC_PATH_TYPE_PATH;
  513          card->cache.current_path.value[0] = 0x3f;
  514          card->cache.current_path.value[1] = 0x00;
  515          if (id_hi == 0x3f && id_lo == 0x00){
  516               card->cache.current_path.len = 2;
  517          } else {
  518               card->cache.current_path.len = 4;
  519               card->cache.current_path.value[2] = id_hi;
  520               card->cache.current_path.value[3] = id_lo;
  521          }
  522     }
  523     
  524     if (file_out)
  525         *file_out = file;
  526     else
  527         sc_file_free(file);
  528 
  529     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
  530 }
  531 
  532 static int entersafe_select_aid(sc_card_t *card,
  533                                 const sc_path_t *in_path,
  534                                 sc_file_t **file_out)
  535 {
  536     int r = 0;
  537 
  538     if (card->cache.valid 
  539         && card->cache.current_path.type == SC_PATH_TYPE_DF_NAME
  540         && card->cache.current_path.len == in_path->len
  541         && memcmp(card->cache.current_path.value, in_path->value, in_path->len)==0 )
  542     {
  543          if(file_out)
  544          {
  545               *file_out = sc_file_new();
  546               if(!file_out)
  547                    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
  548          }
  549     }
  550     else
  551     {
  552          r = iso_ops->select_file(card,in_path,file_out);
  553          LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  554 
  555          /* update cache */
  556          card->cache.current_path.type = SC_PATH_TYPE_DF_NAME;
  557          card->cache.current_path.len = in_path->len;
  558          memcpy(card->cache.current_path.value,in_path->value,in_path->len);
  559     }
  560     if (file_out) {
  561          sc_file_t *file = *file_out;
  562          assert(file);
  563 
  564          file->type = SC_FILE_TYPE_DF;
  565          file->ef_structure = SC_FILE_EF_UNKNOWN;
  566          file->path.len = 0;
  567          file->size = 0;
  568          /* AID */
  569          memcpy(file->name,in_path->value,in_path->len);
  570          file->namelen = in_path->len;
  571          file->id = 0x0000;
  572     }
  573     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
  574 }
  575 
  576 static int entersafe_select_path(sc_card_t *card,
  577                                 const u8 pathbuf[16], const size_t len,
  578                                 sc_file_t **file_out)
  579 {
  580      u8 n_pathbuf[SC_MAX_PATH_SIZE];
  581      const u8 *path=pathbuf;
  582      size_t pathlen=len;
  583      int bMatch = -1;
  584      unsigned int i;
  585      int r;
  586 
  587      if (pathlen%2 != 0 || pathlen > 6 || pathlen <= 0)
  588           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  589 
  590      /* if pathlen == 6 then the first FID must be MF (== 3F00) */
  591      if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
  592           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  593 
  594      /* unify path (the first FID should be MF) */
  595      if (path[0] != 0x3f || path[1] != 0x00)
  596      {
  597           n_pathbuf[0] = 0x3f;
  598           n_pathbuf[1] = 0x00;
  599           memcpy(n_pathbuf+2, path, pathlen);
  600           path = n_pathbuf;
  601           pathlen += 2; 
  602      }
  603     
  604      /* check current working directory */
  605      if (card->cache.valid 
  606          && card->cache.current_path.type == SC_PATH_TYPE_PATH
  607          && card->cache.current_path.len >= 2
  608          && card->cache.current_path.len <= pathlen )
  609      {
  610           bMatch = 0;
  611           for (i=0; i < card->cache.current_path.len; i+=2)
  612                if (card->cache.current_path.value[i] == path[i] 
  613                    && card->cache.current_path.value[i+1] == path[i+1] )
  614                     bMatch += 2;
  615      }
  616 
  617      if ( card->cache.valid && bMatch > 2 )
  618      {
  619           if ( pathlen - bMatch == 2 )
  620           {
  621                /* we are in the right directory */
  622                return entersafe_select_fid(card, path[bMatch], path[bMatch+1], file_out);
  623           }
  624           else if ( pathlen - bMatch > 2 )
  625           {
  626                /* two more steps to go */
  627                sc_path_t new_path;
  628     
  629                /* first step: change directory */
  630                r = entersafe_select_fid(card, path[bMatch], path[bMatch+1], NULL);
  631                LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
  632     
  633                memset(&new_path, 0, sizeof(sc_path_t));
  634 
  635                new_path.type = SC_PATH_TYPE_PATH;
  636                new_path.len  = pathlen - bMatch-2;
  637                memcpy(new_path.value, &(path[bMatch+2]), new_path.len);
  638                /* final step: select file */
  639                return entersafe_select_file(card, &new_path, file_out);
  640           }
  641           else /* if (bMatch - pathlen == 0) */
  642           {
  643                /* done: we are already in the
  644                 * requested directory */
  645                sc_log(card->ctx, 
  646                 "cache hit\n");
  647                /* copy file info (if necessary) */
  648                if (file_out) {
  649                     sc_file_t *file = sc_file_new();
  650                     if (!file)
  651                          LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
  652                     file->id = (path[pathlen-2] << 8) +
  653                          path[pathlen-1];
  654                     file->path = card->cache.current_path;
  655                     file->type = SC_FILE_TYPE_DF;
  656                     file->ef_structure = SC_FILE_EF_UNKNOWN;
  657                     file->size = 0;
  658                     file->namelen = 0;
  659                     file->magic = SC_FILE_MAGIC;
  660                     *file_out = file;
  661                }
  662                /* nothing left to do */
  663                return SC_SUCCESS;
  664           }
  665      }
  666      else
  667      {
  668           /* no usable cache */
  669           for ( i=0; i<pathlen-2; i+=2 )
  670           {
  671                r = entersafe_select_fid(card, path[i], path[i+1], NULL);
  672                LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
  673           }
  674           return entersafe_select_fid(card, path[pathlen-2], path[pathlen-1], file_out);
  675      }
  676 }
  677 
  678 static int entersafe_select_file(sc_card_t *card,
  679                                  const sc_path_t *in_path,
  680                                  sc_file_t **file_out)
  681 {
  682      int r;
  683      char pbuf[SC_MAX_PATH_STRING_SIZE];
  684      assert(card);
  685      assert(in_path);
  686      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  687 
  688 
  689       r = sc_path_print(pbuf, sizeof(pbuf), &card->cache.current_path);
  690       if (r != SC_SUCCESS)
  691          pbuf[0] = '\0';
  692 
  693       sc_log(card->ctx, 
  694            "current path (%s, %s): %s (len: %"SC_FORMAT_LEN_SIZE_T"u)\n",
  695            card->cache.current_path.type == SC_PATH_TYPE_DF_NAME ?
  696            "aid" : "path",
  697            card->cache.valid ? "valid" : "invalid", pbuf,
  698            card->cache.current_path.len);
  699 
  700      switch(in_path->type)
  701      {
  702      case SC_PATH_TYPE_FILE_ID:
  703           if (in_path->len != 2)
  704                SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS);
  705           return entersafe_select_fid(card,in_path->value[0],in_path->value[1], file_out);
  706      case SC_PATH_TYPE_DF_NAME:
  707           return entersafe_select_aid(card,in_path,file_out);
  708      case SC_PATH_TYPE_PATH:
  709           return entersafe_select_path(card,in_path->value,in_path->len,file_out);
  710      default:
  711           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  712      }
  713 }
  714 
  715 static int entersafe_create_mf(sc_card_t *card, sc_entersafe_create_data * data)
  716 {
  717     int r;
  718     sc_apdu_t apdu;
  719 
  720     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  721 
  722     memcpy(data->data.df.init_key, init_key, sizeof(init_key));
  723 
  724     sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x00,0x00);
  725     apdu.cla=0x84;
  726     apdu.data=(u8*)&data->data.df;
  727     apdu.datalen=apdu.lc=sizeof(data->data.df);
  728 
  729     switch(card->type)
  730     {
  731     case SC_CARD_TYPE_ENTERSAFE_3K:
  732     {
  733          r = entersafe_transmit_apdu(card, &apdu,trans_code_3k,sizeof(trans_code_3k),0,1);
  734     }break;
  735     case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C:
  736     case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C:
  737     case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0:    
  738     case SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1:
  739     case SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1:
  740     case SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1:
  741     case SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1:
  742     case SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1:  
  743     {
  744          r = entersafe_transmit_apdu(card, &apdu,trans_code_ftcos_pk_01c,sizeof(trans_code_ftcos_pk_01c),0,1);
  745     }break;
  746     default:
  747     {
  748          r = SC_ERROR_INTERNAL;
  749     }break;
  750     }
  751 
  752     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  753     return sc_check_sw(card, apdu.sw1, apdu.sw2);
  754 }
  755 static int entersafe_create_df(sc_card_t *card, sc_entersafe_create_data * data)
  756 {
  757     int r;
  758     sc_apdu_t apdu;
  759 
  760     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  761 
  762     memcpy(data->data.df.init_key, init_key, sizeof(init_key));
  763 
  764     sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x01,0x00);
  765     apdu.cla=0x84;
  766     apdu.data=(u8*)&data->data.df;
  767     apdu.lc=apdu.datalen=sizeof(data->data.df);
  768 
  769     r = entersafe_transmit_apdu(card, &apdu,init_key,sizeof(init_key),0,1);
  770     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  771     return sc_check_sw(card, apdu.sw1, apdu.sw2);
  772 }
  773 
  774 static int entersafe_create_ef(sc_card_t *card, sc_entersafe_create_data * data)
  775 {
  776     int r;
  777     sc_apdu_t apdu;
  778 
  779     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  780 
  781     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00);
  782     apdu.cla = 0x84;
  783     apdu.data = (u8*)&data->data.ef;
  784     apdu.lc = apdu.datalen = sizeof(data->data.ef);
  785 
  786     r = entersafe_transmit_apdu(card, &apdu,init_key,sizeof(init_key),0,1);
  787     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  788     return sc_check_sw(card, apdu.sw1, apdu.sw2);
  789 }
  790 
  791 static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def)
  792 {
  793     u8 def = (u8)in_def;
  794     const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method);
  795     if (!entry)
  796     {
  797         return def;
  798     }
  799     else if (entry->method & SC_AC_CHV)
  800     {
  801         unsigned int key_ref = entry->key_ref;
  802         if (key_ref == SC_AC_KEY_REF_NONE)
  803             return def;
  804         else
  805             return ENTERSAFE_AC_ALWAYS&0x04;
  806     }
  807     else if (entry->method & SC_AC_NEVER)
  808     {
  809         return ENTERSAFE_AC_NEVER;
  810     }
  811     else
  812     {
  813         return def;
  814     }
  815 }
  816 
  817 static int entersafe_create_file(sc_card_t *card, sc_file_t *file)
  818 {   
  819      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  820      
  821      if (file->type == SC_FILE_TYPE_WORKING_EF) {
  822           sc_entersafe_create_data data;
  823           memset(&data,0,sizeof(data));
  824 
  825           data.data.ef.file_id[0] = (file->id>>8)&0xFF; 
  826           data.data.ef.file_id[1] = file->id&0xFF;  
  827           data.data.ef.size[0] = (file->size>>8)&0xFF;
  828           data.data.ef.size[1] = file->size&0xFF;
  829           memset(data.data.ef.ac,ENTERSAFE_AC_ALWAYS,sizeof(data.data.ef.ac));
  830           data.data.ef.ac[0] = process_acl_entry(file,SC_AC_OP_READ,ENTERSAFE_AC_ALWAYS);
  831           data.data.ef.ac[1] = process_acl_entry(file,SC_AC_OP_UPDATE,ENTERSAFE_AC_ALWAYS);
  832 
  833           return entersafe_create_ef(card, &data);
  834      } else
  835           return SC_ERROR_INVALID_ARGUMENTS;
  836 }
  837 
  838 static int entersafe_internal_set_security_env(sc_card_t *card,
  839                                                const sc_security_env_t *env,
  840                                                u8 ** data,size_t* size)
  841 {
  842     sc_apdu_t apdu;
  843     u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
  844     u8 *p=sbuf;
  845     int r;
  846 
  847     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  848 
  849     assert(card != NULL && env != NULL);
  850     
  851     switch (env->operation) {
  852     case SC_SEC_OPERATION_DECIPHER:
  853     case SC_SEC_OPERATION_SIGN:
  854          sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
  855          apdu.p1 = 0x41;
  856          apdu.p2 = 0xB8;
  857          *p++ = 0x80;
  858          *p++ = 0x01;
  859          *p++ = 0x80;
  860          *p++ = 0x83;
  861          *p++ = 0x02;
  862          *p++ = env->key_ref[0];
  863          *p++ = 0x22;
  864          if(*size>1024/8)
  865          {
  866               if(*size == 2048/8)
  867               {
  868                    *p++ = 0x89;
  869                    *p++ = 0x40;
  870                    memcpy(p,*data,0x40);
  871                    p+=0x40;
  872                    *data+=0x40;
  873                    *size-=0x40;
  874               }
  875               else
  876               {
  877                    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  878               }
  879          }
  880          break;
  881     default:
  882          SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
  883     }
  884     
  885     apdu.le = 0;
  886     apdu.lc = apdu.datalen = p - sbuf;
  887     apdu.data = sbuf;
  888     apdu.resplen = 0;
  889 
  890     r = sc_transmit_apdu(card, &apdu);
  891     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  892     return sc_check_sw(card, apdu.sw1, apdu.sw2);
  893 }
  894 
  895 /**
  896  * We don't really set the security environment,but cache it.It will be set when
  897  * security operation is performed later.Because we may transport partial of
  898  * the sign/decipher data within the security environment apdu.
  899  */
  900 static int entersafe_set_security_env(sc_card_t *card,
  901                                       const sc_security_env_t *env,
  902                                       int se_num)
  903 {
  904      assert(card);
  905      assert(env);
  906 
  907      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  908 
  909      if(card->drv_data){
  910           free(card->drv_data);
  911           card->drv_data=0;
  912      }
  913 
  914      card->drv_data = calloc(1,sizeof(*env));
  915      if(!card->drv_data)
  916           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
  917 
  918      memcpy(card->drv_data,env,sizeof(*env));
  919      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
  920 }
  921 
  922 static int entersafe_restore_security_env(sc_card_t *card, int se_num)
  923 {
  924      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  925      return SC_SUCCESS;
  926 }
  927 
  928 
  929 static int entersafe_compute_with_prkey(sc_card_t *card,
  930                                         const u8 * data, size_t datalen,
  931                                         u8 * out, size_t outlen)
  932 {
  933     int r;
  934     sc_apdu_t apdu;
  935     u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
  936     u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
  937     u8* p=sbuf;
  938     size_t size = datalen;
  939 
  940     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  941 
  942     if(!data)
  943          SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS);
  944 
  945     memcpy(p,data,size);
  946 
  947     if(!card->drv_data)
  948          SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INTERNAL);
  949 
  950     r = entersafe_internal_set_security_env(card,card->drv_data,&p,&size);
  951     LOG_TEST_RET(card->ctx, r, "internal set security env failed");
  952    
  953     sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x86,0x80);
  954     apdu.data=p;
  955     apdu.lc = size;
  956     apdu.datalen = size;
  957     apdu.resp = rbuf;
  958     apdu.resplen = sizeof(rbuf);
  959     apdu.le = 256;
  960 
  961     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
  962     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
  963 
  964     if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
  965         size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
  966         memcpy(out, apdu.resp, len);
  967         SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
  968     }
  969     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
  970 }
  971 
  972 static int entersafe_compute_signature(sc_card_t *card,
  973                                        const u8 * data, size_t datalen,
  974                                        u8 * out, size_t outlen)
  975 {
  976      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  977      return entersafe_compute_with_prkey(card,data,datalen,out,outlen);
  978 }
  979 
  980 static int entersafe_decipher(sc_card_t *card,
  981                               const u8 * crgram, size_t crgram_len,
  982                               u8 * out, size_t outlen)
  983 {
  984      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
  985      return entersafe_compute_with_prkey(card,crgram,crgram_len,out,outlen);
  986 }
  987 
  988 static void entersafe_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
  989 {
  990     pin->encoding   = SC_PIN_ENCODING_ASCII;
  991     pin->min_length = 4;
  992     pin->max_length = 16;
  993     pin->pad_length = 16;
  994     pin->offset     = 5 + num * 16;
  995     pin->pad_char   = 0x00;
  996 }
  997 
  998 static int entersafe_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
  999                int *tries_left)
 1000 {
 1001      int r;
 1002      SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1003      entersafe_init_pin_info(&data->pin1,0);
 1004      entersafe_init_pin_info(&data->pin2,1);
 1005      data->flags |= SC_PIN_CMD_NEED_PADDING;
 1006 
 1007      if(data->cmd!=SC_PIN_CMD_UNBLOCK)
 1008      {
 1009           r = iso_ops->pin_cmd(card,data,tries_left);
 1010           sc_log(card->ctx,  "Verify rv:%i", r);
 1011      }
 1012      else
 1013      {
 1014           {/*verify*/
 1015                sc_apdu_t apdu;
 1016                u8 sbuf[0x10]={0};
 1017 
 1018                memcpy(sbuf,data->pin1.data,data->pin1.len);
 1019                sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,0x20,0x00,data->pin_reference+1);
 1020                apdu.lc = apdu.datalen = sizeof(sbuf);
 1021                apdu.data = sbuf;
 1022 
 1023                r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 1024                LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1025           }
 1026 
 1027           {/*change*/
 1028                sc_apdu_t apdu;
 1029                u8 sbuf[0x12]={0};
 1030                
 1031                sbuf[0] = 0x33;
 1032                sbuf[1] = 0x00;
 1033                memcpy(sbuf+2,data->pin2.data,data->pin2.len);
 1034                sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,0xF4,0x0B,data->pin_reference);
 1035                apdu.cla = 0x84;
 1036                apdu.lc = apdu.datalen = sizeof(sbuf);
 1037                apdu.data = sbuf;
 1038 
 1039                r = entersafe_transmit_apdu(card, &apdu,key_maintain,sizeof(key_maintain),1,1);
 1040                LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1041           }
 1042      }
 1043      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
 1044 }
 1045 
 1046 static int entersafe_erase_card(sc_card_t *card)
 1047 {
 1048     int r;
 1049     u8  sbuf[2];
 1050     sc_apdu_t apdu;
 1051 
 1052     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1053 
 1054     sbuf[0] = 0x3f;
 1055     sbuf[1] = 0x00;
 1056     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x00);
 1057     apdu.lc   = 2;
 1058     apdu.datalen = 2;
 1059     apdu.data = sbuf;
 1060     
 1061     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 1062     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1063     sc_invalidate_cache(card);
 1064 
 1065     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xEE, 0x00, 0x00);
 1066     apdu.cla=0x84;
 1067     apdu.lc=2;
 1068     apdu.datalen=2;
 1069     apdu.data=sbuf;
 1070 
 1071     switch(card->type)
 1072     {
 1073     case SC_CARD_TYPE_ENTERSAFE_3K:
 1074     {
 1075          r = entersafe_transmit_apdu(card, &apdu,trans_code_3k,sizeof(trans_code_3k),0,1);
 1076     }break;
 1077     case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C:
 1078     case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C:
 1079     case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0:        
 1080     case SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1:
 1081     case SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1:
 1082     case SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1:
 1083     case SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1:
 1084     case SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1:
 1085     {
 1086          r = entersafe_transmit_apdu(card, &apdu,trans_code_ftcos_pk_01c,sizeof(trans_code_ftcos_pk_01c),0,1);
 1087     }break;
 1088     default:
 1089     {
 1090          r = SC_ERROR_INTERNAL;
 1091     }break;
 1092     }
 1093 
 1094     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1095     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
 1096 }
 1097 
 1098 static void entersafe_encode_bignum(u8 tag,sc_pkcs15_bignum_t bignum,u8** ptr)
 1099 {
 1100      u8 *p=*ptr;
 1101 
 1102      *p++=tag;
 1103      if(bignum.len<128)
 1104      {
 1105           *p++=(u8)bignum.len;
 1106      }
 1107      else
 1108      {
 1109           u8 bytes=1;
 1110           size_t len=bignum.len;
 1111           while(len)
 1112           {
 1113                len=len>>8;
 1114                ++bytes;
 1115           }
 1116           bytes&=0x0F;
 1117           *p++=0x80|bytes;
 1118           while(bytes)
 1119           {
 1120                *p++=bignum.len>>((bytes-1)*8);
 1121                --bytes;
 1122           }
 1123      }
 1124      memcpy(p,bignum.data,bignum.len);
 1125      entersafe_reverse_buffer(p,bignum.len);
 1126      p+=bignum.len;
 1127      *ptr = p;
 1128 }
 1129 
 1130 static int entersafe_write_small_rsa_key(sc_card_t *card,u8 key_id,struct sc_pkcs15_prkey_rsa *rsa)
 1131 {
 1132      sc_apdu_t apdu;
 1133      u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
 1134      int r;
 1135      u8 *p=sbuff;
 1136 
 1137     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1138 
 1139      {/* write prkey */
 1140           *p++=0x00;            /* EC */
 1141           *p++=0x00;            /* ver */
 1142           entersafe_encode_bignum('E',rsa->exponent,&p);
 1143           entersafe_encode_bignum('D',rsa->d,&p);
 1144 
 1145           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF4,0x22,key_id);
 1146           apdu.cla=0x84;
 1147           apdu.data=sbuff;
 1148           apdu.lc=apdu.datalen=p-sbuff;
 1149 
 1150           r=entersafe_transmit_apdu(card,&apdu,key_maintain,sizeof(key_maintain),1,1);
 1151           LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1152           LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write prkey failed");
 1153      }
 1154 
 1155      p=sbuff;
 1156      {/* write pukey */
 1157           *p++=0x00;            /* EC */
 1158           *p++=0x00;            /* ver */
 1159           entersafe_encode_bignum('E',rsa->exponent,&p);
 1160           entersafe_encode_bignum('N',rsa->modulus,&p);
 1161 
 1162           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF4,0x2A,key_id);
 1163           apdu.cla=0x84;
 1164           apdu.data=sbuff;
 1165           apdu.lc=apdu.datalen=p-sbuff;
 1166 
 1167           r=entersafe_transmit_apdu(card,&apdu,key_maintain,sizeof(key_maintain),1,1);
 1168           LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1169           LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write pukey failed");
 1170      }
 1171 
 1172      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1173 }
 1174 
 1175 static int entersafe_write_rsa_key_factor(sc_card_t *card,
 1176                                           u8 key_id,u8 usage,
 1177                                           u8 factor,
 1178                                           sc_pkcs15_bignum_t data)
 1179 {
 1180     int r;
 1181     sc_apdu_t apdu;
 1182 
 1183     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1184 
 1185     {/* MSE */
 1186          u8 sbuff[4];
 1187          sbuff[0]=0x84;
 1188          sbuff[1]=0x02;
 1189          sbuff[2]=key_id;
 1190          sbuff[3]=usage;
 1191 
 1192          sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0x22,0x01,0xB8);
 1193          apdu.data=sbuff;
 1194          apdu.lc=apdu.datalen=4;
 1195          
 1196          r=entersafe_transmit_apdu(card,&apdu,0,0,0,0);
 1197          LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1198          LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write prkey factor failed(MSE)");
 1199     }
 1200 
 1201     {/* Write 'x'; */
 1202         u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
 1203 
 1204          sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0x46,factor,0x00);
 1205 
 1206          memcpy(sbuff,data.data,data.len);
 1207          entersafe_reverse_buffer(sbuff,data.len);
 1208 /*
 1209  *  PK01C and PK13C smart card only support 1024 or 2048bit key .
 1210  *  Size of exponent1 exponent2 coefficient of RSA private key keep the same as size of prime1
 1211  *  So check factor is padded with zero or not
 1212  */
 1213          switch(factor){
 1214              case 0x3:
 1215              case 0x4:
 1216              case 0x5:
 1217                  {
 1218                      if( data.len > 32 && data.len < 64 )
 1219                      {
 1220                          for(r = data.len ; r < 64 ; r ++)
 1221                              sbuff[r] = 0;
 1222                          data.len = 64;
 1223                      }
 1224                      else if( data.len > 64 && data.len < 128 )
 1225                      {
 1226                          for(r = data.len ; r < 128 ; r ++)
 1227                              sbuff[r] = 0;
 1228                          data.len = 128;
 1229                      }
 1230                  }
 1231                  break;
 1232              default:
 1233                  break;
 1234          }
 1235 
 1236          apdu.data=sbuff;
 1237          apdu.lc=apdu.datalen=data.len;
 1238 
 1239          r = entersafe_transmit_apdu(card,&apdu,0,0,0,0);
 1240          LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1241          LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write prkey factor failed");
 1242     }
 1243     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1244 }
 1245 
 1246 static int entersafe_write_large_rsa_key(sc_card_t *card,u8 key_id,struct sc_pkcs15_prkey_rsa *rsa)
 1247 {
 1248      int r;
 1249 
 1250     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1251 
 1252      {/* write prkey */
 1253           r = entersafe_write_rsa_key_factor(card,key_id,0x22,0x01,rsa->p);
 1254           LOG_TEST_RET(card->ctx, r, "write p failed");
 1255           r = entersafe_write_rsa_key_factor(card,key_id,0x22,0x02,rsa->q);
 1256           LOG_TEST_RET(card->ctx, r, "write q failed");
 1257           r = entersafe_write_rsa_key_factor(card,key_id,0x22,0x03,rsa->dmp1);
 1258           LOG_TEST_RET(card->ctx, r, "write dmp1 failed");
 1259           r = entersafe_write_rsa_key_factor(card,key_id,0x22,0x04,rsa->dmq1);
 1260           LOG_TEST_RET(card->ctx, r, "write dmq1 failed");
 1261           r = entersafe_write_rsa_key_factor(card,key_id,0x22,0x05,rsa->iqmp);
 1262           LOG_TEST_RET(card->ctx, r, "write iqmp failed");
 1263      }
 1264 
 1265      {/* write pukey */
 1266           u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
 1267           sc_apdu_t apdu;
 1268 
 1269           /* first 64(0x40) bytes of N */
 1270           sbuff[0]=0x83;
 1271           sbuff[1]=0x02;
 1272           sbuff[2]=key_id;
 1273           sbuff[3]=0x2A;
 1274           sbuff[4]=0x89;
 1275           sbuff[5]=0x40;
 1276           memcpy(sbuff+6,rsa->modulus.data,0x40);
 1277 
 1278           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0x22,0x01,0xB8);
 1279           apdu.data=sbuff;
 1280           apdu.lc=apdu.datalen=0x46;
 1281 
 1282           r=entersafe_transmit_apdu(card,&apdu,0,0,0,0);
 1283           LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1284           LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write pukey N(1) failed");
 1285 
 1286           /* left 192(0xC0) bytes of N */
 1287           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0x46,0x0B,0x00);
 1288           apdu.data=rsa->modulus.data+0x40;
 1289           apdu.lc=apdu.datalen=0xC0;
 1290 
 1291           r=entersafe_transmit_apdu(card,&apdu,0,0,0,0);
 1292           LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1293           LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write pukey N(2) failed");
 1294 
 1295           /* E */
 1296           r = entersafe_write_rsa_key_factor(card,key_id,0x2A,0x0D,rsa->exponent);
 1297           LOG_TEST_RET(card->ctx, r, "write exponent failed");
 1298      }
 1299     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1300 }
 1301 
 1302 static int entersafe_write_symmetric_key(sc_card_t *card,
 1303                                          u8 key_id,u8 usage,
 1304                                          u8 EC,u8 ver,
 1305                                          u8 *data,size_t len)
 1306 {
 1307      sc_apdu_t apdu;
 1308      u8 sbuff[SC_MAX_APDU_BUFFER_SIZE]={0};
 1309      int r;
 1310 
 1311     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1312 
 1313      if(len>240)
 1314           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INCORRECT_PARAMETERS);
 1315 
 1316      sbuff[0]=EC;
 1317      sbuff[1]=ver;
 1318      memcpy(&sbuff[2],data,len);
 1319 
 1320      sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF4,usage,key_id);
 1321      apdu.cla=0x84;
 1322      apdu.data=sbuff;
 1323      apdu.lc=apdu.datalen=len+2;
 1324 
 1325      r=entersafe_transmit_apdu(card,&apdu,key_maintain,sizeof(key_maintain),1,1);
 1326      LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1327      LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write prkey failed");
 1328      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,r);
 1329 }
 1330 
 1331 static int entersafe_write_key(sc_card_t *card, sc_entersafe_wkey_data *data)
 1332 {
 1333      struct sc_pkcs15_prkey_rsa* rsa=data->key_data.rsa;
 1334 
 1335     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1336 
 1337      switch(data->usage)
 1338      {
 1339      case 0x22:
 1340           if(rsa->modulus.len < 256)
 1341                return entersafe_write_small_rsa_key(card,data->key_id,rsa);
 1342           else
 1343                return entersafe_write_large_rsa_key(card,data->key_id,rsa);
 1344           break;
 1345      case 0x2A:
 1346           SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_NOT_SUPPORTED);
 1347           break;
 1348      default:
 1349           return entersafe_write_symmetric_key(card,data->key_id,data->usage,
 1350                                                data->key_data.symmetric.EC,
 1351                                                data->key_data.symmetric.ver,
 1352                                                data->key_data.symmetric.key_val,
 1353                                                data->key_data.symmetric.key_len);
 1354           break;
 1355      }
 1356      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1357 }
 1358 
 1359 static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
 1360 {
 1361     int r;
 1362     size_t len = data->key_length >> 3;
 1363     sc_apdu_t apdu;
 1364     u8 rbuf[300];
 1365     u8 sbuf[4],*p;
 1366 
 1367     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1368 
 1369     /* MSE */
 1370     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x01, 0xB8);
 1371     apdu.lc=0x04;
 1372     sbuf[0]=0x83;
 1373     sbuf[1]=0x02;
 1374     sbuf[2]=data->key_id;
 1375     sbuf[3]=0x2A;
 1376     apdu.data = sbuf;
 1377     apdu.datalen=4;
 1378     apdu.lc=4;
 1379     apdu.le=0;
 1380 
 1381     r=entersafe_transmit_apdu(card, &apdu, 0,0,0,0);
 1382     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1383     LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe set MSE failed");
 1384 
 1385     /* generate key */
 1386     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46,  0x00, 0x00);
 1387     apdu.le      = 0;
 1388     sbuf[0] = (u8)(data->key_length >> 8);
 1389     sbuf[1] = (u8)(data->key_length);
 1390     apdu.data    = sbuf;
 1391     apdu.lc      = 2;
 1392     apdu.datalen = 2;
 1393 
 1394     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 1395     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1396     LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe generate key pair failed");
 1397 
 1398     /* read public key via READ PUBLIC KEY */
 1399     sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xE6,  0x2A, data->key_id);
 1400     apdu.cla     = 0x80;
 1401     apdu.resp    = rbuf;
 1402     apdu.resplen = sizeof(rbuf);
 1403     apdu.le      = 256;
 1404     r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 1405     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1406     LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get pukey failed");
 1407 
 1408     data->modulus = malloc(len);
 1409     if (!data->modulus)
 1410         SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
 1411 
 1412     p=rbuf;
 1413     if (*p!='E')
 1414         SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
 1415     p+=2+p[1];
 1416     /* N */
 1417     if (*p!='N')
 1418         SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
 1419     ++p;
 1420     if(*p++>0x80)
 1421     {
 1422          u8 len_bytes=(*(p-1))&0x0f;
 1423          size_t module_len=0;
 1424          while(len_bytes!=0)
 1425          {
 1426               module_len=module_len<<8;
 1427               module_len+=*p++;
 1428               --len_bytes;
 1429          }
 1430     }
 1431 
 1432     entersafe_reverse_buffer(p,len);
 1433     memcpy(data->modulus,p,len);
 1434 
 1435     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1436 }
 1437 
 1438 static int entersafe_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
 1439 {
 1440     int r;
 1441     sc_apdu_t apdu;
 1442     u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
 1443 
 1444     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1445     assert(serial);
 1446 
 1447     sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT,0xEA,0x00,0x00);
 1448     apdu.cla=0x80;
 1449     apdu.resp=rbuf;
 1450     apdu.resplen=sizeof(rbuf);
 1451     apdu.le=0x08;
 1452 
 1453     r=entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 1454     LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 1455     LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get SN failed");
 1456 
 1457     card->serialnr.len=serial->len=8;
 1458     memcpy(card->serialnr.value,rbuf,8);
 1459     memcpy(serial->value,rbuf,8);
 1460 
 1461     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1462 }
 1463 
 1464 static int entersafe_preinstall_rsa_2048(sc_card_t *card,u8 key_id)
 1465 {
 1466     u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
 1467     sc_apdu_t apdu;
 1468     int ret=0;
 1469     static u8 const rsa_key_e[] =
 1470     {
 1471         'E', 0x04, 0x01, 0x00, 0x01, 0x00
 1472     };
 1473 
 1474     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1475 
 1476     /*  create rsa item in IKF */
 1477     sbuf[0] = 0x04; /* key len extern */
 1478     sbuf[1] = 0x0a; /* key len */
 1479     sbuf[2] = 0x22; /* USAGE */
 1480     sbuf[3] = 0x34; /* user ac */
 1481     sbuf[4] = 0x04; /* change ac */
 1482     sbuf[5] = 0x34; /* UPDATE AC */
 1483     sbuf[6] = 0x40; /* ALGO */
 1484     sbuf[7] = 0x00; /* EC */
 1485     sbuf[8] = 0x00; /* VER */
 1486     memcpy(&sbuf[9], rsa_key_e, sizeof(rsa_key_e));
 1487     sbuf[9 + sizeof(rsa_key_e) + 0] = 'C'+'R'+'T';
 1488     sbuf[9 + sizeof(rsa_key_e) + 1] = 0x82;
 1489     sbuf[9 + sizeof(rsa_key_e) + 2] = 0x04;
 1490     sbuf[9 + sizeof(rsa_key_e) + 3] = 0x00;
 1491 
 1492     sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,0xF0,0x00,key_id);
 1493     apdu.cla=0x84;
 1494     apdu.data=sbuf;
 1495     apdu.lc=apdu.datalen=9 + sizeof(rsa_key_e) + 4;
 1496 
 1497     ret = entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1);
 1498     LOG_TEST_RET(card->ctx, ret, "Preinstall rsa failed");
 1499 
 1500     /*  create rsa item in PKF */
 1501     sbuf[0] = 0x01; /* key len extern */
 1502     sbuf[1] = 0x0A; /* key len */
 1503     sbuf[2] = 0x2A; /* USAGE */
 1504     sbuf[3] = ENTERSAFE_AC_ALWAYS;  /* user ac */
 1505     sbuf[4] = 0x04; /* change ac */
 1506     sbuf[5] = ENTERSAFE_AC_ALWAYS;  /* UPDATE AC */
 1507     sbuf[6] = 0x40; /* ALGO */
 1508     sbuf[7] = 0x00; /* EC */
 1509     sbuf[8] = 0x00; /* VER */
 1510     memcpy(&sbuf[9], rsa_key_e, sizeof(rsa_key_e));     
 1511     sbuf[9 + sizeof(rsa_key_e) + 0] = 'N';
 1512     sbuf[9 + sizeof(rsa_key_e) + 1] = 0x82;
 1513     sbuf[9 + sizeof(rsa_key_e) + 2] = 0x01;
 1514     sbuf[9 + sizeof(rsa_key_e) + 3] = 0x00;
 1515 
 1516     sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF0,0x00,key_id);
 1517     apdu.cla=0x84;
 1518     apdu.data=sbuf;
 1519     apdu.lc=apdu.datalen=9 + sizeof(rsa_key_e) + 4;
 1520 
 1521     ret=entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1);
 1522     LOG_TEST_RET(card->ctx, ret, "Preinstall rsa failed");
 1523 
 1524     SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1525 }
 1526 
 1527 static int entersafe_preinstall_keys(sc_card_t *card,int (*install_rsa)(sc_card_t *,u8))
 1528 {
 1529      int r;
 1530      u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
 1531      sc_apdu_t apdu;
 1532 
 1533     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1534 
 1535      {/* RSA */
 1536           u8 rsa_index;
 1537           for(rsa_index=ENTERSAFE_MIN_KEY_ID;
 1538               rsa_index<=ENTERSAFE_MAX_KEY_ID;
 1539               ++rsa_index)
 1540           {
 1541                r=install_rsa(card,rsa_index);
 1542                LOG_TEST_RET(card->ctx, r, "Preinstall rsa key failed");
 1543           }
 1544      }
 1545 
 1546      {/* key maintain */
 1547           /* create key maintain*/
 1548           sbuf[0] = 0;  /* key len extern */
 1549           sbuf[1] = sizeof(key_maintain);   /* key len */
 1550           sbuf[2] = 0x03;   /* USAGE */
 1551           sbuf[3] = ENTERSAFE_AC_ALWAYS;    /* use AC   */
 1552           sbuf[4] = ENTERSAFE_AC_ALWAYS;    /* CHANGE AC */
 1553           sbuf[5] = ENTERSAFE_AC_NEVER; /* UPDATE AC */
 1554           sbuf[6] = 0x01;   /* ALGO */
 1555           sbuf[7] = 0x00;   /* EC */
 1556           sbuf[8] = 0x00;   /* VER */
 1557           memcpy(&sbuf[9], key_maintain, sizeof(key_maintain));
 1558 
 1559           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF0,0x00,0x00);
 1560           apdu.cla=0x84;
 1561           apdu.data=sbuf;
 1562           apdu.lc=apdu.datalen=0x19;
 1563 
 1564           r = entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1);
 1565           LOG_TEST_RET(card->ctx, r, "Preinstall key maintain failed");
 1566      }
 1567 
 1568      {/* user PIN */
 1569           memset(sbuf,0,sizeof(sbuf));
 1570           sbuf[0] = 0;  /* key len extern */
 1571           sbuf[1] = 16; /* key len */
 1572           sbuf[2] = 0x0B;   /* USAGE */
 1573           sbuf[3] = ENTERSAFE_AC_ALWAYS;    /* use AC */
 1574           sbuf[4] = 0X04;   /* CHANGE AC */
 1575           sbuf[5] = 0x38;   /* UPDATE AC */
 1576           sbuf[6] = 0x01;   /* ALGO */
 1577           sbuf[7] = 0xFF;   /* EC */
 1578           sbuf[8] = 0x00;   /* VER */
 1579 
 1580           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF0,0x00,ENTERSAFE_USER_PIN_ID);
 1581           apdu.cla=0x84;
 1582           apdu.data=sbuf;
 1583           apdu.lc=apdu.datalen=0x19;
 1584 
 1585           r = entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1);
 1586           LOG_TEST_RET(card->ctx, r, "Preinstall user PIN failed");
 1587      }
 1588 
 1589      {/* user PUK */
 1590           memset(sbuf,0,sizeof(sbuf));
 1591           sbuf[0] = 0;  /* key len extern */
 1592           sbuf[1] = 16; /* key len */
 1593           sbuf[2] = 0x0B;   /* USAGE */
 1594           sbuf[3] = ENTERSAFE_AC_ALWAYS;    /* use AC */
 1595           sbuf[4] = 0X08;   /* CHANGE AC */
 1596           sbuf[5] = 0xC0;   /* UPDATE AC */
 1597           sbuf[6] = 0x01;   /* ALGO */
 1598           sbuf[7] = 0xFF;   /* EC */
 1599           sbuf[8] = 0x00;   /* VER */
 1600 
 1601           sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF0,0x00,ENTERSAFE_USER_PIN_ID+1);
 1602           apdu.cla=0x84;
 1603           apdu.data=sbuf;
 1604           apdu.lc=apdu.datalen=0x19;
 1605 
 1606           r = entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1);
 1607           LOG_TEST_RET(card->ctx, r, "Preinstall user PUK failed");
 1608      }
 1609 
 1610 
 1611      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
 1612 }
 1613 
 1614 static int entersafe_card_ctl_2048(sc_card_t *card, unsigned long cmd, void *ptr)
 1615 {
 1616     sc_entersafe_create_data *tmp = (sc_entersafe_create_data *)ptr;
 1617 
 1618     SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 1619 
 1620     switch (cmd)
 1621     {
 1622     case SC_CARDCTL_ENTERSAFE_CREATE_FILE:
 1623         if (tmp->type == SC_ENTERSAFE_MF_DATA)
 1624             return entersafe_create_mf(card, tmp);
 1625         else if (tmp->type == SC_ENTERSAFE_DF_DATA)
 1626             return entersafe_create_df(card, tmp);
 1627         else if (tmp->type == SC_ENTERSAFE_EF_DATA)
 1628             return entersafe_create_ef(card, tmp);
 1629         else
 1630             return SC_ERROR_INTERNAL;
 1631     case SC_CARDCTL_ENTERSAFE_WRITE_KEY:
 1632         return entersafe_write_key(card, (sc_entersafe_wkey_data *)ptr);
 1633     case SC_CARDCTL_ENTERSAFE_GENERATE_KEY:
 1634         return entersafe_gen_key(card, (sc_entersafe_gen_key_data *)ptr);
 1635     case SC_CARDCTL_ERASE_CARD:
 1636         return entersafe_erase_card(card);
 1637     case SC_CARDCTL_GET_SERIALNR:
 1638         return entersafe_get_serialnr(card, (sc_serial_number_t *)ptr);
 1639     case SC_CARDCTL_ENTERSAFE_PREINSTALL_KEYS:
 1640          return entersafe_preinstall_keys(card,entersafe_preinstall_rsa_2048);
 1641     default:
 1642         return SC_ERROR_NOT_SUPPORTED;
 1643     }
 1644 }
 1645 
 1646 static struct sc_card_driver * sc_get_driver(void)
 1647 {
 1648     struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
 1649 
 1650     if (iso_ops == NULL)
 1651         iso_ops = iso_drv->ops;
 1652   
 1653     entersafe_ops = *iso_drv->ops;
 1654     entersafe_ops.match_card = entersafe_match_card;
 1655     entersafe_ops.init   = entersafe_init;
 1656     entersafe_ops.read_binary = entersafe_read_binary;
 1657     entersafe_ops.write_binary = NULL;
 1658     entersafe_ops.update_binary = entersafe_update_binary;
 1659     entersafe_ops.select_file = entersafe_select_file;
 1660     entersafe_ops.restore_security_env = entersafe_restore_security_env;
 1661     entersafe_ops.set_security_env  = entersafe_set_security_env;
 1662     entersafe_ops.decipher = entersafe_decipher;
 1663     entersafe_ops.compute_signature = entersafe_compute_signature;
 1664     entersafe_ops.create_file = entersafe_create_file;
 1665     entersafe_ops.delete_file = NULL;
 1666     entersafe_ops.pin_cmd = entersafe_pin_cmd;
 1667     entersafe_ops.card_ctl    = entersafe_card_ctl_2048;
 1668     entersafe_ops.process_fci = entersafe_process_fci;
 1669     return &entersafe_drv;
 1670 }
 1671 
 1672 struct sc_card_driver * sc_get_entersafe_driver(void)
 1673 {
 1674     return sc_get_driver();
 1675 }
 1676 #endif