diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 641dee0b..90812124 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -354,6 +354,7 @@ static int decode_bit_string(const u8 * inbuf, int inlen, void *outbuf, int octets_left = inlen - 1; int i, count = 0; + memset(outbuf, 0, outlen); in++; if (outlen < octets_left) return SC_ERROR_BUFFER_TOO_SMALL; @@ -527,7 +528,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr int *len = entry->len; int r = 0; - if (ctx->debug > 2) { + if (ctx->debug >= 3) { u8 line[128], *linep = line; int i; @@ -556,6 +557,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr } break; case SC_ASN1_INTEGER: + case SC_ASN1_ENUMERATED: if (parm != NULL) r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm); break; @@ -627,7 +629,7 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, struct sc_asn1_struct *entry = asn1; int left = len, objlen; - if (ctx->debug > 2) + if (ctx->debug >= 3) debug(ctx, "called, depth %d%s\n", depth, choice ? ", choice" : ""); if (left < 2) return SC_ERROR_ASN1_END_OF_CONTENTS; @@ -640,8 +642,12 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, if (obj == NULL) { if (choice) continue; - if (entry->flags & SC_ASN1_OPTIONAL) + if (entry->flags & SC_ASN1_OPTIONAL) { + if (ctx->debug >= 3) + debug(ctx, "optional ASN.1 object '%s' not present\n", + entry->name); continue; + } error(ctx, "mandatory ASN.1 object '%s' not found\n", entry->name); if (ctx->debug && left) { u8 line[128], *linep = line; @@ -654,7 +660,7 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, } debug(ctx, "next tag: %s\n", line); } - SC_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND); + SC_FUNC_RETURN(ctx, 3, SC_ERROR_ASN1_OBJECT_NOT_FOUND); } r = asn1_decode_entry(ctx, entry, obj, objlen, depth); if (r) @@ -663,14 +669,14 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, break; } if (choice && asn1[idx].name == NULL) /* No match */ - SC_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND); + SC_FUNC_RETURN(ctx, 3, SC_ERROR_ASN1_OBJECT_NOT_FOUND); if (newp != NULL) *newp = p; if (len_left != NULL) *len_left = left; if (choice) - SC_FUNC_RETURN(ctx, idx); - SC_FUNC_RETURN(ctx, 0); + SC_FUNC_RETURN(ctx, 3, idx); + SC_FUNC_RETURN(ctx, 3, 0); } int sc_asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, diff --git a/src/libopensc/log.c b/src/libopensc/log.c index e262beff..7056f5fd 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -32,16 +32,7 @@ void error(struct sc_context *ctx, const char *format, ...) va_list ap; va_start(ap, format); - do_log2(ctx, SC_LOG_ERROR, "", format, ap); - va_end(ap); -} - -void log(struct sc_context *ctx, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - do_log2(ctx, SC_LOG_NORMAL, "", format, ap); + do_log2(ctx, SC_LOG_TYPE_ERROR, "", format, ap); va_end(ap); } @@ -50,7 +41,7 @@ void debug(struct sc_context *ctx, const char *format, ...) va_list ap; va_start(ap, format); - do_log2(ctx, SC_LOG_DEBUG, "", format, ap); + do_log2(ctx, SC_LOG_TYPE_DEBUG, "", format, ap); va_end(ap); } @@ -79,12 +70,11 @@ void do_log2(struct sc_context *ctx, int type, const char *file, assert(ctx != NULL); if (ctx->use_std_output) { switch (type) { - case SC_LOG_ERROR: + case SC_LOG_TYPE_ERROR: outf = stderr; break; - case SC_LOG_NORMAL: - case SC_LOG_DEBUG: - case SC_LOG_DEBUG2: + + case SC_LOG_TYPE_DEBUG: outf = stdout; } if (outf == NULL) @@ -122,14 +112,15 @@ void do_log2(struct sc_context *ctx, int type, const char *file, if (do_color) { color_sfx = "\e[0m"; switch (type) { - case SC_LOG_ERROR: + case SC_LOG_TYPE_ERROR: color_pfx = "\e[01;31m"; break; - case SC_LOG_NORMAL: +#if 0 + case SC_LOG_TYPE_NORMAL: color_pfx = "\e[01;33m"; break; - case SC_LOG_DEBUG: - case SC_LOG_DEBUG2: +#endif + case SC_LOG_TYPE_DEBUG: color_pfx = "\e[00;32m"; break; } diff --git a/src/libopensc/log.h b/src/libopensc/log.h index d05ed9eb..2703afd8 100644 --- a/src/libopensc/log.h +++ b/src/libopensc/log.h @@ -24,34 +24,29 @@ #include "opensc.h" #include -#define SC_LOG_ERROR 0 -#define SC_LOG_NORMAL 1 -#define SC_LOG_VERBOSE 2 -#define SC_LOG_DEBUG 3 -#define SC_LOG_DEBUG2 4 +#define SC_LOG_TYPE_ERROR 0 +#define SC_LOG_TYPE_VERBOSE 1 +#define SC_LOG_TYPE_DEBUG 2 #ifdef __GNUC__ -#define error(ctx, format, args...) do_log(ctx, SC_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) -#define log(ctx, format, args...) do_log(ctx, SC_LOG_NORMAL, __FILE__, __LINE__, __FUNCTION__, format , ## args) -#define debug(ctx, format, args...) do_log(ctx, SC_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args) -#define debug2(ctx, format, args...) do_log(ctx, SC_LOG_DEBUG2, __FILE__, __LINE__, __FUNCTION__, format , ## args) +#define error(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) +#define debug(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args) + #else void error(struct sc_context *ctx, const char *format, ...); -void log(struct sc_context *ctx, const char *format, ...); void debug(struct sc_context *ctx, const char *format, ...); -void debug2(struct sc_context *ctx, const char *format, ...); #endif -#define SC_FUNC_CALLED(ctx) {\ - if ((ctx)->debug > 2)\ +#define SC_FUNC_CALLED(ctx, level) {\ + if ((ctx)->debug >= level)\ debug(ctx, "called\n"); } -#define SC_FUNC_RETURN(ctx, r) {\ +#define SC_FUNC_RETURN(ctx, level, r) {\ int _ret = r;\ if (_ret < 0) {\ error(ctx, "returning with: %s\n", sc_strerror(_ret));\ - } else if ((ctx)->debug > 2) {\ + } else if ((ctx)->debug >= level) {\ debug(ctx, "returning with: %d\n", _ret);\ }\ return _ret; } diff --git a/src/libopensc/opensc-pkcs15.h b/src/libopensc/opensc-pkcs15.h index e54d0822..13207f40 100644 --- a/src/libopensc/opensc-pkcs15.h +++ b/src/libopensc/opensc-pkcs15.h @@ -58,6 +58,7 @@ struct sc_pkcs15_pin_info { struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_id auth_id; + int reference; int flags, type; int min_length, stored_length; u8 pad_char; @@ -129,7 +130,7 @@ struct sc_pkcs15_prkey_info { struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_id id; /* correlates to public certificate id */ - int usage, access_flags; + int usage, access_flags, native; int key_reference; struct sc_path file_id; @@ -173,9 +174,12 @@ struct sc_pkcs15_defaults { int arg; }; -int sc_pkcs15_init(struct sc_card *card, +/* Binds a card object to a PKCS#15 card object and initializes + * a new PKCS#15 card object */ +int sc_pkcs15_bind(struct sc_card *card, struct sc_pkcs15_card **pkcs15_card); -int sc_pkcs15_destroy(struct sc_pkcs15_card *card); + +int sc_pkcs15_unbind(struct sc_pkcs15_card *card); int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_prkey_info *prkey, diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index b3eac436..bedf2d5c 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -42,7 +42,7 @@ extern "C" { #define SC_ERROR_OUT_OF_MEMORY -1009 #define SC_ERROR_NO_READERS_FOUND -1010 #define SC_ERROR_OBJECT_NOT_VALID -1011 -#define SC_ERROR_UNKNOWN_RESPONSE -1012 +#define SC_ERROR_ILLEGAL_RESPONSE -1012 #define SC_ERROR_PIN_CODE_INCORRECT -1013 #define SC_ERROR_SECURITY_STATUS_NOT_SATISFIED -1014 #define SC_ERROR_CONNECTING_TO_RES_MGR -1015 @@ -106,7 +106,6 @@ extern "C" { #define SC_ASN1_MAX_OBJECT_ID_OCTETS 16 typedef unsigned char u8; -typedef unsigned int uint32; struct sc_object_id { int value[SC_ASN1_MAX_OBJECT_ID_OCTETS]; @@ -132,6 +131,9 @@ struct sc_file { unsigned int magic; }; +#define SC_SEC_OPERATION_DECIPHER 0 +#define SC_SEC_OPERATION_SIGN 1 + struct sc_security_env { int algorithm_ref; struct sc_path key_file_id; @@ -146,19 +148,19 @@ struct sc_card_operations { int (*init)(struct sc_card *card); int (*finish)(struct sc_card *card); - int (*read_binary)(struct sc_card *card, uint32 idx, + int (*read_binary)(struct sc_card *card, unsigned int idx, u8 * buf, size_t count); - int (*write_binary)(struct sc_card *card, uint32 idx, + int (*write_binary)(struct sc_card *card, unsigned int idx, const u8 * buf, size_t count); - int (*update_binary)(struct sc_card *card, uint32 idx, + int (*update_binary)(struct sc_card *card, unsigned int idx, const u8 * buf, size_t count); - int (*erase_binary)(struct sc_card *card, uint32 idx, + int (*erase_binary)(struct sc_card *card, unsigned int idx, size_t count); - int (*read_binary_large)(struct sc_card *card, uint32 idx, + int (*read_binary_large)(struct sc_card *card, unsigned int idx, u8 * buf, size_t count); - int (*write_binary_large)(struct sc_card *card, uint32 idx, + int (*write_binary_large)(struct sc_card *card, unsigned int idx, const u8 * buf, size_t count); - int (*update_binary_large)(struct sc_card *card, uint32 idx, + int (*update_binary_large)(struct sc_card *card, unsigned int idx, const u8 * buf, size_t count); /* possibly TODO: record handling */ int (*select_file)(struct sc_card *card, struct sc_file *file, diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 9faca5a6..6283fd93 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -224,7 +224,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, struct sc_pkcs15_cert *cert; assert(p15card != NULL && info != NULL && cert_out != NULL); - SC_FUNC_CALLED(p15card->card->ctx); + SC_FUNC_CALLED(p15card->card->ctx, 1); r = find_cached_cert(p15card, info, &data, &len); if (r) { r = sc_select_file(p15card->card, &file, &info->path, @@ -290,7 +290,7 @@ static int parse_x509_cert_info(struct sc_context *ctx, struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; struct sc_asn1_struct asn1_cert[] = { - { "x509Certificate", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &cert_obj, }, + { "x509Certificate", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &cert_obj }, { NULL } }; @@ -332,15 +332,17 @@ static int get_certs_from_file(struct sc_pkcs15_card *card, return r; bytes_left = r; do { - if (card->cert_count >= SC_PKCS15_MAX_CERTS) - return SC_ERROR_TOO_MANY_OBJECTS; + struct sc_pkcs15_cert_info tmp; + r = parse_x509_cert_info(card->card->ctx, - &card->cert_info[card->cert_count], - &p, &bytes_left); + &tmp, &p, &bytes_left); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) break; if (r) return r; + if (card->cert_count >= SC_PKCS15_MAX_CERTS) + return SC_ERROR_TOO_MANY_OBJECTS; + card->cert_info[card->cert_count] = tmp; card->cert_count++; } while (bytes_left); diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index e2ac5e88..5199f221 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -27,73 +27,49 @@ #include #include -static int decode_pin_info(const u8 *buf, - int buflen, struct sc_pkcs15_pin_info *pin) +static int parse_pin_info(struct sc_context *ctx, + struct sc_pkcs15_pin_info *pin, + const u8 ** buf, int *buflen) { - const u8 *tag, *p = buf; - int taglen, left = buflen; + int r; + struct sc_asn1_struct asn1_com_ao_attr[] = { + { "authId", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, &pin->auth_id }, + { NULL } + }; + int flags_len = sizeof(pin->flags); + int padchar_len = 1; + struct sc_asn1_struct asn1_pin_attr[] = { + { "pinFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, &pin->flags, &flags_len}, + { "pinType", SC_ASN1_ENUMERATED, ASN1_ENUMERATED, 0, &pin->type }, + { "minLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &pin->min_length }, + { "storedLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &pin->stored_length }, + { "maxLength", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, + { "pinReference", SC_ASN1_INTEGER, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, &pin->reference }, + { "padChar", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, SC_ASN1_OPTIONAL, &pin->pad_char, &padchar_len }, + { "lastPinChange",SC_ASN1_GENERALIZEDTIME, ASN1_GENERALIZEDTIME, SC_ASN1_OPTIONAL, NULL }, + { "path", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, &pin->path }, + { NULL } + }; + struct sc_asn1_struct asn1_type_pin_attr[] = { + { "pinAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_pin_attr}, + { NULL } + }; + struct sc_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL, + asn1_type_pin_attr }; + struct sc_asn1_struct asn1_pin[] = { + { "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj }, + { NULL } + }; + + pin->reference = 0; memset(pin, 0, sizeof(*pin)); - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* SEQUENCE */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - sc_pkcs15_parse_common_object_attr(&pin->com_attr, tag, taglen); - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* SEQUENCE */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - tag = sc_asn1_verify_tag(tag, taglen, 0x04, &taglen); /* OCTET STRING */ - if (tag == NULL || taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - if (taglen > SC_PKCS15_MAX_ID_SIZE) - taglen = SC_PKCS15_MAX_ID_SIZE; - memcpy(pin->auth_id.value, tag, taglen); - pin->auth_id.len = taglen; + r = sc_asn1_parse(ctx, asn1_pin, *buf, *buflen, buf, buflen); + if (r == 0) + pin->magic = SC_PKCS15_PIN_MAGIC; - p = sc_asn1_verify_tag(p, left, 0xA1, &left); /* CONS */ - if (left == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - p = sc_asn1_verify_tag(p, left, 0x30, &left); - if (left == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - - tag = sc_asn1_skip_tag(&p, &left, 0x03, &taglen); - if (taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - sc_asn1_decode_bit_string(tag, taglen, &pin->flags, - sizeof(pin->flags)); - - tag = sc_asn1_skip_tag(&p, &left, 0x0A, &taglen); - if (taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - pin->type = tag[0]; - - tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); - if (taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - pin->min_length = tag[0]; - - tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); - if (taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - pin->stored_length = tag[0]; - - tag = sc_asn1_find_tag(p, left, 0x04, &taglen); - if (taglen == 0) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - pin->pad_char = tag[0]; - - tag = sc_asn1_find_tag(p, left, 0x30, &taglen); - if (taglen != 0) { - tag = sc_asn1_find_tag(tag, taglen, 0x04, &taglen); - if (taglen >= 0) { - memcpy(pin->path.value, tag, taglen); - pin->path.len = taglen; - } - } - pin->magic = SC_PKCS15_PIN_MAGIC; - - return 0; + return r; } void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) @@ -120,36 +96,40 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) printf("\n"); } -static int get_pins_from_file(struct sc_pkcs15_card *p15card, +static int get_pins_from_file(struct sc_pkcs15_card *card, struct sc_file *file) { - int r, taglen, left; - const u8 *p, *tag; - u8 buf[MAX_BUFFER_SIZE]; + int r, bytes_left; + u8 buf[2048]; + const u8 *p = buf; - r = sc_select_file(p15card->card, file, &file->path, + r = sc_select_file(card->card, file, &file->path, SC_SELECT_FILE_BY_PATH); if (r) return r; if (file->size > sizeof(buf)) return SC_ERROR_BUFFER_TOO_SMALL; - r = sc_read_binary(p15card->card, 0, buf, file->size); + r = sc_read_binary(card->card, 0, buf, file->size); if (r < 0) return r; + bytes_left = r; + do { + struct sc_pkcs15_pin_info tmp; - left = r; - p = buf; - while ((tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen)) != NULL) { - if (p15card->pin_count >= SC_PKCS15_MAX_PINS) - return SC_ERROR_TOO_MANY_OBJECTS; - r = decode_pin_info(tag, taglen, - &p15card->pin_info[p15card->pin_count]); + r = parse_pin_info(card->card->ctx, + &tmp, &p, &bytes_left); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + break; if (r) return r; + if (card->pin_count >= SC_PKCS15_MAX_CERTS) + return SC_ERROR_TOO_MANY_OBJECTS; + card->pin_info[card->pin_count] = tmp; + card->pin_count++; + } while (bytes_left); - p15card->pin_count++; - } return 0; + } int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) @@ -158,7 +138,7 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) struct sc_context *ctx = p15card->card->ctx; assert(p15card != NULL); - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); if (p15card->pin_count) { for (i = 0; i < p15card->pin_count; i++) { if (p15card->pin_info[i].magic != SC_PKCS15_PIN_MAGIC) @@ -167,6 +147,7 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) if (i == p15card->pin_count) return i; /* Already enumerated */ } + p15card->pin_count = 0; for (i = 0; i < p15card->aodf_count; i++) { r = get_pins_from_file(p15card, &p15card->file_aodf[i]); SC_TEST_RET(ctx, r, "Failed to read PINs from AODF"); diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 279b4b69..2f090325 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -47,105 +47,97 @@ void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey) printf("\n"); } -static int parse_prkey_info(const u8 * buf, - int buflen, struct sc_pkcs15_prkey_info *prkey) +static int parse_rsa_prkey_info(struct sc_context *ctx, + struct sc_pkcs15_prkey_info *prkey, + const u8 **buf, int *buflen) { - const u8 *tag, *p; - int taglen, left; + int r; + int usage_len = sizeof(prkey->usage); + int af_len = sizeof(prkey->access_flags); + struct sc_asn1_struct asn1_com_key_attr[] = { + { "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, &prkey->id, NULL }, + { "usage", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, &prkey->usage, &usage_len }, + { "native", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, &prkey->native }, + { "accessFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, &prkey->access_flags, &af_len }, + { "keyReference",SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, &prkey->key_reference }, + { NULL } + }; + struct sc_asn1_struct asn1_com_prkey_attr[] = { + { NULL } + }; + struct sc_asn1_struct asn1_rsakey_attr[] = { + { "value", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey->file_id }, + { "modulusLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &prkey->modulus_length }, + { "keyInfo", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, + { NULL } + }; + struct sc_asn1_struct asn1_type_attr[] = { + { "publicRSAKeyAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_rsakey_attr }, + { NULL } + }; - tag = sc_asn1_skip_tag(&buf, &buflen, 0x30, &taglen); /* SEQUENCE */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - sc_pkcs15_parse_common_object_attr(&prkey->com_attr, tag, taglen); + struct sc_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr, + asn1_com_prkey_attr, asn1_type_attr }; + struct sc_asn1_struct asn1_prkey[] = { + { "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj }, + { NULL } + }; - p = sc_asn1_skip_tag(&buf, &buflen, 0x30, &left); /* SEQUENCE */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; + prkey->key_reference = -1; + prkey->native = 1; - tag = sc_asn1_skip_tag(&p, &left, 0x04, &taglen); /* OCTET STRING */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - memcpy(prkey->id.value, tag, taglen); - prkey->id.len = taglen; + r = sc_asn1_parse(ctx, asn1_prkey, *buf, *buflen, buf, buflen); - tag = sc_asn1_skip_tag(&p, &left, 0x03, &taglen); /* BIT STRING */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - sc_asn1_decode_bit_string(tag, taglen, &prkey->usage, - sizeof(prkey->usage)); + return r; +} - tag = sc_asn1_skip_tag(&p, &left, 0x01, &taglen); /* BOOLEAN */ - if (tag != NULL) { - /* FIXME */ - } +static int get_prkeys_from_file(struct sc_pkcs15_card *card, + struct sc_file *file) +{ + int r, bytes_left; + u8 buf[2048]; + const u8 *p = buf; - tag = sc_asn1_skip_tag(&p, &left, 0x03, &taglen); /* BIT STRING */ - if (tag != NULL) { - sc_asn1_decode_bit_string(tag, taglen, - &prkey->access_flags, - sizeof(prkey->access_flags)); - } else - prkey->access_flags = 0; + r = sc_select_file(card->card, file, &file->path, + SC_SELECT_FILE_BY_PATH); + if (r) + return r; + if (file->size > sizeof(buf)) + return SC_ERROR_BUFFER_TOO_SMALL; + r = sc_read_binary(card->card, 0, buf, file->size); + if (r < 0) + return r; + bytes_left = r; + do { + struct sc_pkcs15_prkey_info tmp; - tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); /* INTEGER */ - if (tag != NULL && taglen) { - prkey->key_reference = tag[0]; - } else - prkey->key_reference = -1; - - - /* FIXME */ - p = sc_asn1_find_tag(buf, buflen, 0xA1, &left); - if (p == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - p = sc_asn1_verify_tag(p, left, 0x30, &left); /* SEQUENCE 1 */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* SEQUENCE 2 */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - tag = sc_asn1_verify_tag(tag, taglen, 0x04, &taglen); /* OCTET STRING */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - memcpy(prkey->file_id.value, tag, taglen); - prkey->file_id.len = taglen; - - tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); /* INTEGER */ - if (tag == NULL) - return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; - sc_asn1_decode_integer(tag, taglen, &prkey->modulus_length); + r = parse_rsa_prkey_info(card->card->ctx, + &tmp, &p, &bytes_left); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + break; + if (r) + return r; + if (card->prkey_count >= SC_PKCS15_MAX_PRKEYS) + return SC_ERROR_TOO_MANY_OBJECTS; + card->prkey_info[card->prkey_count] = tmp; + card->prkey_count++; + } while (bytes_left); return 0; } + int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card) { - int r, left, taglen; - const u8 *p, *tag; - u8 buf[1024]; - + int r, i; assert(card != NULL); if (card->prkey_count) return card->prkey_count; /* already enumerated */ - card->prkey_count = 0; - r = sc_select_file(card->card, &card->file_prkdf, - &card->file_prkdf.path, SC_SELECT_FILE_BY_PATH); - if (r) - return r; - r = sc_read_binary(card->card, 0, buf, card->file_prkdf.size); - if (r < 0) - return r; - left = r; - p = buf; - while ((tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen)) != NULL) { - struct sc_pkcs15_prkey_info *prkey = - &card->prkey_info[card->prkey_count]; - - if (parse_prkey_info(tag, taglen, prkey)) - break; - card->prkey_count++; + for (i = 0; i < 1; i++) { + r = get_prkeys_from_file(card, &card->file_prkdf); + if (r != 0) + return r; } return card->prkey_count; } diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index bb3636df..48f74968 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -40,13 +40,14 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, senv.operation = 0; senv.key_ref = prkey->key_reference; - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); r = sc_select_file(p15card->card, &p15card->file_app, &p15card->file_app.path, SC_SELECT_FILE_BY_PATH); SC_TEST_RET(ctx, r, "sc_select_file() failed"); r = sc_select_file(p15card->card, &p15card->file_app, &p15card->file_app.path, SC_SELECT_FILE_BY_PATH); SC_TEST_RET(ctx, r, "sc_select_file() failed"); + usleep(100*1000); /* PC/SC Lite quirks */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */ SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); r = sc_set_security_env(p15card->card, &senv); @@ -78,10 +79,11 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, senv.operation = 1; senv.key_ref = prkey->key_reference; - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); r = sc_select_file(p15card->card, &p15card->file_app, &p15card->file_app.path, SC_SELECT_FILE_BY_PATH); SC_TEST_RET(ctx, r, "sc_select_file() failed"); + usleep(100*1000); /* PC/SC Lite quirks */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */ SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); r = sc_set_security_env(p15card->card, &senv); diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 1826779c..e9dd0650 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -236,7 +236,7 @@ static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen) return match; } -int sc_pkcs15_init(struct sc_card *card, +int sc_pkcs15_bind(struct sc_card *card, struct sc_pkcs15_card **p15card_out) { unsigned char buf[MAX_BUFFER_SIZE]; @@ -324,7 +324,7 @@ error: return err; } -int sc_pkcs15_destroy(struct sc_pkcs15_card *p15card) +int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) { free(p15card->label); free(p15card->serial_number); diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index e54d0822..13207f40 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -58,6 +58,7 @@ struct sc_pkcs15_pin_info { struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_id auth_id; + int reference; int flags, type; int min_length, stored_length; u8 pad_char; @@ -129,7 +130,7 @@ struct sc_pkcs15_prkey_info { struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_id id; /* correlates to public certificate id */ - int usage, access_flags; + int usage, access_flags, native; int key_reference; struct sc_path file_id; @@ -173,9 +174,12 @@ struct sc_pkcs15_defaults { int arg; }; -int sc_pkcs15_init(struct sc_card *card, +/* Binds a card object to a PKCS#15 card object and initializes + * a new PKCS#15 card object */ +int sc_pkcs15_bind(struct sc_card *card, struct sc_pkcs15_card **pkcs15_card); -int sc_pkcs15_destroy(struct sc_pkcs15_card *card); + +int sc_pkcs15_unbind(struct sc_pkcs15_card *card); int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_prkey_info *prkey, diff --git a/src/libopensc/sc-log.h b/src/libopensc/sc-log.h index d05ed9eb..2703afd8 100644 --- a/src/libopensc/sc-log.h +++ b/src/libopensc/sc-log.h @@ -24,34 +24,29 @@ #include "opensc.h" #include -#define SC_LOG_ERROR 0 -#define SC_LOG_NORMAL 1 -#define SC_LOG_VERBOSE 2 -#define SC_LOG_DEBUG 3 -#define SC_LOG_DEBUG2 4 +#define SC_LOG_TYPE_ERROR 0 +#define SC_LOG_TYPE_VERBOSE 1 +#define SC_LOG_TYPE_DEBUG 2 #ifdef __GNUC__ -#define error(ctx, format, args...) do_log(ctx, SC_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) -#define log(ctx, format, args...) do_log(ctx, SC_LOG_NORMAL, __FILE__, __LINE__, __FUNCTION__, format , ## args) -#define debug(ctx, format, args...) do_log(ctx, SC_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args) -#define debug2(ctx, format, args...) do_log(ctx, SC_LOG_DEBUG2, __FILE__, __LINE__, __FUNCTION__, format , ## args) +#define error(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) +#define debug(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args) + #else void error(struct sc_context *ctx, const char *format, ...); -void log(struct sc_context *ctx, const char *format, ...); void debug(struct sc_context *ctx, const char *format, ...); -void debug2(struct sc_context *ctx, const char *format, ...); #endif -#define SC_FUNC_CALLED(ctx) {\ - if ((ctx)->debug > 2)\ +#define SC_FUNC_CALLED(ctx, level) {\ + if ((ctx)->debug >= level)\ debug(ctx, "called\n"); } -#define SC_FUNC_RETURN(ctx, r) {\ +#define SC_FUNC_RETURN(ctx, level, r) {\ int _ret = r;\ if (_ret < 0) {\ error(ctx, "returning with: %s\n", sc_strerror(_ret));\ - } else if ((ctx)->debug > 2) {\ + } else if ((ctx)->debug >= level) {\ debug(ctx, "returning with: %d\n", _ret);\ }\ return _ret; } diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 39f1d8d2..55944869 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -118,28 +118,28 @@ int sc_check_apdu(struct sc_context *ctx, const struct sc_apdu *apdu) switch (apdu->cse) { case SC_APDU_CASE_1: if (apdu->datalen) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); break; case SC_APDU_CASE_2_SHORT: if (apdu->datalen) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); if (apdu->resplen < apdu->le) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); break; case SC_APDU_CASE_3_SHORT: if (apdu->datalen == 0 || apdu->data == NULL) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); break; case SC_APDU_CASE_4_SHORT: if (apdu->datalen == 0 || apdu->data == NULL) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); if (apdu->resplen < apdu->le) - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); break; case SC_APDU_CASE_2_EXT: case SC_APDU_CASE_3_EXT: case SC_APDU_CASE_4_EXT: - SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); } return 0; } @@ -196,7 +196,7 @@ static int sc_transceive_t0(struct sc_card *card, struct sc_apdu *apdu) dwRecvLength = apdu->resplen + 2; if (dwRecvLength > 255) /* FIXME: PC/SC Lite quirk */ dwRecvLength = 255; - if (card->ctx->debug > 3) { + if (card->ctx->debug >= 5) { char buf[2048]; sc_hex_dump(card->ctx, s, dwSendLength, buf, sizeof(buf)); @@ -221,7 +221,7 @@ static int sc_transceive_t0(struct sc_card *card, struct sc_apdu *apdu) } } if (dwRecvLength < 2) - return SC_ERROR_UNKNOWN_RESPONSE; + return SC_ERROR_ILLEGAL_RESPONSE; apdu->sw1 = r[dwRecvLength-2]; apdu->sw2 = r[dwRecvLength-1]; dwRecvLength -= 2; @@ -239,12 +239,12 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu) { int r; - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 4); r = sc_check_apdu(card->ctx, apdu); SC_TEST_RET(card->ctx, r, "APDU sanity check failed"); r = sc_transceive_t0(card, apdu); SC_TEST_RET(card->ctx, r, "transceive_t0() failed"); - if (card->ctx->debug > 3) { + if (card->ctx->debug >= 5) { char buf[2048]; buf[0] = 0; @@ -273,7 +273,7 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu) sc_strerror(r)); return r; } - if (card->ctx->debug > 3) { + if (card->ctx->debug >= 5) { char buf[2048]; buf[0] = 0; if (rspapdu.resplen) { @@ -315,7 +315,7 @@ int sc_detect_card(struct sc_context *ctx, int reader) SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS]; assert(ctx != NULL); - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); if (reader >= ctx->reader_count || reader < 0) return SC_ERROR_INVALID_ARGUMENTS; @@ -324,11 +324,16 @@ int sc_detect_card(struct sc_context *ctx, int reader) ret = SCardGetStatusChange(ctx->pcsc_ctx, 0, rgReaderStates, 1); if (ret != 0) { error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(ret)); - SC_FUNC_RETURN(ctx, -1); /* FIXME */ + SC_FUNC_RETURN(ctx, 1, -1); /* FIXME */ } - if (rgReaderStates[0].dwEventState & SCARD_STATE_PRESENT) - SC_FUNC_RETURN(ctx, 1); - SC_FUNC_RETURN(ctx, 0); + if (rgReaderStates[0].dwEventState & SCARD_STATE_PRESENT) { + if (ctx->debug >= 1) + debug(ctx, "card present\n"); + return 1; + } + if (ctx->debug >= 1) + debug(ctx, "card absent\n"); + return 0; } int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout) @@ -338,13 +343,13 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout) int count = 0, i; assert(ctx != NULL); - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); if (reader >= ctx->reader_count) - return SC_ERROR_INVALID_ARGUMENTS; + SC_FUNC_RETURN(ctx, 1, SC_ERROR_INVALID_ARGUMENTS); if (reader < 0) { if (ctx->reader_count == 0) - SC_FUNC_RETURN(ctx, SC_ERROR_NO_READERS_FOUND); + SC_FUNC_RETURN(ctx, 1, SC_ERROR_NO_READERS_FOUND); for (i = 0; i < ctx->reader_count; i++) { rgReaderStates[i].szReader = ctx->readers[i]; rgReaderStates[i].dwCurrentState = @@ -360,13 +365,13 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout) count); if (ret != 0) { error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(ret)); - SC_FUNC_RETURN(ctx, -1); + SC_FUNC_RETURN(ctx, 1, -1); } for (i = 0; i < count; i++) { if (rgReaderStates[i].dwEventState & SCARD_STATE_CHANGED) - SC_FUNC_RETURN(ctx, 1); + SC_FUNC_RETURN(ctx, 1, 1); } - SC_FUNC_RETURN(ctx, 0); + SC_FUNC_RETURN(ctx, 1, 0); } int sc_establish_context(struct sc_context **ctx_out) @@ -417,7 +422,7 @@ int sc_destroy_context(struct sc_context *ctx) int i; assert(ctx != NULL); - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); for (i = 0; i < ctx->reader_count; i++) free(ctx->readers[i]); free(ctx); @@ -462,23 +467,23 @@ int sc_connect_card(struct sc_context *ctx, const struct sc_defaults *defaults; assert(card_out != NULL); - SC_FUNC_CALLED(ctx); + SC_FUNC_CALLED(ctx, 1); if (reader >= ctx->reader_count || reader < 0) - SC_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_FOUND); + SC_FUNC_RETURN(ctx, 1, SC_ERROR_OBJECT_NOT_FOUND); rgReaderStates[0].szReader = ctx->readers[reader]; rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE; rv = SCardGetStatusChange(ctx->pcsc_ctx, 0, rgReaderStates, 1); if (rv != 0) { error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(rv)); - SC_FUNC_RETURN(ctx, SC_ERROR_RESOURCE_MANAGER); /* FIXME */ + SC_FUNC_RETURN(ctx, 1, SC_ERROR_RESOURCE_MANAGER); /* FIXME */ } if (!(rgReaderStates[0].dwEventState & SCARD_STATE_PRESENT)) - SC_FUNC_RETURN(ctx, SC_ERROR_CARD_NOT_PRESENT); + SC_FUNC_RETURN(ctx, 1, SC_ERROR_CARD_NOT_PRESENT); card = malloc(sizeof(struct sc_card)); if (card == NULL) - SC_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + SC_FUNC_RETURN(ctx, 1, SC_ERROR_OUT_OF_MEMORY); memset(card, 0, sizeof(struct sc_card)); rv = SCardConnect(ctx->pcsc_ctx, ctx->readers[reader], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, @@ -506,17 +511,18 @@ int sc_connect_card(struct sc_context *ctx, pthread_mutex_init(&card->mutex, NULL); *card_out = card; - return 0; + SC_FUNC_RETURN(ctx, 1, 0); } int sc_disconnect_card(struct sc_card *card) { + struct sc_context *ctx = card->ctx; assert(card != NULL); + SC_FUNC_CALLED(ctx, 1); SCardDisconnect(card->pcsc_card, SCARD_LEAVE_CARD); pthread_mutex_destroy(&card->mutex); free(card); - - return 0; + SC_FUNC_RETURN(ctx, 1, 0); } const char *sc_strerror(int error) @@ -578,8 +584,9 @@ int _sc_lock_int(struct sc_card *card) int sc_lock(struct sc_card *card) { + SC_FUNC_CALLED(card->ctx, 2); pthread_mutex_lock(&card->mutex); - return _sc_lock_int(card); + SC_FUNC_RETURN(card->ctx, 2, _sc_lock_int(card)); } int _sc_unlock_int(struct sc_card *card) @@ -596,22 +603,23 @@ int _sc_unlock_int(struct sc_card *card) int sc_unlock(struct sc_card *card) { + SC_FUNC_CALLED(card->ctx, 2); pthread_mutex_unlock(&card->mutex); - return _sc_unlock_int(card); + SC_FUNC_RETURN(card->ctx, 2, _sc_unlock_int(card)); } int sc_list_files(struct sc_card *card, u8 *buf, int buflen) { struct sc_apdu apdu; int r; - + + SC_FUNC_CALLED(card->ctx, 2); sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0); apdu.resp = buf; apdu.resplen = buflen; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); - if (r) - return r; + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.resplen == 0) return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); return apdu.resplen; @@ -658,10 +666,10 @@ int sc_create_file(struct sc_card *card, const struct sc_file *file) u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; struct sc_apdu apdu; + SC_FUNC_CALLED(card->ctx, 1); len = SC_MAX_APDU_BUFFER_SIZE; r = construct_fci(file, sbuf, &len); - if (r) - return r; + SC_TEST_RET(card->ctx, r, "construct_fci() failed"); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00); apdu.lc = len; @@ -671,9 +679,8 @@ int sc_create_file(struct sc_card *card, const struct sc_file *file) apdu.resp = rbuf; r = sc_transmit_apdu(card, &apdu); - if (r) - return r; - return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_delete_file(struct sc_card *card, int file_id) @@ -683,6 +690,7 @@ int sc_delete_file(struct sc_card *card, int file_id) u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; struct sc_apdu apdu; + SC_FUNC_CALLED(card->ctx, 1); sbuf[0] = (file_id >> 8) & 0xFF; sbuf[1] = file_id & 0xFF; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00); @@ -693,11 +701,10 @@ int sc_delete_file(struct sc_card *card, int file_id) apdu.resp = rbuf; r = sc_transmit_apdu(card, &apdu); - if (r) - return r; - if (apdu.resplen != 2) - return -1; - return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + if (apdu.resplen != 0) + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_ILLEGAL_RESPONSE); + SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_file_valid(const struct sc_file *file) diff --git a/src/libopensc/sec.c b/src/libopensc/sec.c index 41128939..484468f1 100644 --- a/src/libopensc/sec.c +++ b/src/libopensc/sec.c @@ -33,7 +33,7 @@ int sc_set_security_env(struct sc_card *card, int r; assert(card != NULL && env != NULL); - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 2); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); if (env->operation == 1) { apdu.p1 = 0x81; @@ -61,7 +61,7 @@ int sc_set_security_env(struct sc_card *card, apdu.resplen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_restore_security_env(struct sc_card *card, int num) @@ -71,13 +71,13 @@ int sc_restore_security_env(struct sc_card *card, int num) u8 rbuf[MAX_BUFFER_SIZE]; assert(card != NULL); - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 2); sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, num); apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf); apdu.resp = rbuf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_decipher(struct sc_card *card, @@ -89,9 +89,9 @@ int sc_decipher(struct sc_card *card, u8 sbuf[MAX_BUFFER_SIZE]; assert(card != NULL && crgram != NULL && out != NULL); - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 2); if (crgram_len > 255) - SC_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x80, 0x86); apdu.resp = rbuf; @@ -108,9 +108,9 @@ int sc_decipher(struct sc_card *card, int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); - SC_FUNC_RETURN(card->ctx, len); + SC_FUNC_RETURN(card->ctx, 2, len); } - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_compute_signature(struct sc_card *card, @@ -123,9 +123,9 @@ int sc_compute_signature(struct sc_card *card, u8 sbuf[MAX_BUFFER_SIZE]; assert(card != NULL && data != NULL && out != NULL); - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 2); if (datalen > 255) - SC_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x9E, 0x9A); @@ -142,9 +142,9 @@ int sc_compute_signature(struct sc_card *card, int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); - SC_FUNC_RETURN(card->ctx, len); + SC_FUNC_RETURN(card->ctx, 2, len); } - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_verify(struct sc_card *card, int ref, const u8 *pin, int pinlen, @@ -154,9 +154,9 @@ int sc_verify(struct sc_card *card, int ref, const u8 *pin, int pinlen, u8 sbuf[MAX_BUFFER_SIZE]; int r; - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 2); if (pinlen >= MAX_BUFFER_SIZE) - SC_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0, ref); memcpy(sbuf, pin, pinlen); apdu.lc = pinlen; @@ -170,9 +170,9 @@ int sc_verify(struct sc_card *card, int ref, const u8 *pin, int pinlen, if (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) { if (tries_left != NULL) *tries_left = apdu.sw2 & 0x0F; - SC_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT); + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_PIN_CODE_INCORRECT); } - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_change_reference_data(struct sc_card *card, int ref, const u8 *old, @@ -183,9 +183,9 @@ int sc_change_reference_data(struct sc_card *card, int ref, const u8 *old, u8 sbuf[MAX_BUFFER_SIZE]; int r, p1 = 0, len = oldlen + newlen; - SC_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, 1); if (len >= MAX_BUFFER_SIZE) - SC_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); if (oldlen == 0) p1 = 1; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, ref); @@ -202,9 +202,9 @@ int sc_change_reference_data(struct sc_card *card, int ref, const u8 *old, if (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) { if (tries_left != NULL) *tries_left = apdu.sw2 & 0x0F; - SC_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT); + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_PIN_CODE_INCORRECT); } - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); } int sc_reset_retry_counter(struct sc_card *card, int ref, const u8 *puk, @@ -215,7 +215,7 @@ int sc_reset_retry_counter(struct sc_card *card, int ref, const u8 *puk, int r, p1 = 0, len = puklen + newlen; if (len >= MAX_BUFFER_SIZE) - SC_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); if (puklen == 0) { if (newlen == 0) p1 = 3; @@ -238,5 +238,5 @@ int sc_reset_retry_counter(struct sc_card *card, int ref, const u8 *puk, r = sc_transmit_apdu(card, &apdu); memset(sbuf, 0, len); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); - SC_FUNC_RETURN(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); + SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); }