Ticket #128: new_piv.patch

File new_piv.patch, 54.8 KB (added by harningt, 2 years ago)

New PIV patch, resolves some compile problems

  • src/libopensc/compression.c

     
     1/* 
     2 * compression.c: Generic wrapper for compression of data 
     3 * 
     4 * Copyright (C) 2006, Identity Alliance, Thomas Harning <thomas.harning@identityalliance.com> 
     5 * 
     6 * This library is free software; you can redistribute it and/or 
     7 * modify it under the terms of the GNU Lesser General Public 
     8 * License as published by the Free Software Foundation; either 
     9 * version 2.1 of the License, or (at your option) any later version. 
     10 * 
     11 * This library is distributed in the hope that it will be useful, 
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     14 * Lesser General Public License for more details. 
     15 * 
     16 * You should have received a copy of the GNU Lesser General Public 
     17 * License along with this library; if not, write to the Free Software 
     18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     19 */ 
     20#include "compression.h" 
     21 
     22#include <zlib.h> 
     23#include <memory.h> 
     24#include <stdlib.h> 
     25#include "errors.h" 
     26 
     27static int zerr_to_opensc(int err) { 
     28        switch(err) { 
     29        case Z_OK: 
     30        case Z_STREAM_END: 
     31                return SC_SUCCESS; 
     32        case Z_UNKNOWN: 
     33                return SC_ERROR_UNKNOWN; 
     34        case Z_BUF_ERROR: 
     35        case Z_MEM_ERROR: 
     36                return SC_ERROR_MEMORY_FAILURE; 
     37        case Z_VERSION_ERROR: 
     38        case Z_DATA_ERROR: 
     39        case Z_STREAM_ERROR: 
     40        //case Z_NEED_DICT: 
     41        default: 
     42                return SC_ERROR_INTERNAL; 
     43        } 
     44} 
     45static int detect_method(const u8* in, size_t inLen) { 
     46        if(inLen > 2 && in[0] == 0x1f && in[1] == 0x8b) { /* GZIP */ 
     47                return COMPRESSION_GZIP; 
     48        } else if(inLen > 1 /*&& (in[0] & 0x10) == Z_DEFLATED*/) { 
     49                /* REALLY SIMPLE ZLIB TEST --  
     50                 * Check for the compression method to be set to 8... 
     51                 * many things can spoof this, but this is ok for now 
     52                 * */ 
     53                return COMPRESSION_ZLIB; 
     54        } else { 
     55                return COMPRESSION_UNKNOWN; 
     56        } 
     57} 
     58 
     59static int do_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) { 
     60        /* Since uncompress does not offer a way to make it uncompress gzip... manually set it up */ 
     61        z_stream gz; 
     62        int err; 
     63        int window_size = 15 + 0x20; 
     64        memset(&gz, 0, sizeof(gz)); 
     65 
     66        gz.next_in = (u8*)in; 
     67        gz.avail_in = inLen; 
     68        gz.next_out = out; 
     69        gz.avail_out = *outLen; 
     70 
     71        err = inflateInit2(&gz, window_size); 
     72        if(err != Z_OK) return zerr_to_opensc(err); 
     73        err = inflate(&gz, Z_FINISH); 
     74        if(err != Z_STREAM_END) { 
     75                inflateEnd(&gz); 
     76                return zerr_to_opensc(err); 
     77        } 
     78        *outLen = gz.total_out; 
     79 
     80        err = inflateEnd(&gz); 
     81        return zerr_to_opensc(err);      
     82} 
     83 
     84int do_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) { 
     85        if(method == COMPRESSION_AUTO) { 
     86                method = detect_method(in, inLen); 
     87                if(method == COMPRESSION_UNKNOWN) { 
     88                        return SC_ERROR_UNKNOWN_DATA_RECEIVED; 
     89                } 
     90        } 
     91        switch(method) { 
     92        case COMPRESSION_ZLIB: 
     93                return zerr_to_opensc(uncompress(out, outLen, in, inLen)); 
     94        case COMPRESSION_GZIP: 
     95                return do_decompress_gzip(out, outLen, in, inLen); 
     96        default: 
     97                return SC_ERROR_INVALID_ARGUMENTS; 
     98        } 
     99} 
     100 
     101static int do_decompress_zlib_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int gzip) { 
     102        /* Since uncompress does not offer a way to make it uncompress gzip... manually set it up */ 
     103        z_stream gz; 
     104        int err; 
     105        int window_size = 15; 
     106        const int startSize = inLen < 1024 ? 2048 : inLen * 2; 
     107        const int blockSize = inLen < 1024 ? 512 : inLen / 2; 
     108        int bufferSize = startSize; 
     109        if(gzip) 
     110                window_size += 0x20; 
     111        memset(&gz, 0, sizeof(gz)); 
     112         
     113        gz.next_in = (u8*)in; 
     114        gz.avail_in = inLen; 
     115 
     116        err = inflateInit2(&gz, window_size); 
     117        if(err != Z_OK) return zerr_to_opensc(err); 
     118 
     119        *outLen = 0; 
     120 
     121        while(1) { 
     122                /* Setup buffer... */ 
     123                int num; 
     124                u8* buf = realloc(*out, bufferSize); 
     125                if(!buf) { 
     126                        if(*out) 
     127                                free(*out); 
     128                        *out = NULL; 
     129                        return Z_MEM_ERROR; 
     130                } 
     131                *out = buf; 
     132                gz.next_out = buf + *outLen; 
     133                gz.avail_out = bufferSize - *outLen; 
     134 
     135                err = inflate(&gz, Z_FULL_FLUSH); 
     136                if(err != Z_STREAM_END && err != Z_OK) { 
     137                        if(*out) 
     138                                free(*out); 
     139                        *out = NULL; 
     140                        break; 
     141                } 
     142                num = bufferSize - *outLen - gz.avail_out; 
     143                if(num > 0) { 
     144                        *outLen += num; 
     145                        bufferSize += num + blockSize; 
     146                } 
     147                if(err == Z_STREAM_END) { 
     148                        buf = realloc(buf, *outLen); /* Shrink it down, if it fails, just use old data */ 
     149                        if(buf) { 
     150                                *out = buf; 
     151                        } 
     152                        break; 
     153                } 
     154        } 
     155        inflateEnd(&gz); 
     156        return zerr_to_opensc(err); 
     157} 
     158int do_decompress_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int method) { 
     159        if(method == COMPRESSION_AUTO) { 
     160                method = detect_method(in, inLen); 
     161                if(method == COMPRESSION_UNKNOWN) { 
     162                        return SC_ERROR_UNKNOWN_DATA_RECEIVED; 
     163                } 
     164        } 
     165        switch(method) { 
     166        case COMPRESSION_ZLIB: 
     167                return do_decompress_zlib_alloc(out, outLen, in, inLen, 0); 
     168        case COMPRESSION_GZIP: 
     169                return do_decompress_zlib_alloc(out, outLen, in, inLen, 1); 
     170        default: 
     171                return SC_ERROR_INVALID_ARGUMENTS; 
     172        } 
     173} 
  • src/libopensc/card-piv.c

     
    44 * 
    55 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi> 
    66 * Copyright (C) 2005, Douglas E. Engert <deengert@anl.gov> 
     7 * Copyright (C) 2006, Identity Alliance, Thomas Harning <thomas.harning@identityalliance.com> 
    78 * 
    89 * This library is free software; you can redistribute it and/or 
    910 * modify it under the terms of the GNU Lesser General Public 
     
    2930#include <openssl/rsa.h> 
    3031#include "asn1.h" 
    3132#include "cardctl.h" 
     33#include "compression.h" 
    3234 
    33 struct piv_private_data { 
     35typedef struct { 
     36        u8* data; 
     37        size_t length; 
     38        int enumtag; 
     39} piv_cache_item; 
     40 
     41typedef struct piv_private_data { 
    3442        struct sc_pin_cmd_pin pin_info; 
    3543        sc_file_t *aid_file; 
    3644        int enumtag; 
     
    3947        size_t max_recv_size; /* saved size, need to lie to pkcs15_read_file */ 
    4048        size_t max_send_size;  
    4149        int key_ref; /* saved from set_security_env and */ 
    42         int alg_id;  /* used in decrypy, signature */  
    43 }; 
     50        int alg_id;  /* used in decrypt, signature */  
     51        piv_cache_item* cache; 
     52        int cacheLen; 
     53        piv_cache_item* current_item; 
     54} piv_private_data_t; 
    4455 
     56#define PIV_DATA(card) ((piv_private_data_t*)card->drv_data) 
     57 
     58static int add_cache_item(piv_private_data_t* priv, int enumtag, u8* data, size_t length) { 
     59        int idx, len = priv->cacheLen; 
     60        piv_cache_item* cache = priv->cache; 
     61        for(idx = 0; idx < len; idx++) { 
     62                if(!cache[idx].data) 
     63                        break; 
     64                if(cache[idx].enumtag == enumtag) /* Found matching tag */ 
     65                        break; 
     66        } 
     67        if(idx == len)  
     68                return -1; /* FAILED NO FREE ROOM */ 
     69        if(cache[idx].data) 
     70                free(cache[idx].data); 
     71        cache[idx].data = data; 
     72        cache[idx].length = length; 
     73        cache[idx].enumtag = enumtag; 
     74        return 0; 
     75} 
     76 
     77static piv_cache_item* get_cache_item(piv_private_data_t* priv, int enumtag) { 
     78        int idx, len = priv->cacheLen; 
     79        piv_cache_item* cache = priv->cache; 
     80        for(idx = 0; idx < len; idx++) { 
     81                if(cache[idx].enumtag == enumtag) 
     82                        return &cache[idx]; 
     83        } 
     84        return NULL; 
     85} 
     86 
     87static void free_cache_items(piv_private_data_t* priv) { 
     88        int idx, len = priv->cacheLen; 
     89        piv_cache_item* cache = priv->cache; 
     90        for(idx = 0; idx < len; idx++) { 
     91                if(cache[idx].data) { 
     92                        free(cache[idx].data); 
     93                        cache[idx].data = NULL; 
     94                } 
     95        } 
     96} 
     97 
    4598struct piv_aid { 
    4699        int enumtag; 
    47100        size_t len_short;       /* min lenght without version */ 
     
    71124        PIV_OBJ_X509_CARD_AUTH, 
    72125        PIV_OBJ_SEC_OBJ, 
    73126        PIV_OBJ_9B03, 
    74         PIV_OBJ_9A06 
     127        PIV_OBJ_9A06, 
     128        PIV_CACHE_SIZE 
    75129}; 
    76130 
    77131struct piv_object { 
     
    88142        { PIV_OBJ_CCC, "Card Capability Container",  
    89143                        "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 266}, 
    90144        { PIV_OBJ_CHUI, "Card Holder Unique Identifier",  
    91                         "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 3377}, 
     145                        "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 3379}, /* Updated per SP800-73-1 Errata */ 
    92146        { PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication",  
    93147                        "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", 1856+4+400} ,  
    94148                /* extra 400 is hack for MultOS card which returns 2200 bytes  */ 
    95         { PIV_OBJ_CHF1, "Card Holder Fingerprint I", 
    96                         "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x01", 7768}, 
    97         { PIV_OBJ_CHF2, "Card Holder Fingerprint II", 
    98                         "2.16.840.1.101.3.7.2.96.17", 3, "\x5F\xC1\x04", "\x60\x11", 7768}, 
     149        { PIV_OBJ_CHF1, "Card Holder Fingerprints", 
     150                        "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 7768}, 
    99151        { PIV_OBJ_PI, "Printed Information",  
    100152                        "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 106}, 
    101153        { PIV_OBJ_CHFI, "Card Holder Facial Image", 
     
    184236        const u8 * sendbuf, size_t sendbuflen, u8 ** recvbuf, 
    185237        size_t * recvbuflen) 
    186238{ 
    187         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     239        piv_private_data_t * priv = PIV_DATA(card); 
    188240        int r; 
    189241        sc_apdu_t apdu; 
    190242        u8 rbufinitbuf[20000]; /* crude way to do this  see above comments */ 
     
    502554static int piv_get_data(sc_card_t * card, unsigned int enumtag,  
    503555                        u8 **buf, size_t *buf_len) 
    504556{ 
    505         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     557        piv_private_data_t * priv = PIV_DATA(card); 
    506558        u8 *p; 
    507559        int r = 0; 
    508560        u8 tagbuf[8]; 
    509561        size_t tag_len; 
    510                  
     562         
    511563        SC_FUNC_CALLED(card->ctx,1); 
    512564        sc_debug(card->ctx, "get_data: tag=%d \n", enumtag); 
    513565 
     
    599651 
    600652        SC_FUNC_RETURN(card->ctx, 1, r); 
    601653} 
    602            
     654 
     655 
     656static int piv_handle_certificate_data(sc_card_t *card, 
     657                int enumtag, 
     658                unsigned idx, u8* buf, size_t count, 
     659                u8* data, size_t length) { 
     660        piv_private_data_t * priv = PIV_DATA(card); 
     661        u8* tag; 
     662        size_t taglen; 
     663        int compressed = 0; 
     664        piv_cache_item* item; 
     665        /* get the certificate out */ 
     666        tag = (u8 *) sc_asn1_find_tag(card->ctx, data, length, 0x71, &taglen); 
     667        if (tag && (((*tag) & 0x80) || ((*tag) & 0x01))) { 
     668                compressed = 1; 
     669        } 
     670        tag = (u8 *) sc_asn1_find_tag(card->ctx, data,  length, 0x70, &taglen); 
     671        if (tag == NULL) { 
     672                return SC_ERROR_OBJECT_NOT_VALID; 
     673        } 
     674        /* Potential truncation */ 
     675        if(compressed) { 
     676                size_t len = count; 
     677                u8* newBuf = NULL; 
     678                if(SC_SUCCESS != do_decompress_alloc(&newBuf, &len, tag, taglen, COMPRESSION_AUTO)) { 
     679                        return SC_ERROR_OBJECT_NOT_VALID; 
     680                } else { 
     681                        if(len < count + idx) 
     682                                count = len - idx; 
     683                        if(count <= 0) 
     684                                return 0; 
     685                        memcpy(buf, newBuf + idx, count); 
     686                        if(0 != add_cache_item(priv, enumtag, newBuf, len)) { 
     687                                /* Failed to cache item */ 
     688                                free(newBuf); 
     689                        } 
     690                        priv->current_item = get_cache_item(priv, enumtag); 
     691                } 
     692                return count; 
     693        } 
     694        if(taglen < count + idx) 
     695                count = taglen - idx; 
     696        if(count <= 0) 
     697                return 0; 
     698        memcpy(buf, tag, count); 
     699        if(0 == add_cache_item(priv, enumtag, NULL, 0)) { 
     700                /* Space available in the cache array, use it */ 
     701                item = get_cache_item(priv, enumtag); 
     702                if(item) { 
     703                        item->data = malloc(taglen); 
     704                        if(item->data) { 
     705                                item->length = taglen; 
     706                                memcpy(item->data, tag, taglen); 
     707                        } 
     708                        priv->current_item = item; 
     709                } 
     710        } 
     711        return count; 
     712} 
     713 
     714static int piv_handle_data(sc_card_t *card, int enumtag,  
     715                unsigned idx, u8* buf, size_t count, u8* data, size_t length) { 
     716        /* For now get the first tag, and return the data */ 
     717        piv_private_data_t * priv = PIV_DATA(card); 
     718        u8* tag; 
     719        size_t taglen; 
     720        piv_cache_item* item; 
     721 
     722        tag = (u8 *) sc_asn1_find_tag(card->ctx, data,  length, *data, &taglen); 
     723        if (tag == NULL) { 
     724                return SC_ERROR_OBJECT_NOT_VALID; 
     725        } 
     726        if(taglen < count + idx) 
     727                count = taglen - idx; 
     728        if(count <= 0) 
     729                return 0; 
     730        memcpy(buf, tag + idx, count); 
     731        if(0 == add_cache_item(priv, enumtag, NULL, 0)) { 
     732                item = get_cache_item(priv, enumtag); 
     733                if(item) { 
     734                        item->data = malloc(taglen); 
     735                        if(item->data) { 
     736                                item->length = taglen; 
     737                                memcpy(item->data, tag, taglen); 
     738                        } 
     739                        priv->current_item = item; 
     740                } 
     741        } 
     742        return count; 
     743} 
    603744/*  
    604745 * Callers of this are expecting a file without tags, 
    605746 * So we need to know what type of file this is, so we can get the 
     
    609750static int piv_read_binary(sc_card_t *card, unsigned int idx, 
    610751                unsigned char *buf, size_t count, unsigned long flags) 
    611752{ 
    612         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     753        piv_private_data_t * priv = PIV_DATA(card); 
     754        piv_cache_item* item = NULL; 
     755        int enumtag; 
    613756        int r; 
    614757        u8 *rbuf = NULL; 
    615758        size_t rbuflen = 0; 
    616         u8 *tag; 
    617         size_t taglen; 
    618759        u8 *body; 
    619760        size_t bodylen; 
    620761 
    621762        SC_FUNC_CALLED(card->ctx,1); 
    622763        if (priv->selected_obj < 0)  
    623764                 SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL); 
     765        enumtag = piv_objects[priv->selected_obj].enumtag; 
    624766 
     767        /* Hit the cache */ 
     768        if(priv->current_item) { 
     769                item = priv->current_item; 
     770                if(idx + count > item->length) { 
     771                        count = item->length - idx; 
     772                } 
     773                if(count <= 0) 
     774                        return 0; 
     775                memcpy(buf, item->data + idx, count); 
     776                return count; 
     777        } 
     778 
    625779        if (priv->eof == 1) 
    626780                return 0; 
    627781 
     
    629783         
    630784        if (r >=0) { 
    631785                /* if tag is 0, assume card is telling us no object on card */ 
    632                 if (rbuf[0] == '0') { 
     786                if (!rbuf || rbuf[0] == '0') { 
    633787                        r = SC_ERROR_FILE_NOT_FOUND; 
    634788                        goto err; 
    635789                } 
     
    639793                        /* if missing, assume its the body */ 
    640794                        /* DEE bug in the beta card */ 
    641795                        sc_debug(card->ctx," ***** tag 0x53 MISSING \n"); 
    642                         body =  rbuf; 
    643                         bodylen = rbuflen; 
    644 #if 0 
    645796                        r = SC_ERROR_INVALID_DATA; 
    646797                        goto err; 
    647 #endif 
    648798                } 
    649                 switch (piv_objects[priv->selected_obj].enumtag) { 
     799                switch (enumtag) { 
    650800                        case PIV_OBJ_X509_PIV_AUTH: 
    651801                        case PIV_OBJ_X509_DS: 
    652802                        case PIV_OBJ_X509_KM: 
    653803                        case PIV_OBJ_X509_CARD_AUTH: 
    654                                 /* get the certificate out */ 
    655                                 tag = (u8 *) sc_asn1_find_tag(card->ctx, body,  bodylen, 0x70, &taglen); 
    656                                 if (tag == NULL) { 
    657                                         r = SC_ERROR_OBJECT_NOT_VALID; 
    658                                         break; 
    659                                 } 
    660                                 memcpy(buf, tag, taglen); /*DEE should check lengths */ 
    661                                 r = taglen; 
    662                                 tag = (u8 *) sc_asn1_find_tag(card->ctx, body,  bodylen, 0x71, &taglen); 
    663                                 if (tag && ((*tag) & 0x80)) { 
    664                                         sc_debug(card->ctx,0,"Cert is gziped! %0x2.2x\n",*tag); 
    665                                 } 
     804                                r = piv_handle_certificate_data(card, enumtag, idx, buf, count, body, bodylen); 
    666805                                break; 
    667806                        default: 
    668                                 /* For now get the first tag, and return the data */ 
    669                                 tag = (u8 *) sc_asn1_find_tag(card->ctx, body,  bodylen, *body, &taglen); 
    670                                 if (tag == NULL) { 
    671                                         r = SC_ERROR_OBJECT_NOT_VALID; 
    672                                         break; 
    673                                 } 
    674                                 memcpy(buf, tag, taglen); /*DEE should check lengths */ 
    675                                 r = taglen; 
     807                                r = piv_handle_data(card, enumtag, idx, buf, count, body, bodylen); 
    676808                                break; 
    677809                } 
    678810        } 
     
    720852        SC_FUNC_RETURN(card->ctx, 1, r); 
    721853} 
    722854 
     855static int piv_write_certificate(sc_card_t *card, 
     856                unsigned idx, const u8* buf, size_t count) { 
     857        piv_private_data_t * priv = PIV_DATA(card); 
     858        int r = SC_SUCCESS; 
     859        u8 *sbuf = NULL; 
     860        u8 *p; 
     861        size_t sbuflen; 
     862        size_t taglen; 
    723863 
     864        sc_debug(card->ctx,"DEE cert len=%d",count); 
     865        taglen = put_tag_and_len(0x70, count, NULL)  
     866                + put_tag_and_len(0x71, 1, NULL); 
     867 
     868        sbuflen =  put_tag_and_len(0x53, taglen, NULL); 
     869 
     870        sbuf = (u8*) malloc(sbuflen); 
     871        if (sbuf == NULL)  
     872                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY); 
     873        p = sbuf; 
     874        put_tag_and_len(0x53, taglen, &p); 
     875 
     876        put_tag_and_len(0x70, count, &p); 
     877        memcpy(p, buf, count); 
     878        p += count; 
     879        put_tag_and_len(0x71, 1, &p); 
     880        *p++ = 0x00; /* certinfo, i.e. not gziped */ 
     881        sc_debug(card->ctx,"DEE buf %p len %d %d", sbuf, p -sbuf, sbuflen); 
     882 
     883        r = piv_put_data(card, priv->selected_obj, sbuf, sbuflen); 
     884        if (sbuf) 
     885                free(sbuf); 
     886 
     887        return r; 
     888} 
    724889/*  
    725890 * We need to add the 0x53 tag and other specific tags,  
    726891 * and call the piv_put_data  
     
    730895static int piv_write_binary(sc_card_t *card, unsigned int idx, 
    731896                const u8 *buf, size_t count, unsigned long flags) 
    732897{ 
    733         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
    734         int r = 0; 
    735         u8 *sbuf = NULL; 
    736         u8 *p; 
    737         size_t sbuflen; 
    738         size_t taglen; 
    739          
     898        piv_private_data_t * priv = PIV_DATA(card); 
     899        /* TODO: Add cache hooks */      
    740900        SC_FUNC_CALLED(card->ctx,1); 
    741901 
    742902        if (priv->selected_obj < 0) 
     
    749909                case PIV_OBJ_X509_DS: 
    750910                case PIV_OBJ_X509_KM: 
    751911                case PIV_OBJ_X509_CARD_AUTH: 
    752                 sc_debug(card->ctx,"DEE cert len=%d",count); 
    753                  
    754                         taglen = put_tag_and_len(0x70, count, NULL)  
    755                                 + put_tag_and_len(0x71, 1, NULL); 
    756  
    757                         sbuflen =  put_tag_and_len(0x53, taglen, NULL); 
    758  
    759                         sbuf = (u8*) malloc(sbuflen); 
    760                         if (sbuf == NULL)  
    761                                 SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY); 
    762                         p = sbuf; 
    763                         put_tag_and_len(0x53, taglen, &p); 
    764  
    765                         put_tag_and_len(0x70, count, &p); 
    766                         memcpy(p, buf, count); 
    767                         p += count; 
    768                         put_tag_and_len(0x71, 1, &p); 
    769                         *p++ = 0x00; /* certinfo, i.e. not gziped */ 
    770                         sc_debug(card->ctx,"DEE buf %p len %d %d", sbuf, p -sbuf, sbuflen); 
    771                         break; 
    772                          
     912                        SC_FUNC_RETURN(card->ctx, 1, piv_write_certificate(card, idx, buf, count)); 
    773913                default: 
    774914                sc_debug(card->ctx, "Don't know how to write object %s\n", 
    775915                        piv_objects[priv->selected_obj].name); 
    776                         r = SC_ERROR_NOT_SUPPORTED; 
    777                         break; 
     916                        SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED); 
    778917        } 
    779  
    780         if (r == 0)  
    781                 r = piv_put_data(card, priv->selected_obj, sbuf, sbuflen); 
    782         if (sbuf) 
    783                 free(sbuf); 
    784  
    785         SC_FUNC_RETURN(card->ctx, 1, r); 
    786918} 
    787919 
    788920/* 
     
    9551087static int piv_general_external_authenticate(sc_card_t *card,  
    9561088                unsigned int key_ref, unsigned int alg_id) 
    9571089{ 
    958         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     1090        piv_private_data_t * priv = PIV_DATA(card); 
    9591091        int r; 
    9601092        u8  *rbuf = NULL; 
    9611093        size_t rbuflen; 
     
    10491181                        return piv_generate_key(card,  
    10501182                                (struct sc_cardctl_cryptoflex_genkey_info *) ptr); 
    10511183                        break; 
     1184                case SC_CARDCTL_PIV_GET_FULL_DATA: { 
     1185                        int ret; 
     1186                        piv_private_data_t * priv = PIV_DATA(card); 
     1187                        sc_cardctl_piv_get_full_data_t* data = (sc_cardctl_piv_get_full_data_t*)ptr; 
     1188                        /* Clear out the data so that failure returns leave data in a clean state */ 
     1189                        memset(data, 0, sizeof(sc_cardctl_piv_get_full_data_t)); 
     1190                        /* Make sure the cache item is fresh */ 
     1191                        { 
     1192                                /* In order for sc_read_binary to actually call into the card, 1 byte must be read... */ 
     1193                                u8 buf[1]; 
     1194                                ret = sc_read_binary(card, 0, buf, 1, 0); 
     1195                                if(ret < 0) return ret; 
     1196                        } 
     1197                        /* No cached item or the cached item is forcibly marked as non-existent */ 
     1198                        if(!priv->current_item || priv->current_item->length == -1)  
     1199                                return SC_ERROR_FILE_NOT_FOUND; 
     1200                        data->buf = priv->current_item->data; 
     1201                        data->length = priv->current_item->length; 
     1202                        data->should_free = 0; 
     1203                        return SC_SUCCESS; 
     1204                } 
    10521205        } 
    10531206 
    10541207        return SC_ERROR_NOT_SUPPORTED; 
     
    11081261                    const sc_security_env_t *env, 
    11091262                    int se_num) 
    11101263{ 
    1111         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     1264        piv_private_data_t * priv = (piv_private_data_t *) card->drv_data; 
    11121265         
    11131266        SC_FUNC_CALLED(card->ctx,1); 
    11141267 
     
    11381291                                        const u8 * data, size_t datalen, 
    11391292                                        u8 * out, size_t outlen) 
    11401293{ 
    1141         struct piv_private_data * priv = (struct piv_private_data *) card->drv_data; 
     1294        piv_private_data_t * priv = (piv_private_data_t *) card->drv_data; 
    11421295        int r; 
    11431296        u8 *p; 
    11441297        u8 *tag; 
     
    12271380static int piv_select_file(sc_card_t *card, const sc_path_t *in_path, 
    12281381        sc_file_t **file_out) 
    12291382{ 
    1230         str