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

Revision 3502, 45.3 KB (checked in by ludovic.rousseau, 7 months ago)

convert C++ in C comment

Line 
1/*
2 * card-piv.c: Support for PIV-II from NIST SP800-73
3 * card-default.c: Support for cards with no driver
4 *
5 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
6 * Copyright (C) 2005,2006,2007 Douglas E. Engert <deengert@anl.gov>
7 * Copyright (C) 2006, Identity Alliance, Thomas Harning <thomas.harning@identityalliance.com>
8 * Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25#include "internal.h"
26
27#ifdef ENABLE_OPENSSL
28
29#include <ctype.h>
30#include <string.h>
31#include <fcntl.h>
32#include <openssl/evp.h>
33#include <openssl/bio.h>
34#include <openssl/pem.h>
35#include <openssl/rsa.h>
36#include "asn1.h"
37#include "cardctl.h"
38#ifdef ENABLE_ZLIB
39#include "compression.h"
40#endif
41
42typedef struct {
43        u8* data;
44        size_t length;
45        int enumtag;
46} piv_cache_item;
47
48typedef struct piv_private_data {
49        struct sc_pin_cmd_pin pin_info;
50        sc_file_t *aid_file;
51        int enumtag;
52        int  selected_obj; /* The index into the piv_objects last selected */
53        int  return_only_cert; /* return the cert from the object */
54        int  eof;
55        size_t max_recv_size; /* saved size, need to lie to pkcs15_read_file */
56        size_t max_send_size;
57        int key_ref; /* saved from set_security_env and */
58        int alg_id;  /* used in decrypt, signature */ 
59        piv_cache_item* cache;
60        int cacheLen;
61        piv_cache_item* current_item;
62} piv_private_data_t;
63
64#define PIV_DATA(card) ((piv_private_data_t*)card->drv_data)
65
66static int add_cache_item(piv_private_data_t* priv, int enumtag, u8* data, size_t length) {
67        int idx, len = priv->cacheLen;
68        piv_cache_item* cache = priv->cache;
69        for(idx = 0; idx < len; idx++) {
70                if(!cache[idx].data)
71                        break;
72                if(cache[idx].enumtag == enumtag) /* Found matching tag */
73                        break;
74        }
75        if(idx == len)
76                return -1; /* FAILED NO FREE ROOM */
77        if(cache[idx].data)
78                free(cache[idx].data);
79        cache[idx].data = data;
80        cache[idx].length = length;
81        cache[idx].enumtag = enumtag;
82        return 0;
83}
84
85static piv_cache_item* get_cache_item(piv_private_data_t* priv, int enumtag) {
86        int idx, len = priv->cacheLen;
87        piv_cache_item* cache = priv->cache;
88#if 1
89/* DEE some thing not right with the cache,
90 * when used with the pkcs15-tool -C it cant find the CCC, but finds the
91 * CHUI ( as it was read for the serial) and finds part of a cert for the
92 * CHFingerprints
93 * So turn it off for now. 6/1/2007
94 */
95return NULL;
96#endif
97
98        for(idx = 0; idx < len; idx++) {
99                if(cache[idx].enumtag == enumtag)
100                        return &cache[idx];
101        }
102        return NULL;
103}
104
105static void free_cache_items(piv_private_data_t* priv) {
106        int idx, len = priv->cacheLen;
107        piv_cache_item* cache = priv->cache;
108        for(idx = 0; idx < len; idx++) {
109                if(cache[idx].data) {
110                        free(cache[idx].data);
111                        cache[idx].data = NULL;
112                }
113        }
114}
115
116struct piv_aid {
117        int enumtag;
118        size_t len_short;       /* min lenght without version */
119        size_t len_long;        /* With version and other stuff */
120        u8 *value;
121};
122 
123/* The Generic entry should be the "A0 00 00 03 08 00 00 01 00 "
124 * NIST published  this on 10/6/2005   
125 * 800-73-2 is due for release 11/2007.
126 * 800-73-2 Part 1 now refers to version "02 00"
127 * i.e. "A0 00 00 03 08 00 00 01 00 02 00".
128 * but we dont need the version number. but could get it from the PIX.
129 */ 
130static struct piv_aid piv_aids[] = {
131        {SC_CARD_TYPE_PIV_II_GENERIC,
132                 9, 9, (u8 *) "\xA0\x00\x00\x03\x08\x00\x00\x10\x00" },
133        {0,  9, 0, NULL }
134};
135
136enum {
137        PIV_OBJ_CCC = 1,
138        PIV_OBJ_CHUI,
139        PIV_OBJ_UCHUI,  /* new with 800-73-2 */
140        PIV_OBJ_X509_PIV_AUTH,
141        PIV_OBJ_CHF,
142        PIV_OBJ_PI,
143        PIV_OBJ_CHFI,
144        PIV_OBJ_X509_DS,
145        PIV_OBJ_X509_KM,
146        PIV_OBJ_X509_CARD_AUTH,
147        PIV_OBJ_SEC_OBJ,
148        PIV_OBJ_9B03,
149        PIV_OBJ_9A06,
150        PIV_OBJ_9C06,
151        PIV_OBJ_9D06,
152        PIV_OBJ_9E06,
153        PIV_CACHE_SIZE
154};
155
156struct piv_object {
157        int enumtag;
158        const char * name;
159        const char * oidstring;
160        size_t tag_len;
161        u8  tag_value[3];
162        u8  containerid[2];     /* will use as relative paths for simulation */
163        size_t maxlen;          /* advisory, used with select_file, but we can read larger */
164};
165
166/* maxlen values are advisory only, we can read larger if needed. */
167static struct piv_object piv_objects[] = {
168        { PIV_OBJ_CCC, "Card Capability Container",
169                        "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 266+30+3},
170        { PIV_OBJ_CHUI, "Card Holder Unique Identifier",
171                        "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 3392+20+4},
172        { PIV_OBJ_CHUI, "Unsigned Card Holder Unique Identifier",
173                        "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x04", "\x30\x10", 67+14+4},
174        { PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication",
175                        "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", 1895+9+4+400} ,
176                /* extra 400 is hack for MultOS card which returns 2200 bytes  */
177        { PIV_OBJ_CHF, "Card Holder Fingerprints",
178                        "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 4000+4+4},
179        { PIV_OBJ_PI, "Printed Information",
180                        "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 146+18+3},
181        { PIV_OBJ_CHFI, "Card Holder Facial Image",
182                        "2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 12704+5+4},
183        { PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature",
184                        "2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", 1895+9+4+400},
185        { PIV_OBJ_X509_KM, "X.509 Certificate for Key Management",
186                        "2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", 1895+9+4+400},
187        { PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication",
188                        "2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", 1895+9+4+400},
189        { PIV_OBJ_SEC_OBJ, "Security Object",
190                        "2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 1000+30+4+4},
191/* following not standard , to be used by piv-tool only for testing */
192        { PIV_OBJ_9B03, "3DES-ECB ADM",
193                        "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 24},
194        /* Only used when signing a cert req, usually from engine
195         * after piv-tool generated the key and saved the pub key
196         * to a file. Note RSA key can be 1024, 2048 or 3072
197         * but still use the "9x06" name.
198         */
199        { PIV_OBJ_9A06, "RSA 9A Pub key from last genkey",
200                        "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", 2048},
201        { PIV_OBJ_9C06, "Pub 9C key from last genkey",
202                        "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", 2048},
203        { PIV_OBJ_9D06, "Pub 9D key from last genkey",
204                        "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", 2048},
205        { PIV_OBJ_9E06, "Pub 9E key from last genkey",
206                        "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", 2048},
207        { 0, "", "", 0, "", "", 0}
208};
209       
210static struct sc_card_operations piv_ops;
211
212static struct sc_card_driver piv_drv = {
213        "PIV-II  for multiple cards",
214        "piv",
215        &piv_ops,
216        NULL, 0, NULL
217};
218
219/*
220 * If ptr == NULL, just return the size of the tag and lenght and data
221 * oterwise, store tag and length at **ptr, and increment
222 */
223
224static size_t put_tag_and_len(unsigned int tag, size_t len, u8 **ptr)
225{
226        int i;
227        u8 *p;
228       
229        if (len < 128) {
230                i = 2;
231        } else if (len < 256) {
232                i = 3;
233        } else {
234                i = 4;
235        }
236       
237        if (ptr) {
238                p = *ptr;
239                *p++ = (u8)tag;
240                switch (i) {
241                        case 2:
242                                *p++ = len;
243                                break;
244                        case 3:
245                                *p++ = 0x81;
246                                *p++ = len;
247                                break;
248                        case 4:
249                                *p++ = 0x82;
250                                *p++ = (u8) (len >> 8);
251                                *p++ = (u8) (len & 0xff);
252                                break;
253                }
254                *ptr = p;
255        } else {
256                i += len;
257        }
258        return i;
259}
260
261/*
262 * Send a command and receive data. Receive as much as the card indicates
263 * in the first segment. There is always something to send.
264 * Used by  GET DATA, PUT DATA, GENERAL AUTHENTICATE
265 * and GENERATE ASYMMETRIC KEY PAIR.
266 * SELECT could too.
267 *
268 * For now we will use a large buffer. What we should be doing is using  a
269 * the TLV in the first few bytes to see how large the object is and
270 * allocating a buffer.
271 */
272
273static int piv_general_io(sc_card_t *card, int ins, int p1, int p2,
274        const u8 * sendbuf, size_t sendbuflen, u8 ** recvbuf,
275        size_t * recvbuflen)
276{
277        piv_private_data_t * priv = PIV_DATA(card);
278        int r;
279        sc_apdu_t apdu;
280        u8 rbufinitbuf[20000]; /* crude way to do this  see above comments */
281        u8 *rbuf;
282        size_t rbuflen;
283        unsigned int cla_out, tag_out;
284        const u8 *body;
285        size_t bodylen;
286
287        SC_FUNC_CALLED(card->ctx,1);
288
289       
290        sc_debug(card->ctx, "piv_general_io %02x %02x %02x %d : %d %d\n",
291                 ins, p1, p2, sendbuflen , priv->max_send_size, priv->max_recv_size);
292
293        rbuf = rbufinitbuf;
294        rbuflen = sizeof(rbufinitbuf);
295
296        r = sc_lock(card);
297        if (r != SC_SUCCESS)
298                SC_FUNC_RETURN(card->ctx, 1, r);
299               
300        sc_format_apdu(card, &apdu,
301                        recvbuf ? SC_APDU_CASE_4_SHORT: SC_APDU_CASE_3_SHORT,
302                        ins, p1, p2);
303        apdu.flags |= SC_APDU_FLAGS_CHAINING;
304
305        apdu.lc = sendbuflen;
306        apdu.datalen = sendbuflen;
307        apdu.data = sendbuf;
308
309        if (recvbuf) {
310                apdu.resp = rbuf;
311                apdu.le = priv->max_recv_size;
312                apdu.resplen = rbuflen;
313        } else {
314                 apdu.resp =  rbuf;
315                 apdu.le = 0;
316                 apdu.resplen = 0;
317        }
318
319        card->max_recv_size = priv->max_recv_size;
320
321        sc_debug(card->ctx,"calling sc_transmit_apdu flags=%x le=%d, resplen=%d, resp=%p",
322                apdu.flags, apdu.le, apdu.resplen, apdu.resp);
323
324        /* with new adpu.c and chaining, this actually reads the whole object */
325        r = sc_transmit_apdu(card, &apdu);
326        card->max_recv_size = 0xffff;
327
328        sc_debug(card->ctx,"DEE r=%d apdu.resplen=%d sw1=%02x sw2=%02x",
329                        r, apdu.resplen, apdu.sw1, apdu.sw2);
330        if (r < 0) {
331                sc_debug(card->ctx,"Transmit failed");
332                goto err;
333        }
334                       
335        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
336       
337        if (r < 0) {
338                sc_debug(card->ctx, "Card returned error ");
339                goto err;
340        }
341
342        /*
343         * See how much we read and make sure it is asn1
344         * if not, return 0 indicating no data found
345         */ 
346
347       
348        rbuflen = 0;  /* in case rseplen < 3  i.e. not parseable */
349        if ( recvbuflen && recvbuf && apdu.resplen > 3) {
350                *recvbuflen = 0;
351                /* we should have all the tag data, so we have to tell sc_asn1_find_tag
352                 * the buffer is bigger, so it will not produce "ASN1.tag too long!" */
353
354                body = rbuf;
355                if (sc_asn1_read_tag(&body, 0xffff, &cla_out, &tag_out, &bodylen) !=  SC_SUCCESS)               {
356                        sc_debug(card->ctx, "***** received buffer tag MISSING ");
357                        body = rbuf;
358                        /* some readers/cards might return 6c 00 */ 
359                        if (apdu.sw1 == 0x61  || apdu.sw2 == 0x6c )
360                                bodylen = 12000;
361                        else
362                                bodylen = apdu.resplen;
363                }
364                rbuflen = body - rbuf + bodylen;
365                *recvbuf = (u8 *)malloc(rbuflen);
366                sc_debug(card->ctx, "DEE got buffer %p len %d",*recvbuf,  rbuflen);
367                if (*recvbuf == NULL) {
368                        r = SC_ERROR_OUT_OF_MEMORY;
369                        goto err;
370                }
371
372                memcpy(*recvbuf, rbuf, rbuflen); /* copy tag too */
373        }
374        /* If we only read part of the object, we would continue chaining, but the
375         * apdu.c chaining code has already read all the data */
376        priv->eof = 1;
377
378        if (recvbuflen) {
379                *recvbuflen =  rbuflen;
380                r = *recvbuflen;
381        }
382
383err:
384        sc_unlock(card);
385        SC_FUNC_RETURN(card->ctx, 1, r);
386}
387
388/* Add the PIV-II operations */
389/* Should use our own keydata, actually should be common to all cards */
390/* only do RSA for now */
391
392static int piv_generate_key(sc_card_t *card,
393                struct sc_cardctl_cryptoflex_genkey_info *keydata)
394{
395        int r;
396        u8 *rbuf = NULL;
397        size_t rbuflen = 0;
398        size_t buf_len = 0;
399        u8 *buf_end;
400        u8 *p, *rp, *tag;
401        u8 tagbuf[16];
402        u8 outdata[3]; /* we could also add tag 81 for exponent */
403        size_t taglen, i;
404        size_t out_len;
405        size_t in_len;
406        unsigned int cla_out, tag_out;
407       
408        SC_FUNC_CALLED(card->ctx, 1);
409
410        keydata->exponent = 0;
411        keydata->pubkey = NULL;
412        keydata->pubkey_len = 0;
413
414       
415        out_len = 3;
416        outdata[0] = 0x80;
417        outdata[1] = 0x01;
418        switch (keydata->key_bits) {
419                case 1024: outdata[2] = 0x06; break;
420                case 2048: outdata[2] = 0x07; break;
421                case 3072: outdata[2] = 0x05; break;
422                default:
423                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
424        }
425
426        p = tagbuf;
427
428        put_tag_and_len(0xAC, out_len, &p);
429
430        memcpy(p, outdata, out_len);
431        p+=out_len;
432
433        rp = rbuf;
434        buf_end = rp + buf_len;
435
436        r = piv_general_io(card, 0x47, 0x00, keydata->key_num,
437                        tagbuf, p - tagbuf, &rbuf, &rbuflen);
438       
439        if (r >= 0) {
440                const u8 *cp;
441                keydata->exponent = 0;
442
443                /* expected tag is 7f49.  */
444                /* we will whatever tag is present */
445
446                cp = rbuf;
447                in_len = rbuflen;
448
449                r = sc_asn1_read_tag(&cp, rbuflen, &cla_out, &tag_out, &in_len);
450                if (r != SC_SUCCESS) {
451                        sc_debug(card->ctx,"Tag buffer not found");
452                        goto err;
453                }
454               
455                tag = (u8 *) sc_asn1_find_tag(card->ctx, cp, in_len, 0x82, &taglen);
456                if (tag != NULL && taglen <= 4) {
457                        keydata->exponent = 0;
458                        for (i = 0; i < taglen;i++) {
459                                keydata->exponent = (keydata->exponent<<8) + tag[i];
460                        }
461                }
462                tag = (u8 *) sc_asn1_find_tag(card->ctx, cp, in_len, 0x81, &taglen);
463       
464                if (tag != NULL && taglen > 0) {
465                        keydata->pubkey = malloc(taglen);
466                        if (keydata->pubkey == NULL)
467                                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
468                        keydata->pubkey_len = taglen;
469                        memcpy (keydata->pubkey, tag, taglen);
470                }
471                r = 0;
472        }
473       
474err:
475        if (rbuf)
476                free(rbuf);
477        SC_FUNC_RETURN(card->ctx, 1, r);
478}
479
480
481static int piv_select_aid(sc_card_t* card, u8* aid, size_t aidlen, u8* response, size_t *responselen)
482{
483        sc_apdu_t apdu;
484        int r;
485
486        SC_FUNC_CALLED(card->ctx,4);
487        if (card->ctx->debug >= 5)
488                sc_debug(card->ctx, "Got args: aid=%x, aidlen=%d, response=%x, responselen=%d\n", aid, aidlen, response, *responselen);
489
490        sc_format_apdu(card, &apdu,
491                response == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
492        apdu.lc = aidlen;
493        apdu.data = aid;
494        apdu.datalen = aidlen;
495        apdu.resp = response;
496        apdu.resplen = *responselen;
497        apdu.le = response == NULL ? 0 : 256; /* could be 21  for fci */
498
499        r = sc_transmit_apdu(card, &apdu);
500        *responselen = apdu.resplen;
501        SC_TEST_RET(card->ctx, 4,  r);
502        SC_FUNC_RETURN(card->ctx, 4,  sc_check_sw(card, apdu.sw1, apdu.sw2));
503}
504
505/* find the PIV AID on the card. If card->type already filled in,
506 * then look for specific AID only
507 * Assumes that priv may not be present
508 */
509
510static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file)
511{
512        sc_apdu_t apdu;
513        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
514        int r,i;
515        u8 *tag;
516        size_t taglen;
517        u8 *pix;
518        size_t pixlen;
519        size_t resplen = sizeof(rbuf);
520
521        SC_FUNC_CALLED(card->ctx,1);
522
523        /* first  see if the default applcation will return a template
524         * that we know about.
525         */
526
527        if (card->type == SC_CARD_TYPE_PIV_II_GENERIC)
528                SC_FUNC_RETURN(card->ctx, 1, 0);
529
530        r = piv_select_aid(card, piv_aids[0].value, piv_aids[0].len_short, rbuf, &resplen);
531        if (r >= 0 && resplen > 2 ) {
532                tag = (u8 *) sc_asn1_find_tag(card->ctx, rbuf, resplen, 0x61, &taglen);
533                if (tag != NULL) {
534                        pix = (u8 *) sc_asn1_find_tag(card->ctx, tag, taglen, 0x4F, &pixlen);
535                        if (pix != NULL ) {
536                                sc_debug(card->ctx,"found PIX");
537                 
538                                /* early cards returned full AID, rather then just the pix */
539                                for (i = 0; piv_aids[i].len_long != 0; i++) {
540                                        if ((pixlen >= 6 && memcmp(pix, piv_aids[i].value + 5,
541                                                                        piv_aids[i].len_long - 5 ) == 0)
542                                                 || ((pixlen >=  piv_aids[i].len_short &&
543                                                        memcmp(pix, piv_aids[i].value,
544                                                        piv_aids[i].len_short) == 0))) {
545                                                if (card->type > SC_CARD_TYPE_PIV_II_BASE &&
546                                                        card->type < SC_CARD_TYPE_PIV_II_BASE+1000 &&
547                                                        card->type == piv_aids[i].enumtag) {
548                                                        SC_FUNC_RETURN(card->ctx, 1, i);
549                                                } else {
550                                                        SC_FUNC_RETURN(card->ctx, 1, i);
551                                                }
552                                        }
553                                }
554                        }
555                }
556        }
557
558        /* for testing, we can force the use of a specific AID 
559         *  by using the card= parameter in conf file
560         */
561        for (i = 0; piv_aids[i].len_long != 0; i++) {
562                if (card->type > SC_CARD_TYPE_PIV_II_BASE &&
563                        card->type < SC_CARD_TYPE_PIV_II_BASE+1000 &&
564                        card->type != piv_aids[i].enumtag) {
565                                continue;
566                }
567                sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
568                apdu.lc = piv_aids[i].len_long;
569                apdu.data = piv_aids[i].value;
570       
571                apdu.datalen = apdu.lc;
572                apdu.resp = rbuf;
573                apdu.resplen = sizeof(rbuf);
574                apdu.le = 256;
575
576                r = sc_transmit_apdu(card, &apdu);
577                SC_TEST_RET(card->ctx, r, "APDU transmit failed");
578
579                r = sc_check_sw(card, apdu.sw1, apdu.sw2);
580       
581
582                if (r)  {
583                        if (card->type != 0 && card->type == piv_aids[i].enumtag) {
584                                SC_FUNC_RETURN(card->ctx, 1, i);
585                        }
586                        continue;
587                }
588
589                if ( apdu.resplen == 0 && r == 0) {
590                        /* could be the MSU card */
591                        continue; /* other cards will return a FCI */
592                }
593
594                if (apdu.resp[0] != 0x6f || apdu.resp[1] > apdu.resplen - 2 )
595                        SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NO_CARD_SUPPORT);
596       
597                card->ops->process_fci(card, aid_file, apdu.resp+2, apdu.resp[1]);
598                if (aid_file->name == NULL)
599                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NO_CARD_SUPPORT);
600
601                SC_FUNC_RETURN(card->ctx, 1, i);
602        }
603       
604        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NO_CARD_SUPPORT);
605}
606
607
608/* the tag is the PIV_OBJ_*  */
609static int piv_get_data(sc_card_t * card, unsigned int enumtag,
610                        u8 **buf, size_t *buf_len)
611{
612        piv_private_data_t * priv = PIV_DATA(card);
613        u8 *p;
614        int r = 0;
615        u8 tagbuf[8];
616        size_t tag_len;
617        char * keyenvname = NULL;
618       
619        SC_FUNC_CALLED(card->ctx,1);
620        sc_debug(card->ctx, "get_data: tag=%d \n", enumtag);
621
622        tag_len = piv_objects[enumtag].tag_len;
623
624        p = tagbuf;
625        put_tag_and_len(0x5c, tag_len, &p);
626        memcpy(p, piv_objects[enumtag].tag_value, tag_len);
627        p += tag_len;
628
629
630        /*
631         * the PIV card will only recover the public key during a generate
632         * key operation. If the piv-tool was used it would save this
633         * as an OpenSSL EVP_KEY PEM using the -o parameter
634         * we will look to see if there is a file then load it
635         * this is ugly, and maybe the pkcs15 cache would work
636         * but we only need it to get the OpenSSL req with engine to work.
637         * Each of the 4 keys with certs has its own file.
638         */
639
640        switch (piv_objects[enumtag].enumtag) {
641                case PIV_OBJ_9A06:
642                        keyenvname = "PIV_9A06_KEY";
643                        break;
644                case PIV_OBJ_9C06:
645                        keyenvname = "PIV_9C06_KEY";
646                        break;
647                case PIV_OBJ_9D06:
648                        keyenvname = "PIV_9D06_KEY";
649                        break;
650                case PIV_OBJ_9E06:
651                        keyenvname = "PIV_9E06_KEY";
652                        break;
653        }
654
655        if (keyenvname)  {
656                BIO * bp = NULL;
657                RSA * rsa = NULL;
658                u8 *q;
659                size_t derlen;
660                size_t taglen;
661                char * keyfilename = NULL;
662
663                keyfilename = getenv(keyenvname);
664
665                if (keyfilename == NULL) {
666                        r = SC_ERROR_FILE_NOT_FOUND;
667                        goto err;
668                }
669                sc_debug(card->ctx, "USING PUB KEY FROM FILE %s",keyfilename);
670
671                bp = BIO_new(BIO_s_file());
672                if (bp == NULL) {
673                        r = SC_ERROR_INTERNAL;
674                        goto err;
675                }
676                if (BIO_read_filename(bp, keyfilename) <= 0) {
677                        BIO_free(bp);
678                        r = SC_ERROR_FILE_NOT_FOUND;
679                        goto err;
680                }
681                rsa = PEM_read_bio_RSAPublicKey(bp, &rsa, NULL, NULL);
682                BIO_free(bp);
683                if (!rsa) {
684                        sc_debug(card->ctx,"Unable to load the public key");
685                        r =  SC_ERROR_DATA_OBJECT_NOT_FOUND;
686                        goto err;
687                }
688
689
690                derlen = i2d_RSAPublicKey(rsa, NULL);
691                if (derlen <= 0) {
692                        r =  SC_ERROR_DATA_OBJECT_NOT_FOUND;
693                        goto err;
694                }
695                taglen = put_tag_and_len(0x99, derlen, NULL);
696                *buf_len = put_tag_and_len(0x53, taglen, NULL);
697
698                *buf = (u8*) malloc(*buf_len);
699                if (*buf  == NULL) {
700                        r = SC_ERROR_OUT_OF_MEMORY;
701                        goto err;
702                }
703                q = *buf;
704
705                put_tag_and_len(0x53, taglen, &q);
706                put_tag_and_len(0x99, derlen, &q);
707
708                i2d_RSAPublicKey(rsa, &q);
709     
710                RSA_free(rsa);
711       
712                priv->eof = 1;
713
714                /* end of read PIV_OBJ_9A06 from file */
715        } else {
716
717                r = piv_general_io(card, 0xCB, 0x3F, 0xFF, tagbuf,  p - tagbuf,
718                        buf, buf_len);
719        }
720
721err:
722
723        SC_FUNC_RETURN(card->ctx, 1, r);
724}
725
726
727static int piv_handle_certificate_data(sc_card_t *card,
728                int enumtag,
729                unsigned idx, u8* buf, size_t count,
730                u8* data, size_t length) {
731        piv_private_data_t * priv = PIV_DATA(card);
732        u8* tag;
733        size_t taglen;
734        int compressed = 0;
735        piv_cache_item* item;
736        /* get the certificate out */
737        tag = (u8 *) sc_asn1_find_tag(card->ctx, data, length, 0x71, &taglen);
738        /* 800-72-1 not clear if this is 80 or 01 Sent comment to NIST for 800-72-2 */
739        if (tag && (((*tag) & 0x80) || ((*tag) & 0x01))) {
740                compressed = 1;
741        }
742        tag = (u8 *) sc_asn1_find_tag(card->ctx, data,  length, 0x70, &taglen);
743        if (tag == NULL) {
744        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
745        }
746        /* Potential truncation */
747        if(compressed) {
748#ifdef ENABLE_ZLIB
749                size_t len = count;
750                u8* newBuf = NULL;
751                if(SC_SUCCESS != sc_decompress_alloc(&newBuf, &len, tag, taglen, COMPRESSION_AUTO)) {
752                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
753                } else {
754                        if(len < count + idx)
755                                count = len - idx;
756                        if(count <= 0)
757                                SC_FUNC_RETURN(card->ctx, 1, 0);
758                        memcpy(buf, newBuf + idx, count);
759                        if(0 != add_cache_item(priv, enumtag, newBuf, len)) {
760                                /* Failed to cache item */
761                                free(newBuf);
762                        }
763                }
764                SC_FUNC_RETURN(card->ctx, 1, count);
765#else
766                sc_error(card->ctx,"PIV compression not supported, no zlib");
767                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
768#endif
769        }
770        if(taglen < count + idx)
771                count = taglen - idx;
772        if(count <= 0)
773                SC_FUNC_RETURN(card->ctx, 1, 0);
774        memcpy(buf, tag, count);
775        if(0 == add_cache_item(priv, enumtag, NULL, 0)) {
776                /* Space available in the cache array, use it */
777                item = get_cache_item(priv, enumtag);
778                if(item) {
779                        item->data = malloc(taglen);
780                        if(item->data) {
781                                item->length = taglen;
782                                memcpy(item->data, tag, taglen);
783                        }
784                }
785        }
786        SC_FUNC_RETURN(card->ctx, 1, count);
787}
788
789static int piv_handle_data(sc_card_t *card, int enumtag,
790                unsigned idx, u8* buf, size_t count, u8* data, size_t length) {
791        /* We need to return the whole not just first tag */
792        piv_private_data_t * priv = PIV_DATA(card);
793        u8* tag;
794        size_t taglen;
795        size_t reallen;
796        piv_cache_item* item;
797       
798        SC_FUNC_CALLED(card->ctx,1);
799
800        tag = (u8 *) sc_asn1_find_tag(card->ctx, data,  length, *data, &taglen);
801        if (tag == NULL) {
802                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
803        }
804        reallen = tag - data + taglen;
805        if (reallen > length)
806                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
807
808        if(reallen < count + idx)
809                count = reallen - idx;
810        if(count <= 0)
811                return 0;
812        memcpy(buf, data + idx, count);
813        if(0 == add_cache_item(priv, enumtag, NULL, 0)) {
814                item = get_cache_item(priv, enumtag);
815                if(item) {
816                        item->data = malloc(reallen);
817                        if(item->data) {
818                                item->length = reallen;
819                                memcpy(item->data, data, reallen);
820                        }
821                }
822        }
823        return count;
824}
825/*
826 * Callers of this are expecting a file without tags,
827 * So we need to know what type of file this is, so we can get the
828 * correct object out of the taged data returned by get_data
829 * Note the select file will have saved the object type for us.
830 */
831static int piv_read_binary(sc_card_t *card, unsigned int idx,
832                unsigned char *buf, size_t count, unsigned long flags)
833{
834        piv_private_data_t * priv = PIV_DATA(card);
835        piv_cache_item* item = NULL;
836        int enumtag;
837        int r;
838        u8 *rbuf = NULL;
839        size_t rbuflen = 0;
840        u8 *tag;
841        size_t taglen;
842        u8 *body;
843        size_t bodylen;
844
845        SC_FUNC_CALLED(card->ctx,1);
846        if (priv->selected_obj < 0)
847                 SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
848        enumtag = piv_objects[priv->selected_obj].enumtag;
849
850        if (priv->eof == 1)
851                return 0;
852
853        /* Hit the cache */
854        if(priv->current_item) {
855                item = priv->current_item;
856                if(idx + count > item->length) {
857                        count = item->length - idx;
858                }
859                if(count <= 0) {
860                        priv->eof = 1;
861                        return 0;
862                }
863                memcpy(buf, item->data + idx, count);
864                return count;
865        }
866
867
868        r = piv_get_data(card, priv->selected_obj, &rbuf, &rbuflen);
869       
870        if (r >=0) {
871                /* if tag is 0, assume card is telling us no object on card */
872                if (!rbuf || rbuf[0] == 0x00 || (rbuf[0] == 0x53 && rbuf[1] == 0x00)) {
873                        r = SC_ERROR_FILE_NOT_FOUND;
874                        goto err;
875                }
876                sc_debug(card->ctx, "DEE rbuf=%p,rbuflen=%d,",rbuf, rbuflen);
877                body = (u8 *) sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x53, &bodylen);
878                if (body == NULL) {
879                        /* if missing, assume its the body */
880                        /* DEE bug in the beta card */
881                        sc_debug(card->ctx," ***** tag 0x53 MISSING \n");
882                        r = SC_ERROR_INVALID_DATA;
883                        goto err;
884                }
885                if (bodylen > body - rbuf + rbuflen) {
886                        sc_debug(card->ctx," ***** tag length > then data: %d>%d+%d",
887                                bodylen , body - rbuf, rbuflen);
888                        r = SC_ERROR_INVALID_DATA;
889                        goto err;
890                }
891                switch (enumtag) {
892                        case PIV_OBJ_X509_PIV_AUTH:
893                        case PIV_OBJ_X509_DS:
894                        case PIV_OBJ_X509_KM:
895                        case PIV_OBJ_X509_CARD_AUTH:
896                                if (priv->return_only_cert)
897                                        r = piv_handle_certificate_data(card, enumtag, idx, buf, count, body, bodylen);
898                                else
899                                        r = piv_handle_data(card, enumtag, idx, buf, count, rbuf, rbuflen);
900                                break;
901                        case PIV_OBJ_9A06:
902                        case PIV_OBJ_9C06:
903                        case PIV_OBJ_9D06:
904                        case PIV_OBJ_9E06:
905                                tag = (u8 *) sc_asn1_find_tag(card->ctx, body,  bodylen,
906                                                *body, &taglen);
907                                if (tag == NULL) {
908                                        r = SC_ERROR_OBJECT_NOT_VALID;
909                                        break;
910                                }
911                                memcpy(buf, tag, taglen); /*DEE should check lengths */
912                                r = taglen;
913                                break;
914                       
915                        default:
916                                /* send whole object, tags and all */
917                                r = piv_handle_data(card, enumtag, idx, buf, count, rbuf, rbuflen);
918                                break;
919                }
920        }
921err:
922        if (rbuf)
923                free(rbuf);
924        SC_FUNC_RETURN(card->ctx, 1, r);
925}
926
927 
928/*
929 * the tag is the PIV_OBJ_*   
930 * The buf should have the 0x53 tag+len+tags and data
931 */
932
933static int piv_put_data(sc_card_t *card, unsigned int tag,
934                const u8 *buf, size_t buf_len)
935{
936        int r;
937        u8 * sbuf;
938        size_t sbuflen;
939        u8 * p;
940        size_t tag_len;
941
942        SC_FUNC_CALLED(card->ctx,1);
943
944        tag_len = piv_objects[tag].tag_len;
945        sbuflen = put_tag_and_len(0x5c, tag_len, NULL) + buf_len;
946        if (!(sbuf = (u8 *) malloc(sbuflen)))
947                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
948
949        p = sbuf;
950        put_tag_and_len(0x5c, tag_len, &p);
951        memcpy(p, piv_objects[tag].tag_value, tag_len);
952        p += tag_len;
953       
954        memcpy(p, buf, buf_len);
955        p += buf_len;
956
957        r = piv_general_io(card, 0xDB, 0x3F, 0xFF,
958                        sbuf, p - sbuf, NULL, NULL);
959
960        if (sbuf)
961                free(sbuf);
962        SC_FUNC_RETURN(card->ctx, 1, r);
963}
964
965static int piv_write_certificate(sc_card_t *card,
966                unsigned idx, const u8* buf, size_t count,
967                unsigned long flags) {
968        piv_private_data_t * priv = PIV_DATA(card);
969        int r = SC_SUCCESS;
970        u8 *sbuf = NULL;
971        u8 *p;
972        size_t sbuflen;
973        size_t taglen;
974
975        sc_debug(card->ctx,"DEE cert len=%d",count);
976        taglen = put_tag_and_len(0x70, count, NULL)
977                + put_tag_and_len(0x71, 1, NULL)
978                + put_tag_and_len(0xFE, 0, NULL);
979
980        sbuflen =  put_tag_and_len(0x53, taglen, NULL);
981
982        sbuf = (u8*) malloc(sbuflen);
983        if (sbuf == NULL)
984                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
985        p = sbuf;
986        put_tag_a