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

Revision 3594, 41.7 KB (checked in by martin, 9 days ago)

typos

Line 
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#include "internal.h"
20#include "asn1.h"
21#include "cardctl.h"
22#include <stdlib.h>
23#include <string.h>
24
25#ifdef ENABLE_OPENSSL
26#include <openssl/evp.h>
27
28static struct sc_atr_table entersafe_atrs[] = {
29        {
30                 "3b:0f:00:65:46:53:05:19:05:71:df:00:00:00:00:00:00",
31                 "ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff:00:00:00:00:00:00",
32                 "ePass3000", SC_CARD_TYPE_ENTERSAFE_3K, 0, NULL },
33        { NULL, NULL, NULL, 0, 0, NULL }
34};
35
36static struct sc_card_operations entersafe_ops;
37static struct sc_card_operations *iso_ops = NULL;
38
39static struct sc_card_driver entersafe_drv = {
40        "entersafe",
41        "entersafe",
42        &entersafe_ops,
43        NULL, 0, NULL
44};
45
46static u8 trans_code[] =
47{
48         0x01,0x02,0x03,0x04,
49         0x05,0x06,0x07,0x08,
50};
51
52static u8 init_key[] =
53{
54         1,  2,  3,  4,
55         5,  6,  7,  8,
56         9,  10, 11, 12,
57         13, 14, 15, 16,
58};
59
60static u8 key_maintain[] =
61{
62         0x12, 0x34, 0x56, 0x78,
63         0x21, 0x43, 0x65, 0x87,
64         0x11, 0x22, 0xaa, 0xbb,
65         0x33, 0x44, 0xcd, 0xef
66};
67
68static void entersafe_reverse_buffer(u8* buff,size_t size)
69{
70         u8 t;
71         u8 * end=buff+size-1;
72
73         while(buff<end)
74         {
75                  t = *buff;
76                  *buff = *end;
77                  *end=t;
78                  ++buff;
79                  --end;
80         }
81}
82
83static int entersafe_select_file(sc_card_t *card,
84                                                                 const sc_path_t *in_path,
85                                                                 sc_file_t **file_out);
86
87/* the entersafe part */
88static int entersafe_match_card(sc_card_t *card)
89{
90        int i;
91        SC_FUNC_CALLED(card->ctx, 1);
92
93        i = _sc_match_atr(card, entersafe_atrs, &card->type);
94        if (i < 0)
95                return 0;               
96
97        return 1;
98}
99
100static int entersafe_init(sc_card_t *card)
101{
102        unsigned int flags;
103
104        SC_FUNC_CALLED(card->ctx, 1);
105
106        card->name = "entersafe";
107        card->cla  = 0x00;
108        /*card->drv_data = NULL;*/
109
110        flags =SC_ALGORITHM_ONBOARD_KEY_GEN
111                 | SC_ALGORITHM_RSA_RAW
112                 | SC_ALGORITHM_RSA_HASH_NONE;
113
114       
115
116        _sc_card_add_rsa_alg(card, 512, flags, 0x10001);
117        _sc_card_add_rsa_alg(card, 768, flags, 0x10001);
118        _sc_card_add_rsa_alg(card,1024, flags, 0x10001);
119        _sc_card_add_rsa_alg(card,2048, flags, 0x10001);
120
121        card->caps = SC_CARD_CAP_RNG;
122        card->drv_data = 0;
123
124        /* we need read_binary&friends with max 224 bytes per read */
125        if (card->max_send_size > 0xE0)
126                card->max_send_size = 0xE0;
127        if (card->max_recv_size > 0xE0)
128                card->max_recv_size = 0xE0;
129        SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
130}
131
132static int entersafe_gen_random(sc_card_t *card,u8 *buff,size_t size)
133{
134         int r=SC_SUCCESS;
135         u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]={0};
136         sc_apdu_t apdu;
137
138        SC_FUNC_CALLED(card->ctx, 1);
139   
140         sc_format_apdu(card,&apdu,SC_APDU_CASE_2_SHORT,0x84,0x00,0x00);
141         apdu.resp=rbuf;
142         apdu.le=size;
143         apdu.resplen=sizeof(rbuf);
144
145         r=sc_transmit_apdu(card,&apdu);
146         SC_TEST_RET(card->ctx, r, "entersafe gen random failed");
147
148         if(apdu.resplen!=size)
149                  SC_FUNC_RETURN(card->ctx,1,SC_ERROR_INTERNAL);
150         memcpy(buff,rbuf,size);
151
152         SC_FUNC_RETURN(card->ctx,1,r);
153}
154
155static int entersafe_cipher_apdu(sc_card_t *card, sc_apdu_t *apdu,
156                                                                 u8 *key, size_t keylen,
157                                                                 u8 *buff, size_t buffsize)
158{
159         EVP_CIPHER_CTX ctx;
160         int i,r;
161         u8 iv[8]={0};
162
163        SC_FUNC_CALLED(card->ctx, 1);
164
165         assert(card);
166         assert(apdu);
167         assert(key);
168         assert(buff);
169
170         /* padding as 0x80 0x00 0x00...... */
171         memset(buff,0,buffsize);
172         buff[0]=apdu->lc;
173         memcpy(buff+1,apdu->data,apdu->lc);
174         buff[apdu->lc+1]=0x80;
175
176         EVP_CIPHER_CTX_init(&ctx);
177         EVP_CIPHER_CTX_set_padding(&ctx,0);
178
179         if(keylen == 8)
180                  EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, key, iv);
181         else if (keylen == 16)
182                  EVP_EncryptInit_ex(&ctx, EVP_des_ede(), NULL, key, iv);
183         else
184                  SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
185         
186         if(!EVP_EncryptUpdate(&ctx,buff,&apdu->lc,buff,buffsize)){
187                  sc_error(card->ctx, "entersafe encryption error.");
188                  SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
189         }
190
191         if (!EVP_CIPHER_CTX_cleanup(&ctx)){
192                  sc_error(card->ctx, "entersafe encryption error.");
193                  SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
194         }
195
196         if(apdu->lc!=buffsize)
197         {
198                  sc_error(card->ctx, "entersafe build cipher apdu failed.");
199                  SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_INTERNAL);
200         }
201
202         apdu->data=buff;
203         apdu->datalen=apdu->lc;
204
205         SC_FUNC_RETURN(card->ctx, 3, SC_SUCCESS);
206}
207
208static int entersafe_mac_apdu(sc_card_t *card, sc_apdu_t *apdu,
209                                                          u8 * key,size_t keylen,
210                                                          u8 * buff,size_t buffsize)
211{
212         int r;
213         u8 iv[8];
214         u8 *tmp=0,*tmp_rounded;
215         size_t tmpsize=0,tmpsize_rounded=0,outl=0;
216         EVP_CIPHER_CTX ctx;
217
218        SC_FUNC_CALLED(card->ctx, 1);
219
220         assert(card);
221         assert(apdu);
222         assert(key);
223         assert(buff);
224
225         if(apdu->cse != SC_APDU_CASE_3_SHORT)
226                  return SC_ERROR_INTERNAL;
227         if(keylen!=8 && keylen!=16)
228                  return SC_ERROR_INTERNAL;
229
230         r=entersafe_gen_random(card,iv,sizeof(iv));
231         SC_TEST_RET(card->ctx,r,"entersafe gen random failed");
232
233         /* encode the APDU in the buffer */
234         if ((r=sc_apdu_get_octets(card->ctx, apdu, &tmp, &tmpsize,SC_PROTO_RAW)) != SC_SUCCESS)
235                  goto out;
236
237         /* round to 8 */
238         tmpsize_rounded=(tmpsize/8+1)*8;
239
240         tmp_rounded = malloc(tmpsize_rounded);
241         if (tmp_rounded == NULL)
242         {
243                  r =  SC_ERROR_MEMORY_FAILURE;
244                  goto out;
245         }
246         
247         /*build content and padded buffer by 0x80 0x00 0x00..... */
248         memset(tmp_rounded,0,tmpsize_rounded);
249         memcpy(tmp_rounded,tmp,tmpsize);
250         tmp_rounded[4]+=4;
251         tmp_rounded[tmpsize]=0x80;
252
253         /* block_size-1 blocks*/
254         EVP_CIPHER_CTX_init(&ctx);
255         EVP_CIPHER_CTX_set_padding(&ctx,0);
256         EVP_EncryptInit_ex(&ctx, EVP_des_cbc(), NULL, key, iv);
257
258         if(tmpsize_rounded>8){
259                  if(!EVP_EncryptUpdate(&ctx,tmp_rounded,&outl,tmp_rounded,tmpsize_rounded-8)){
260                           r = SC_ERROR_INTERNAL;
261                           goto out;                       
262                  }
263         }
264         /* last block */
265         if(keylen==8)
266         {
267                  if(!EVP_EncryptUpdate(&ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
268                           r = SC_ERROR_INTERNAL;
269                           goto out;                       
270                  }
271         }
272         else
273         {
274                  EVP_EncryptInit_ex(&ctx, EVP_des_ede_cbc(), NULL, key,tmp_rounded+outl-8);
275                  if(!EVP_EncryptUpdate(&ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
276                           r = SC_ERROR_INTERNAL;
277                           goto out;                       
278                  }
279         }
280
281         if (!EVP_CIPHER_CTX_cleanup(&ctx)){
282                  r = SC_ERROR_INTERNAL;
283                  goto out;                       
284         }
285
286         memcpy(buff,apdu->data,apdu->lc);
287         /* use first 4 bytes of last block as mac value*/
288         memcpy(buff+apdu->lc,tmp_rounded+tmpsize_rounded-8,4);
289         apdu->data=buff;
290         apdu->lc+=4;
291         apdu->datalen=apdu->lc;
292
293out:
294         if(tmp)
295                  free(tmp);
296         if(tmp_rounded)
297                  free(tmp_rounded);
298
299         SC_FUNC_RETURN(card->ctx, 3, r);
300}
301
302static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
303                                                                   u8 * key, size_t keylen,
304                                                                   int cipher,int mac)
305{
306         u8 *cipher_data=0,*mac_data=0;
307         size_t cipher_data_size,mac_data_size;
308         int blocks;
309         int r=SC_SUCCESS;
310
311        SC_FUNC_CALLED(card->ctx, 1);
312
313         assert(card);
314         assert(apdu);
315
316         if((cipher||mac) && (!key||(keylen!=8 && keylen!=16)))
317                  SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_INVALID_ARGUMENTS);
318
319        if (card->ctx->debug >= 6)
320        {
321                 u8 *sbuf=NULL;
322                 size_t ssize=0;
323                 r = sc_apdu_get_octets(card->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
324                 if (r == SC_SUCCESS)
325                          sc_apdu_log(card->ctx, sbuf, ssize, 1);
326                 free(sbuf);
327        }
328
329         if(cipher)
330         {
331                  blocks=(apdu->lc+2)/8+1;
332                  cipher_data_size=blocks*8;
333                  cipher_data=malloc(cipher_data_size);
334                  if(!cipher)
335                  {
336                           r = SC_ERROR_OUT_OF_MEMORY;
337                           goto out;
338                  }
339
340                  if((r = entersafe_cipher_apdu(card,apdu,key,keylen,cipher_data,cipher_data_size))<0)
341                           goto out;
342         }
343         if(mac)
344         {       
345                  mac_data_size=apdu->lc+4;
346                  mac_data=malloc(mac_data_size);
347                  r = entersafe_mac_apdu(card,apdu,key,keylen,mac_data,mac_data_size);
348                  if(r<0)
349                           goto out;
350         }
351         
352         r = sc_transmit_apdu(card,apdu);
353
354out:
355         if(cipher_data)
356                  free(cipher_data);
357         if(mac_data)
358                  free(mac_data);
359
360         SC_FUNC_RETURN(card->ctx, 3, r);
361}
362
363static int entersafe_read_binary(sc_card_t *card,
364                                                                 unsigned int idx, u8 *buf, size_t count,
365                                                                 unsigned long flags)
366{
367        sc_apdu_t apdu;
368        u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
369        int r;
370
371        SC_FUNC_CALLED(card->ctx, 1);
372
373        assert(count <= card->max_recv_size);
374        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0,
375                       (idx >> 8) & 0xFF, idx & 0xFF);
376
377        apdu.cla=idx > 0x7fff ? 0x80:0x00;
378        apdu.le = count;
379        apdu.resplen = count;
380        apdu.resp = recvbuf;
381
382        r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
383        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
384        if (apdu.resplen == 0)
385                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
386        memcpy(buf, recvbuf, apdu.resplen);
387
388        SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
389}
390
391static int entersafe_update_binary(sc_card_t *card,
392                                                                   unsigned int idx, const u8 *buf,
393                                                                   size_t count, unsigned long flags)
394{
395        sc_apdu_t apdu;
396        int r;
397
398        SC_FUNC_CALLED(card->ctx, 1);
399
400        assert(count <= card->max_send_size);
401
402        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
403                       (idx >> 8) & 0xFF, idx & 0xFF);
404        apdu.cla=idx > 0x7fff ? 0x80:0x00;
405        apdu.lc = count;
406        apdu.datalen = count;
407        apdu.data = buf;
408
409        r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
410        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
411        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
412                    "Card returned error");
413        SC_FUNC_RETURN(card->ctx, 3, count);
414}
415
416
417static int entersafe_process_fci(struct sc_card *card, struct sc_file *file,
418                                                  const u8 *buf, size_t buflen)
419{
420         int r;
421         const u8 *tag = NULL, *p = buf;
422         size_t taglen, len = buflen;
423
424         assert(file);
425         SC_FUNC_CALLED(card->ctx, 1);
426
427         r = iso_ops->process_fci(card,file,buf,buflen);
428         SC_TEST_RET(card->ctx, r, "Process fci failed");
429
430         if(file->namelen)
431         {
432                  file->type = SC_FILE_TYPE_DF;
433                  file->ef_structure = SC_FILE_EF_UNKNOWN;
434         }
435         else
436         {
437                  file->type = SC_FILE_TYPE_WORKING_EF;
438                  file->ef_structure = SC_FILE_EF_TRANSPARENT;
439         }
440
441         SC_FUNC_RETURN(card->ctx, 4, r);
442}
443
444static int entersafe_select_fid(sc_card_t *card,
445                                                                unsigned int id_hi, unsigned int id_lo,
446                                                                sc_file_t **file_out)
447{
448        int r;
449        sc_file_t *file=0;
450        sc_path_t path;
451
452        path.type=SC_PATH_TYPE_FILE_ID;
453        path.value[0]=id_hi;
454        path.value[1]=id_lo;
455        path.len=2;
456
457        r = iso_ops->select_file(card,&path,&file);
458        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
459
460        /* update cache */
461        if (file->type == SC_FILE_TYPE_DF) {
462                 card->cache.current_path.type = SC_PATH_TYPE_PATH;
463                 card->cache.current_path.value[0] = 0x3f;
464                 card->cache.current_path.value[1] = 0x00;
465                 if (id_hi == 0x3f && id_lo == 0x00){
466                          card->cache.current_path.len = 2;
467                 }else{
468                          card->cache.current_path.len = 4;
469                          card->cache.current_path.value[2] = id_hi;
470                          card->cache.current_path.value[3] = id_lo;
471                 }
472        }
473       
474        if (file_out)
475                 *file_out = file;
476
477        SC_FUNC_RETURN(card->ctx, 2, SC_SUCCESS);
478}
479
480static int entersafe_select_aid(sc_card_t *card,
481                                                                const sc_path_t *in_path,
482                                                                sc_file_t **file_out)
483{
484        int r;
485
486        if (card->cache_valid
487                && card->cache.current_path.type == SC_PATH_TYPE_DF_NAME
488                && card->cache.current_path.len == in_path->len
489                && memcmp(card->cache.current_path.value, in_path->value, in_path->len)==0 )
490        {
491                 if(file_out)
492                 {
493                          *file_out = sc_file_new();
494                          if(!file_out)
495                                   SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
496                 }
497        }
498        else
499        {
500                 r = iso_ops->select_file(card,in_path,file_out);
501                 SC_TEST_RET(card->ctx, r, "APDU transmit failed");
502
503                 /* update cache */
504                 card->cache.current_path.type = SC_PATH_TYPE_DF_NAME;
505                 card->cache.current_path.len = in_path->len;
506                 memcpy(card->cache.current_path.value,in_path->value,in_path->len);
507        }
508        if (file_out) {
509                 sc_file_t *file = *file_out;
510                 assert(file);
511
512                 file->type = SC_FILE_TYPE_DF;
513                 file->ef_structure = SC_FILE_EF_UNKNOWN;
514                 file->path.len = 0;
515                 file->size = 0;
516                 /* AID */
517                 memcpy(file->name,in_path->value,in_path->len);
518                 file->namelen = in_path->len;
519                 file->id = 0x0000;
520        }
521        SC_FUNC_RETURN(card->ctx, 2, r);
522}
523
524static int entersafe_select_path(sc_card_t *card,
525                                                                const u8 pathbuf[16], const size_t len,
526                                                                sc_file_t **file_out)
527{
528         u8 n_pathbuf[SC_MAX_PATH_SIZE];
529         const u8 *path=pathbuf;
530         size_t pathlen=len;
531         int bMatch = -1;
532         int i;
533         int r;
534
535         if (pathlen%2 != 0 || pathlen > 6 || pathlen <= 0)
536                  SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
537
538         /* if pathlen == 6 then the first FID must be MF (== 3F00) */
539         if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
540                  SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
541
542         /* unify path (the first FID should be MF) */
543         if (path[0] != 0x3f || path[1] != 0x00)
544         {
545                  n_pathbuf[0] = 0x3f;
546                  n_pathbuf[1] = 0x00;
547                  for (i=0; i< pathlen; i++)
548                           n_pathbuf[i+2] = pathbuf[i];
549                  path = n_pathbuf;
550                  pathlen += 2;
551         }
552       
553         /* check current working directory */
554         if (card->cache_valid
555                 && card->cache.current_path.type == SC_PATH_TYPE_PATH
556                 && card->cache.current_path.len >= 2
557                 && card->cache.current_path.len <= pathlen )
558         {
559                  bMatch = 0;
560                  for (i=0; i < card->cache.current_path.len; i+=2)
561                           if (card->cache.current_path.value[i] == path[i]
562                                   && card->cache.current_path.value[i+1] == path[i+1] )
563                                        bMatch += 2;
564         }
565
566         if ( card->cache_valid && bMatch > 2 )
567         {
568                  if ( pathlen - bMatch == 2 )
569                  {
570                           /* we are in the rigth directory */
571                           return entersafe_select_fid(card, path[bMatch], path[bMatch+1], file_out);
572                  }
573                  else if ( pathlen - bMatch > 2 )
574                  {
575                           /* two more steps to go */
576                           sc_path_t new_path;
577       
578                           /* first step: change directory */
579                           r = entersafe_select_fid(card, path[bMatch], path[bMatch+1], NULL);
580                           SC_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
581               
582                           new_path.type = SC_PATH_TYPE_PATH;
583                           new_path.len  = pathlen - bMatch-2;
584                           memcpy(new_path.value, &(path[bMatch+2]), new_path.len);
585                           /* final step: select file */
586                           return entersafe_select_file(card, &new_path, file_out);
587                  }
588                  else /* if (bMatch - pathlen == 0) */
589                  {
590                           /* done: we are already in the
591                                * requested directory */
592                           if ( card->ctx->debug >= 4 )
593                                        sc_debug(card->ctx, "cache hit\n");
594                           /* copy file info (if necessary) */
595                           if (file_out) {
596                                        sc_file_t *file = sc_file_new();
597                                        if (!file)
598                                                 SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
599                                        file->id = (path[pathlen-2] << 8) +
600                                                 path[pathlen-1];
601                                        file->path = card->cache.current_path;
602                                        file->type = SC_FILE_TYPE_DF;
603                                        file->ef_structure = SC_FILE_EF_UNKNOWN;
604                                        file->size = 0;
605                                        file->namelen = 0;
606                                        file->magic = SC_FILE_MAGIC;
607                                        *file_out = file;
608                           }
609                           /* nothing left to do */
610                           return SC_SUCCESS;
611                  }
612         }
613         else
614         {
615                  /* no usable cache */
616                  for ( i=0; i<pathlen-2; i+=2 )
617                  {
618                           r = entersafe_select_fid(card, path[i], path[i+1], NULL);
619                           SC_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
620                  }
621                  return entersafe_select_fid(card, path[pathlen-2], path[pathlen-1], file_out);
622         }
623}
624
625static int entersafe_select_file(sc_card_t *card,
626                                                                 const sc_path_t *in_path,
627                                                                 sc_file_t **file_out)
628{
629         int r;
630         assert(card);
631         assert(in_path);
632         SC_FUNC_CALLED(card->ctx, 1);
633
634         if (card->ctx->debug >= 4) {
635                  char pbuf[SC_MAX_PATH_STRING_SIZE];
636
637                  r = sc_path_print(pbuf, sizeof(pbuf), &card->cache.current_path);
638                  if (r != SC_SUCCESS)
639                         pbuf[0] = '\0';
640               
641                  sc_debug(card->ctx, "current path (%s, %s): %s (len: %u)\n",
642                                   (card->cache.current_path.type==SC_PATH_TYPE_DF_NAME?"aid":"path"),
643                                   (card->cache_valid?"valid":"invalid"), pbuf,
644                                   card->cache.current_path.len);
645         }
646         
647         
648         switch(in_path->type)
649         {
650         case SC_PATH_TYPE_FILE_ID:
651                  if (in_path->len != 2)
652                           SC_FUNC_RETURN(card->ctx,2,SC_ERROR_INVALID_ARGUMENTS);
653                  return entersafe_select_fid(card,in_path->value[0],in_path->value[1], file_out);
654         case SC_PATH_TYPE_DF_NAME:
655                  return entersafe_select_aid(card,in_path,file_out);
656         case SC_PATH_TYPE_PATH:
657                  return entersafe_select_path(card,in_path->value,in_path->len,file_out);
658         default:
659                  SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
660         }
661}
662
663static int entersafe_create_mf(sc_card_t *card, sc_entersafe_create_data * data)
664{
665        int r;
666        sc_apdu_t apdu;
667
668        SC_FUNC_CALLED(card->ctx, 1);
669
670        memcpy(data->data.mf.init_key, init_key, sizeof(init_key));
671
672        sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x00,0x00);
673        apdu.cla=0x84;
674        apdu.data=(u8*)&data->data.mf;
675        apdu.datalen=apdu.lc=sizeof(data->data.mf);
676
677        r = entersafe_transmit_apdu(card, &apdu,trans_code,sizeof(trans_code),0,1);
678        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
679        return sc_check_sw(card, apdu.sw1, apdu.sw2);
680}
681static int entersafe_create_df(sc_card_t *card, sc_entersafe_create_data * data)
682{
683        int r;
684        sc_apdu_t apdu;
685
686        SC_FUNC_CALLED(card->ctx, 1);
687
688        memcpy(data->data.df.init_key, init_key, sizeof(init_key));
689
690        sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x01,0x00);
691        apdu.cla=0x84;
692        apdu.data=(u8*)&data->data.df;
693        apdu.lc=apdu.datalen=sizeof(data->data.df);
694
695        r = entersafe_transmit_apdu(card, &apdu,init_key,sizeof(init_key),0,1);
696        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
697        return sc_check_sw(card, apdu.sw1, apdu.sw2);
698}
699
700static int entersafe_create_ef(sc_card_t *card, sc_entersafe_create_data * data)
701{
702        int r;
703        sc_apdu_t apdu;
704
705        SC_FUNC_CALLED(card->ctx, 1);
706
707        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00);
708        apdu.cla = 0x84;
709        apdu.data = (u8*)&data->data.ef;
710        apdu.lc = apdu.datalen = sizeof(data->data.ef);
711
712        r = entersafe_transmit_apdu(card, &apdu,init_key,sizeof(init_key),0,1);
713        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
714        return sc_check_sw(card, apdu.sw1, apdu.sw2);
715}
716
717static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def)
718{
719        u8 def = (u8)in_def;
720        const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method);
721        if (!entry)
722        {
723                return def;
724        }
725        else if (entry->method & SC_AC_CHV)
726        {
727                unsigned int key_ref = entry->key_ref;
728                if (key_ref == SC_AC_KEY_REF_NONE)
729                        return def;
730                else
731                        return ENTERSAFE_AC_ALWAYS&0x04;
732        }
733        else if (entry->method & SC_AC_NEVER)
734        {
735                return ENTERSAFE_AC_NEVER;
736        }
737        else
738        {
739                return def;
740        }
741}
742
743static int entersafe_create_file(sc_card_t *card, sc_file_t *file)
744{       
745         SC_FUNC_CALLED(card->ctx, 1);
746         
747         if (file->type == SC_FILE_TYPE_WORKING_EF) {
748                  int    r;
749                  sc_entersafe_create_data data;
750                  memset(&data,0,sizeof(data));
751
752                  data.data.ef.file_id[0] = (file->id>>8)&0xFF;
753                  data.data.ef.file_id[1] = file->id&0xFF;     
754                  data.data.ef.size[0] = (file->size>>8)&0xFF;
755                  data.data.ef.size[1] = file->size&0xFF;
756                  memset(data.data.ef.ac,ENTERSAFE_AC_ALWAYS,sizeof(data.data.ef.ac));
757                  data.data.ef.ac[0] = process_acl_entry(file,SC_AC_OP_READ,ENTERSAFE_AC_ALWAYS);
758                  data.data.ef.ac[1] = process_acl_entry(file,SC_AC_OP_UPDATE,ENTERSAFE_AC_ALWAYS);
759
760                  return entersafe_create_ef(card, &data);
761         } else
762                  return SC_ERROR_INVALID_ARGUMENTS;
763}
764
765static int entersafe_internal_set_security_env(sc_card_t *card,
766                                                                                           const sc_security_env_t *env,
767                                                                                           u8 ** data,size_t* size)
768{
769        sc_apdu_t apdu;
770        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
771        u8 *p=sbuf;
772        int r;
773
774        SC_FUNC_CALLED(card->ctx, 1);
775
776        assert(card != NULL && env != NULL);
777       
778        switch (env->operation) {
779        case SC_SEC_OPERATION_DECIPHER:
780        case SC_SEC_OPERATION_SIGN:
781                 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
782                 apdu.p1 = 0x41;
783                 apdu.p2 = 0xB8;
784                 *p++ = 0x80;
785                 *p++ = 0x01;
786                 *p++ = 0x80;
787                 *p++ = 0x83;
788                 *p++ = 0x02;
789                 *p++ = env->key_ref[0];
790                 *p++ = 0x22;
791                 if(*size>1024/8)
792                 {
793                          if(*size == 2048/8)
794                          {
795                                   *p++ = 0x89;
796                                   *p++ = 0x40;
797                                   memcpy(p,*data,0x40);
798                                   p+=0x40;
799                                   *data+=0x40;
800                                   *size-=0x40;
801                          }
802                          else
803                          {
804                                   SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
805                          }
806                 }
807                 break;
808        default:
809                 SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
810        }
811       
812        apdu.le = 0;
813        apdu.lc = apdu.datalen = p - sbuf;
814        apdu.data = sbuf;
815        apdu.resplen = 0;
816
817        r = sc_transmit_apdu(card, &apdu);
818        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
819        return sc_check_sw(card, apdu.sw1, apdu.sw2);
820}
821
822/**
823 * We don't really set the security envirment,but cache it.It will be set when
824 * security operation is performed later.Because we may transport partial of
825 * the sign/decipher data within the security envirment apdu.
826 */
827static int entersafe_set_security_env(sc_card_t *card,
828                                                                          const sc_security_env_t *env,
829                                                                          int se_num)
830{
831         assert(card);
832         assert(env);
833
834         SC_FUNC_CALLED(card->ctx, 1);
835
836         if(card->drv_data){
837                  free(card->drv_data);
838                  card->drv_data=0;
839         }
840
841         card->drv_data = calloc(1,sizeof(*env));
842         if(!card->drv_data)
843                  SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_OUT_OF_MEMORY);
844
845         memcpy(card->drv_data,env,sizeof(*env));
846         SC_FUNC_RETURN(card->ctx, 2, SC_NO_ERROR);
847}
848
849static int entersafe_restore_security_env(sc_card_t *card, int se_num)
850{
851         SC_FUNC_CALLED(card->ctx, 1);
852         return SC_NO_ERROR;
853}
854
855
856static int entersafe_compute_with_prkey(sc_card_t *card,
857                                                                                const u8 * data, size_t datalen,
858                                                                                u8 * out, size_t outlen)
859{
860        int r;
861        sc_apdu_t apdu;
862        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
863        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
864        u8* p=sbuf;
865        size_t size = datalen;
866
867        SC_FUNC_CALLED(card->ctx, 1);
868
869        if(!data)
870                 SC_FUNC_RETURN(card->ctx, 4,SC_ERROR_INVALID_ARGUMENTS);
871
872        memcpy(p,data,size);
873
874        if(!card->drv_data)
875                 SC_FUNC_RETURN(card->ctx, 4,SC_ERROR_INTERNAL);
876
877        r = entersafe_internal_set_security_env(card,card->drv_data,&p,&size);
878        SC_TEST_RET(card->ctx, r, "internal set security env failed");
879   
880        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x86,0x80);
881        apdu.data=p;
882        apdu.lc = size;
883        apdu.datalen = size;
884        apdu.resp = rbuf;
885        apdu.resplen = sizeof(rbuf);
886        apdu.le = 256;
887        apdu.sensitive = 1;
888
889        r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
890        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
891
892        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
893                size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
894                memcpy(out, apdu.resp, len);
895                SC_FUNC_RETURN(card->ctx, 4, len);
896        }
897        SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
898}
899
900static int entersafe_compute_signature(sc_card_t *card,
901                                                                           const u8 * data, size_t datalen,
902                                                                           u8 * out, size_t outlen)
903{
904         SC_FUNC_CALLED(card->ctx, 1);
905         return entersafe_compute_with_prkey(card,data,datalen,out,outlen);
906}
907
908static int entersafe_decipher(sc_card_t *card,
909                                                          const u8 * crgram, size_t crgram_len,
910                                                          u8 * out, size_t outlen)
911{
912         SC_FUNC_CALLED(card->ctx, 1);
913         return entersafe_compute_with_prkey(card,crgram,crgram_len,out,outlen);
914}
915
916static void entersafe_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
917{
918        pin->encoding   = SC_PIN_ENCODING_ASCII;
919        pin->min_length = 4;
920        pin->max_length = 16;
921        pin->pad_length = 16;
922        pin->offset     = 5 + num * 16;
923        pin->pad_char=0x00;
924}
925
926static int entersafe_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
927                           int *tries_left)
928{
929         int r;
930         SC_FUNC_CALLED(card->ctx, 1);
931         entersafe_init_pin_info(&data->pin1,0);
932         entersafe_init_pin_info(&data->pin2,1);
933         data->flags |= SC_PIN_CMD_NEED_PADDING;
934
935         r = iso_ops->pin_cmd(card,data,tries_left);
936         SC_FUNC_RETURN(card->ctx, 4, r);
937}
938
939static int entersafe_erase_card(sc_card_t *card)
940{
941        int r;
942        u8  sbuf[2];
943        sc_apdu_t apdu;
944
945        SC_FUNC_CALLED(card->ctx, 1);
946
947        sbuf[0] = 0x3f;
948        sbuf[1] = 0x00;
949        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x00);
950        apdu.lc   = 2;
951        apdu.datalen = 2;
952        apdu.data = sbuf;
953       
954        r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
955        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
956        /* invalidate cache */
957        card->cache_valid = 0;
958
959        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xEE, 0x00, 0x00);
960        apdu.cla=0x84;
961        apdu.lc=2;
962        apdu.datalen=2;
963        apdu.data=sbuf;
964        r = entersafe_transmit_apdu(card, &apdu,trans_code,sizeof(trans_code),0,1);
965        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
966        SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
967}
968
969static void entersafe_encode_bignum(u8 tag,sc_pkcs15_bignum_t bignum,u8** ptr)
970{
971         u8 *p=*ptr;
972
973         *p++=tag;
974         assert(0);
975         if(bignum.len<256)
976         {
977                  *p++=(u8)bignum.len;
978         }
979         else
980         {
981                  u8 bytes=0;
982                  size_t len=bignum.len;
983                  while(len)
984                  {
985                           len=len>>8;
986                           ++bytes;
987                  }
988                  bytes&=0x0F;
989                  *p++=0x80|bytes;
990                  while(bytes)
991                  {
992                           *p++=bignum.len>>((bytes-1)*8);
993                           --bytes;
994                  }
995         }
996         memcpy(p,bignum.data,bignum.len);
997         entersafe_reverse_buffer(p,bignum.len);
998         p+=bignum.len;
999}
1000
1001static int entersafe_write_small_rsa_key(sc_card_t *card,u8 key_id,struct sc_pkcs15_prkey_rsa *rsa)
1002{
1003         sc_apdu_t apdu;
1004         u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
1005         int r;
1006         u8 *p=sbuff;
1007
1008        SC_FUNC_CALLED(card->ctx, 1);
1009
1010         {/* write prkey */
1011                  *p++=0x00;                    /* EC */
1012                  *p++=0x00;                    /* ver */
1013                  entersafe_encode_bignum('E',rsa->exponent,&p);
1014                  entersafe_encode_bignum('D',rsa->d,&p);
1015
1016                  sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF4,0x22,key_id);
1017                  apdu.cla=0x84;
1018                  apdu.data=sbuff;
1019                  apdu.lc=apdu.datalen=p-sbuff;
1020
1021                  r=entersafe_transmit_apdu(card,&apdu,key_maintain,sizeof(key_maintain),1,1);
1022                  SC_TEST_RET(card->ctx, r, "APDU transmit failed");
1023                  SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write prkey failed");
1024         }
1025
1026         p=sbuff;
1027         {/* write pukey */
1028                  *p++=0x00;                    /* EC */
1029                  *p++=0x00;                    /* ver */
1030                  entersafe_encode_bignum('E',rsa->exponent,&p);
1031                  entersafe_encode_bignum('N',rsa->modulus,&p);
1032
1033                  sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF4,0x2A,key_id);
1034                  apdu.cla=0x84;
1035                  apdu.data=sbuff;
1036                  apdu.lc=apdu.datalen=p-sbuff;
1037
1038                  r=entersafe_transmit_apdu(card,&apdu,key_maintain,sizeof(key_maintain),1,1);
1039                  SC_TEST_RET(card->ctx, r, "APDU transmit failed");
1040                  SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),"Write pukey failed");
1041         }
1042
1043         SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
1044}
1045
1046static int entersafe_write_rsa_key_factor(sc_card_t *card,
1047                                                                                  u8 key_id,u8 usage,
1048