From 6a4de6d55191e3d8842f0a96cc843e2106ff3f55 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 6 Jan 2013 17:27:02 +0100 Subject: [PATCH] libopensc: APDU 'allocate & copy'and 'free' procedures --- src/libopensc/card.c | 62 +++++++++++++++++++++++++++++++-- src/libopensc/libopensc.exports | 3 ++ src/libopensc/opensc.h | 12 ++++--- src/libopensc/types.h | 32 ++++++++++------- 4 files changed, 91 insertions(+), 18 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 0f98179d..53cb1f8a 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -61,6 +61,55 @@ void sc_format_apdu(sc_card_t *card, sc_apdu_t *apdu, apdu->p2 = (u8) p2; } +struct sc_apdu * +sc_allocate_apdu(struct sc_apdu *copy_from, unsigned flags) +{ + struct sc_apdu *apdu = NULL; + + assert(copy_from != NULL); + apdu = (struct sc_apdu *)malloc(sizeof(struct sc_apdu)); + if (!copy_from || !apdu) + return apdu; + memcpy(apdu, copy_from, sizeof(struct sc_apdu)); + apdu->data = apdu->resp = NULL; + apdu->next = NULL; + apdu->datalen = apdu->resplen = 0; + apdu->allocation_flags = SC_APDU_ALLOCATE_FLAG; + + if ((flags & SC_APDU_ALLOCATE_FLAG_DATA) && copy_from->data && copy_from->datalen) { + apdu->data = malloc(copy_from->datalen); + if (!apdu->data) + return NULL; + memcpy(apdu->data, copy_from->data, copy_from->datalen); + apdu->datalen = copy_from->datalen; + apdu->allocation_flags |= SC_APDU_ALLOCATE_FLAG_DATA; + } + + if ((flags & SC_APDU_ALLOCATE_FLAG_RESP) && copy_from->resp && copy_from->resplen) { + apdu->resp = malloc(copy_from->resplen); + if (!apdu->resp) + return NULL; + memcpy(apdu->resp, copy_from->resp, copy_from->resplen); + apdu->resplen = copy_from->resplen; + apdu->allocation_flags |= SC_APDU_ALLOCATE_FLAG_RESP; + } + return apdu; +} + +void +sc_free_apdu(struct sc_apdu *apdu) +{ + if (!apdu) + return; + if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG_DATA) + free (apdu->data); + if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG_RESP) + free (apdu->resp); + if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG) + free (apdu); +} + + static sc_card_t * sc_card_new(sc_context_t *ctx) { sc_card_t *card; @@ -968,32 +1017,40 @@ int _sc_add_atr(sc_context_t *ctx, struct sc_card_driver *driver, struct sc_atr_ if (!map) return SC_ERROR_OUT_OF_MEMORY; driver->atr_map = map; + dst = &driver->atr_map[driver->natrs++]; memset(dst, 0, sizeof(*dst)); memset(&driver->atr_map[driver->natrs], 0, sizeof(struct sc_atr_table)); dst->atr = strdup(src->atr); if (!dst->atr) return SC_ERROR_OUT_OF_MEMORY; + if (src->atrmask) { dst->atrmask = strdup(src->atrmask); if (!dst->atrmask) return SC_ERROR_OUT_OF_MEMORY; - } else { + } + else { dst->atrmask = NULL; } + if (src->name) { dst->name = strdup(src->name); if (!dst->name) return SC_ERROR_OUT_OF_MEMORY; - } else { + } + else { dst->name = NULL; } + dst->type = src->type; dst->flags = src->flags; dst->card_atr = src->card_atr; + return SC_SUCCESS; } + int _sc_free_atr(sc_context_t *ctx, struct sc_card_driver *driver) { unsigned int i; @@ -1197,6 +1254,7 @@ sc_card_sm_check(struct sc_card *card) int rv, ii; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); + sc_log(ctx, "card->sm_ctx.ops.open %p", card->sm_ctx.ops.open); /* get the name of card specific SM configuration section */ atrblock = _sc_match_atr_block(ctx, card->driver, &card->atr); diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index e677f129..c98ce80c 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -99,6 +99,8 @@ sc_file_set_sec_attr sc_file_set_type_attr sc_file_valid sc_format_apdu +sc_allocate_apdu +sc_free_apdu sc_bytes2apdu sc_format_asn1_entry sc_format_oid @@ -300,6 +302,7 @@ sc_pkcs15init_verify_secret sc_pkcs15init_sanity_check sc_pkcs15init_finalize_profile sc_card_find_rsa_alg +sc_check_apdu sc_print_cache sc_find_app sc_remote_data_init diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ad61b4a5..e0afe109 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -166,7 +166,7 @@ typedef struct sc_security_env { unsigned int algorithm_ref; struct sc_path file_ref; - u8 key_ref[8]; + unsigned char key_ref[8]; size_t key_ref_len; struct sc_supported_algo_info supported_algos[SC_MAX_SUPPORTED_ALGORITHMS]; @@ -719,10 +719,14 @@ typedef struct sc_context { * @param apdu sc_apdu_t object of the APDU to be send * @return SC_SUCCESS on succcess and an error code otherwise */ -int sc_transmit_apdu(struct sc_card *card, sc_apdu_t *apdu); +int sc_transmit_apdu(struct sc_card *, struct sc_apdu *); -void sc_format_apdu(struct sc_card *card, sc_apdu_t *apdu, int cse, int ins, - int p1, int p2); +void sc_format_apdu(struct sc_card *, struct sc_apdu *, int, int, int, int); + +int sc_check_apdu(struct sc_card *, const struct sc_apdu *); + +struct sc_apdu *sc_allocate_apdu(struct sc_apdu *, unsigned); +void sc_free_apdu(struct sc_apdu *); /** Transforms an APDU from binary to its @c sc_apdu_t representation * @param ctx sc_context_t object (used for logging) diff --git a/src/libopensc/types.h b/src/libopensc/types.h index e1a24fe5..79fee1de 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -174,8 +174,11 @@ struct sc_crt { #define SC_AC_OP_WRITE 24 #define SC_AC_OP_RESIZE 25 #define SC_AC_OP_GENERATE 26 +#define SC_AC_OP_CREATE_EF 27 +#define SC_AC_OP_CREATE_DF 28 +#define SC_AC_OP_ADMIN 29 /* If you add more OPs here, make sure you increase SC_MAX_AC_OPS*/ -#define SC_MAX_AC_OPS 27 +#define SC_MAX_AC_OPS 30 /* the use of SC_AC_OP_ERASE is deprecated, SC_AC_OP_DELETE should be used * instead */ @@ -263,18 +266,23 @@ typedef struct sc_file { */ #define SC_APDU_FLAGS_NO_RETRY_WL 0x00000004UL -typedef struct sc_apdu { - int cse; /* APDU case */ - u8 cla, ins, p1, p2; /* CLA, INS, P1 and P2 bytes */ - size_t lc, le; /* Lc and Le bytes */ - const u8 *data; /* C-APDU data */ - size_t datalen; /* length of data in C-APDU */ - u8 *resp; /* R-APDU data buffer */ - size_t resplen; /* in: size of R-APDU buffer, - * out: length of data returned in R-APDU */ - u8 control; /* Set if APDU should go to the reader */ +#define SC_APDU_ALLOCATE_FLAG 0x01 +#define SC_APDU_ALLOCATE_FLAG_DATA 0x02 +#define SC_APDU_ALLOCATE_FLAG_RESP 0x04 - unsigned int sw1, sw2; /* Status words returned in R-APDU */ +typedef struct sc_apdu { + int cse; /* APDU case */ + unsigned char cla, ins, p1, p2; /* CLA, INS, P1 and P2 bytes */ + size_t lc, le; /* Lc and Le bytes */ + unsigned char *data; /* C-APDU data */ + size_t datalen; /* length of data in C-APDU */ + unsigned char *resp; /* R-APDU data buffer */ + size_t resplen; /* in: size of R-APDU buffer, + * out: length of data returned in R-APDU */ + unsigned char control; /* Set if APDU should go to the reader */ + unsigned allocation_flags; /* APDU allocation flags */ + + unsigned int sw1, sw2; /* Status words returned in R-APDU */ unsigned char mac[8]; size_t mac_len;