- continued improving ASN.1 decoding

- improved debug levels
- added some PC/SC Lite workarounds


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@87 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2001-12-21 23:34:47 +00:00
parent 41416437e5
commit c17ff3ebdf
14 changed files with 290 additions and 309 deletions

View File

@ -354,6 +354,7 @@ static int decode_bit_string(const u8 * inbuf, int inlen, void *outbuf,
int octets_left = inlen - 1; int octets_left = inlen - 1;
int i, count = 0; int i, count = 0;
memset(outbuf, 0, outlen);
in++; in++;
if (outlen < octets_left) if (outlen < octets_left)
return SC_ERROR_BUFFER_TOO_SMALL; 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 *len = entry->len;
int r = 0; int r = 0;
if (ctx->debug > 2) { if (ctx->debug >= 3) {
u8 line[128], *linep = line; u8 line[128], *linep = line;
int i; int i;
@ -556,6 +557,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
} }
break; break;
case SC_ASN1_INTEGER: case SC_ASN1_INTEGER:
case SC_ASN1_ENUMERATED:
if (parm != NULL) if (parm != NULL)
r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm); r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm);
break; break;
@ -627,7 +629,7 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1,
struct sc_asn1_struct *entry = asn1; struct sc_asn1_struct *entry = asn1;
int left = len, objlen; int left = len, objlen;
if (ctx->debug > 2) if (ctx->debug >= 3)
debug(ctx, "called, depth %d%s\n", depth, choice ? ", choice" : ""); debug(ctx, "called, depth %d%s\n", depth, choice ? ", choice" : "");
if (left < 2) if (left < 2)
return SC_ERROR_ASN1_END_OF_CONTENTS; 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 (obj == NULL) {
if (choice) if (choice)
continue; 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; continue;
}
error(ctx, "mandatory ASN.1 object '%s' not found\n", entry->name); error(ctx, "mandatory ASN.1 object '%s' not found\n", entry->name);
if (ctx->debug && left) { if (ctx->debug && left) {
u8 line[128], *linep = line; 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); 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); r = asn1_decode_entry(ctx, entry, obj, objlen, depth);
if (r) if (r)
@ -663,14 +669,14 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1,
break; break;
} }
if (choice && asn1[idx].name == NULL) /* No match */ 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) if (newp != NULL)
*newp = p; *newp = p;
if (len_left != NULL) if (len_left != NULL)
*len_left = left; *len_left = left;
if (choice) if (choice)
SC_FUNC_RETURN(ctx, idx); SC_FUNC_RETURN(ctx, 3, idx);
SC_FUNC_RETURN(ctx, 0); SC_FUNC_RETURN(ctx, 3, 0);
} }
int sc_asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, int sc_asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1,

View File

@ -32,16 +32,7 @@ void error(struct sc_context *ctx, const char *format, ...)
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
do_log2(ctx, SC_LOG_ERROR, "", format, ap); do_log2(ctx, SC_LOG_TYPE_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);
va_end(ap); va_end(ap);
} }
@ -50,7 +41,7 @@ void debug(struct sc_context *ctx, const char *format, ...)
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
do_log2(ctx, SC_LOG_DEBUG, "", format, ap); do_log2(ctx, SC_LOG_TYPE_DEBUG, "", format, ap);
va_end(ap); va_end(ap);
} }
@ -79,12 +70,11 @@ void do_log2(struct sc_context *ctx, int type, const char *file,
assert(ctx != NULL); assert(ctx != NULL);
if (ctx->use_std_output) { if (ctx->use_std_output) {
switch (type) { switch (type) {
case SC_LOG_ERROR: case SC_LOG_TYPE_ERROR:
outf = stderr; outf = stderr;
break; break;
case SC_LOG_NORMAL:
case SC_LOG_DEBUG: case SC_LOG_TYPE_DEBUG:
case SC_LOG_DEBUG2:
outf = stdout; outf = stdout;
} }
if (outf == NULL) if (outf == NULL)
@ -122,14 +112,15 @@ void do_log2(struct sc_context *ctx, int type, const char *file,
if (do_color) { if (do_color) {
color_sfx = "\e[0m"; color_sfx = "\e[0m";
switch (type) { switch (type) {
case SC_LOG_ERROR: case SC_LOG_TYPE_ERROR:
color_pfx = "\e[01;31m"; color_pfx = "\e[01;31m";
break; break;
case SC_LOG_NORMAL: #if 0
case SC_LOG_TYPE_NORMAL:
color_pfx = "\e[01;33m"; color_pfx = "\e[01;33m";
break; break;
case SC_LOG_DEBUG: #endif
case SC_LOG_DEBUG2: case SC_LOG_TYPE_DEBUG:
color_pfx = "\e[00;32m"; color_pfx = "\e[00;32m";
break; break;
} }

View File

@ -24,34 +24,29 @@
#include "opensc.h" #include "opensc.h"
#include <stdarg.h> #include <stdarg.h>
#define SC_LOG_ERROR 0 #define SC_LOG_TYPE_ERROR 0
#define SC_LOG_NORMAL 1 #define SC_LOG_TYPE_VERBOSE 1
#define SC_LOG_VERBOSE 2 #define SC_LOG_TYPE_DEBUG 2
#define SC_LOG_DEBUG 3
#define SC_LOG_DEBUG2 4
#ifdef __GNUC__ #ifdef __GNUC__
#define error(ctx, format, args...) do_log(ctx, SC_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) #define error(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_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_TYPE_DEBUG, __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)
#else #else
void error(struct sc_context *ctx, const char *format, ...); 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 debug(struct sc_context *ctx, const char *format, ...);
void debug2(struct sc_context *ctx, const char *format, ...);
#endif #endif
#define SC_FUNC_CALLED(ctx) {\ #define SC_FUNC_CALLED(ctx, level) {\
if ((ctx)->debug > 2)\ if ((ctx)->debug >= level)\
debug(ctx, "called\n"); } debug(ctx, "called\n"); }
#define SC_FUNC_RETURN(ctx, r) {\ #define SC_FUNC_RETURN(ctx, level, r) {\
int _ret = r;\ int _ret = r;\
if (_ret < 0) {\ if (_ret < 0) {\
error(ctx, "returning with: %s\n", sc_strerror(_ret));\ 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);\ debug(ctx, "returning with: %d\n", _ret);\
}\ }\
return _ret; } return _ret; }

View File

@ -58,6 +58,7 @@ struct sc_pkcs15_pin_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
struct sc_pkcs15_id auth_id; struct sc_pkcs15_id auth_id;
int reference;
int flags, type; int flags, type;
int min_length, stored_length; int min_length, stored_length;
u8 pad_char; u8 pad_char;
@ -129,7 +130,7 @@ struct sc_pkcs15_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
struct sc_pkcs15_id id; /* correlates to public certificate id */ struct sc_pkcs15_id id; /* correlates to public certificate id */
int usage, access_flags; int usage, access_flags, native;
int key_reference; int key_reference;
struct sc_path file_id; struct sc_path file_id;
@ -173,9 +174,12 @@ struct sc_pkcs15_defaults {
int arg; 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); 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, int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey, const struct sc_pkcs15_prkey_info *prkey,

View File

@ -42,7 +42,7 @@ extern "C" {
#define SC_ERROR_OUT_OF_MEMORY -1009 #define SC_ERROR_OUT_OF_MEMORY -1009
#define SC_ERROR_NO_READERS_FOUND -1010 #define SC_ERROR_NO_READERS_FOUND -1010
#define SC_ERROR_OBJECT_NOT_VALID -1011 #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_PIN_CODE_INCORRECT -1013
#define SC_ERROR_SECURITY_STATUS_NOT_SATISFIED -1014 #define SC_ERROR_SECURITY_STATUS_NOT_SATISFIED -1014
#define SC_ERROR_CONNECTING_TO_RES_MGR -1015 #define SC_ERROR_CONNECTING_TO_RES_MGR -1015
@ -106,7 +106,6 @@ extern "C" {
#define SC_ASN1_MAX_OBJECT_ID_OCTETS 16 #define SC_ASN1_MAX_OBJECT_ID_OCTETS 16
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned int uint32;
struct sc_object_id { struct sc_object_id {
int value[SC_ASN1_MAX_OBJECT_ID_OCTETS]; int value[SC_ASN1_MAX_OBJECT_ID_OCTETS];
@ -132,6 +131,9 @@ struct sc_file {
unsigned int magic; unsigned int magic;
}; };
#define SC_SEC_OPERATION_DECIPHER 0
#define SC_SEC_OPERATION_SIGN 1
struct sc_security_env { struct sc_security_env {
int algorithm_ref; int algorithm_ref;
struct sc_path key_file_id; struct sc_path key_file_id;
@ -146,19 +148,19 @@ struct sc_card_operations {
int (*init)(struct sc_card *card); int (*init)(struct sc_card *card);
int (*finish)(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); 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); 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); 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); 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); 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); 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); const u8 * buf, size_t count);
/* possibly TODO: record handling */ /* possibly TODO: record handling */
int (*select_file)(struct sc_card *card, struct sc_file *file, int (*select_file)(struct sc_card *card, struct sc_file *file,

View File

@ -224,7 +224,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_cert *cert; struct sc_pkcs15_cert *cert;
assert(p15card != NULL && info != NULL && cert_out != NULL); 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); r = find_cached_cert(p15card, info, &data, &len);
if (r) { if (r) {
r = sc_select_file(p15card->card, &file, &info->path, 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, struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL,
asn1_type_cert_attr }; asn1_type_cert_attr };
struct sc_asn1_struct asn1_cert[] = { 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 } { NULL }
}; };
@ -332,15 +332,17 @@ static int get_certs_from_file(struct sc_pkcs15_card *card,
return r; return r;
bytes_left = r; bytes_left = r;
do { do {
if (card->cert_count >= SC_PKCS15_MAX_CERTS) struct sc_pkcs15_cert_info tmp;
return SC_ERROR_TOO_MANY_OBJECTS;
r = parse_x509_cert_info(card->card->ctx, r = parse_x509_cert_info(card->card->ctx,
&card->cert_info[card->cert_count], &tmp, &p, &bytes_left);
&p, &bytes_left);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS) if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
break; break;
if (r) if (r)
return 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++; card->cert_count++;
} while (bytes_left); } while (bytes_left);

View File

@ -27,73 +27,49 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
static int decode_pin_info(const u8 *buf, static int parse_pin_info(struct sc_context *ctx,
int buflen, struct sc_pkcs15_pin_info *pin) struct sc_pkcs15_pin_info *pin,
const u8 ** buf, int *buflen)
{ {
const u8 *tag, *p = buf; int r;
int taglen, left = buflen; 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)); memset(pin, 0, sizeof(*pin));
tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* SEQUENCE */ r = sc_asn1_parse(ctx, asn1_pin, *buf, *buflen, buf, buflen);
if (tag == NULL) if (r == 0)
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; pin->magic = SC_PKCS15_PIN_MAGIC;
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;
p = sc_asn1_verify_tag(p, left, 0xA1, &left); /* CONS */ return r;
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;
} }
void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) 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"); 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) struct sc_file *file)
{ {
int r, taglen, left; int r, bytes_left;
const u8 *p, *tag; u8 buf[2048];
u8 buf[MAX_BUFFER_SIZE]; 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); SC_SELECT_FILE_BY_PATH);
if (r) if (r)
return r; return r;
if (file->size > sizeof(buf)) if (file->size > sizeof(buf))
return SC_ERROR_BUFFER_TOO_SMALL; 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) if (r < 0)
return r; return r;
bytes_left = r;
do {
struct sc_pkcs15_pin_info tmp;
left = r; r = parse_pin_info(card->card->ctx,
p = buf; &tmp, &p, &bytes_left);
while ((tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen)) != NULL) { if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
if (p15card->pin_count >= SC_PKCS15_MAX_PINS) break;
return SC_ERROR_TOO_MANY_OBJECTS;
r = decode_pin_info(tag, taglen,
&p15card->pin_info[p15card->pin_count]);
if (r) if (r)
return 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; return 0;
} }
int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) 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; struct sc_context *ctx = p15card->card->ctx;
assert(p15card != NULL); assert(p15card != NULL);
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
if (p15card->pin_count) { if (p15card->pin_count) {
for (i = 0; i < p15card->pin_count; i++) { for (i = 0; i < p15card->pin_count; i++) {
if (p15card->pin_info[i].magic != SC_PKCS15_PIN_MAGIC) 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) if (i == p15card->pin_count)
return i; /* Already enumerated */ return i; /* Already enumerated */
} }
p15card->pin_count = 0;
for (i = 0; i < p15card->aodf_count; i++) { for (i = 0; i < p15card->aodf_count; i++) {
r = get_pins_from_file(p15card, &p15card->file_aodf[i]); r = get_pins_from_file(p15card, &p15card->file_aodf[i]);
SC_TEST_RET(ctx, r, "Failed to read PINs from AODF"); SC_TEST_RET(ctx, r, "Failed to read PINs from AODF");

View File

@ -47,105 +47,97 @@ void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey)
printf("\n"); printf("\n");
} }
static int parse_prkey_info(const u8 * buf, static int parse_rsa_prkey_info(struct sc_context *ctx,
int buflen, struct sc_pkcs15_prkey_info *prkey) struct sc_pkcs15_prkey_info *prkey,
const u8 **buf, int *buflen)
{ {
const u8 *tag, *p; int r;
int taglen, left; 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 */ struct sc_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr,
if (tag == NULL) asn1_com_prkey_attr, asn1_type_attr };
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; struct sc_asn1_struct asn1_prkey[] = {
sc_pkcs15_parse_common_object_attr(&prkey->com_attr, tag, taglen); { "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj },
{ NULL }
};
p = sc_asn1_skip_tag(&buf, &buflen, 0x30, &left); /* SEQUENCE */ prkey->key_reference = -1;
if (tag == NULL) prkey->native = 1;
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND;
tag = sc_asn1_skip_tag(&p, &left, 0x04, &taglen); /* OCTET STRING */ r = sc_asn1_parse(ctx, asn1_prkey, *buf, *buflen, buf, buflen);
if (tag == NULL)
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND;
memcpy(prkey->id.value, tag, taglen);
prkey->id.len = taglen;
tag = sc_asn1_skip_tag(&p, &left, 0x03, &taglen); /* BIT STRING */ return r;
if (tag == NULL) }
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND;
sc_asn1_decode_bit_string(tag, taglen, &prkey->usage,
sizeof(prkey->usage));
tag = sc_asn1_skip_tag(&p, &left, 0x01, &taglen); /* BOOLEAN */ static int get_prkeys_from_file(struct sc_pkcs15_card *card,
if (tag != NULL) { struct sc_file *file)
/* FIXME */ {
} int r, bytes_left;
u8 buf[2048];
const u8 *p = buf;
tag = sc_asn1_skip_tag(&p, &left, 0x03, &taglen); /* BIT STRING */ r = sc_select_file(card->card, file, &file->path,
if (tag != NULL) { SC_SELECT_FILE_BY_PATH);
sc_asn1_decode_bit_string(tag, taglen, if (r)
&prkey->access_flags, return r;
sizeof(prkey->access_flags)); if (file->size > sizeof(buf))
} else return SC_ERROR_BUFFER_TOO_SMALL;
prkey->access_flags = 0; 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 */ r = parse_rsa_prkey_info(card->card->ctx,
if (tag != NULL && taglen) { &tmp, &p, &bytes_left);
prkey->key_reference = tag[0]; if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
} else break;
prkey->key_reference = -1; if (r)
return r;
if (card->prkey_count >= SC_PKCS15_MAX_PRKEYS)
/* FIXME */ return SC_ERROR_TOO_MANY_OBJECTS;
p = sc_asn1_find_tag(buf, buflen, 0xA1, &left); card->prkey_info[card->prkey_count] = tmp;
if (p == NULL) card->prkey_count++;
return SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND; } while (bytes_left);
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);
return 0; return 0;
} }
int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card) int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card)
{ {
int r, left, taglen; int r, i;
const u8 *p, *tag;
u8 buf[1024];
assert(card != NULL); assert(card != NULL);
if (card->prkey_count) if (card->prkey_count)
return card->prkey_count; /* already enumerated */ return card->prkey_count; /* already enumerated */
card->prkey_count = 0; for (i = 0; i < 1; i++) {
r = sc_select_file(card->card, &card->file_prkdf, r = get_prkeys_from_file(card, &card->file_prkdf);
&card->file_prkdf.path, SC_SELECT_FILE_BY_PATH); if (r != 0)
if (r) return 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++;
} }
return card->prkey_count; return card->prkey_count;
} }

View File

@ -40,13 +40,14 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
senv.operation = 0; senv.operation = 0;
senv.key_ref = prkey->key_reference; senv.key_ref = prkey->key_reference;
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app, r = sc_select_file(p15card->card, &p15card->file_app,
&p15card->file_app.path, SC_SELECT_FILE_BY_PATH); &p15card->file_app.path, SC_SELECT_FILE_BY_PATH);
SC_TEST_RET(ctx, r, "sc_select_file() failed"); SC_TEST_RET(ctx, r, "sc_select_file() failed");
r = sc_select_file(p15card->card, &p15card->file_app, r = sc_select_file(p15card->card, &p15card->file_app,
&p15card->file_app.path, SC_SELECT_FILE_BY_PATH); &p15card->file_app.path, SC_SELECT_FILE_BY_PATH);
SC_TEST_RET(ctx, r, "sc_select_file() failed"); 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 */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
r = sc_set_security_env(p15card->card, &senv); 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.operation = 1;
senv.key_ref = prkey->key_reference; senv.key_ref = prkey->key_reference;
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app, r = sc_select_file(p15card->card, &p15card->file_app,
&p15card->file_app.path, SC_SELECT_FILE_BY_PATH); &p15card->file_app.path, SC_SELECT_FILE_BY_PATH);
SC_TEST_RET(ctx, r, "sc_select_file() failed"); 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 */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
r = sc_set_security_env(p15card->card, &senv); r = sc_set_security_env(p15card->card, &senv);

View File

@ -236,7 +236,7 @@ static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen)
return match; return match;
} }
int sc_pkcs15_init(struct sc_card *card, int sc_pkcs15_bind(struct sc_card *card,
struct sc_pkcs15_card **p15card_out) struct sc_pkcs15_card **p15card_out)
{ {
unsigned char buf[MAX_BUFFER_SIZE]; unsigned char buf[MAX_BUFFER_SIZE];
@ -324,7 +324,7 @@ error:
return err; 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->label);
free(p15card->serial_number); free(p15card->serial_number);

View File

@ -58,6 +58,7 @@ struct sc_pkcs15_pin_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
struct sc_pkcs15_id auth_id; struct sc_pkcs15_id auth_id;
int reference;
int flags, type; int flags, type;
int min_length, stored_length; int min_length, stored_length;
u8 pad_char; u8 pad_char;
@ -129,7 +130,7 @@ struct sc_pkcs15_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
struct sc_pkcs15_id id; /* correlates to public certificate id */ struct sc_pkcs15_id id; /* correlates to public certificate id */
int usage, access_flags; int usage, access_flags, native;
int key_reference; int key_reference;
struct sc_path file_id; struct sc_path file_id;
@ -173,9 +174,12 @@ struct sc_pkcs15_defaults {
int arg; 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); 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, int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey, const struct sc_pkcs15_prkey_info *prkey,

View File

@ -24,34 +24,29 @@
#include "opensc.h" #include "opensc.h"
#include <stdarg.h> #include <stdarg.h>
#define SC_LOG_ERROR 0 #define SC_LOG_TYPE_ERROR 0
#define SC_LOG_NORMAL 1 #define SC_LOG_TYPE_VERBOSE 1
#define SC_LOG_VERBOSE 2 #define SC_LOG_TYPE_DEBUG 2
#define SC_LOG_DEBUG 3
#define SC_LOG_DEBUG2 4
#ifdef __GNUC__ #ifdef __GNUC__
#define error(ctx, format, args...) do_log(ctx, SC_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__ , format , ## args) #define error(ctx, format, args...) do_log(ctx, SC_LOG_TYPE_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_TYPE_DEBUG, __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)
#else #else
void error(struct sc_context *ctx, const char *format, ...); 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 debug(struct sc_context *ctx, const char *format, ...);
void debug2(struct sc_context *ctx, const char *format, ...);
#endif #endif
#define SC_FUNC_CALLED(ctx) {\ #define SC_FUNC_CALLED(ctx, level) {\
if ((ctx)->debug > 2)\ if ((ctx)->debug >= level)\
debug(ctx, "called\n"); } debug(ctx, "called\n"); }
#define SC_FUNC_RETURN(ctx, r) {\ #define SC_FUNC_RETURN(ctx, level, r) {\
int _ret = r;\ int _ret = r;\
if (_ret < 0) {\ if (_ret < 0) {\
error(ctx, "returning with: %s\n", sc_strerror(_ret));\ 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);\ debug(ctx, "returning with: %d\n", _ret);\
}\ }\
return _ret; } return _ret; }

View File

@ -118,28 +118,28 @@ int sc_check_apdu(struct sc_context *ctx, const struct sc_apdu *apdu)
switch (apdu->cse) { switch (apdu->cse) {
case SC_APDU_CASE_1: case SC_APDU_CASE_1:
if (apdu->datalen) if (apdu->datalen)
SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
break; break;
case SC_APDU_CASE_2_SHORT: case SC_APDU_CASE_2_SHORT:
if (apdu->datalen) 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) if (apdu->resplen < apdu->le)
SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
break; break;
case SC_APDU_CASE_3_SHORT: case SC_APDU_CASE_3_SHORT:
if (apdu->datalen == 0 || apdu->data == NULL) 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; break;
case SC_APDU_CASE_4_SHORT: case SC_APDU_CASE_4_SHORT:
if (apdu->datalen == 0 || apdu->data == NULL) 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) if (apdu->resplen < apdu->le)
SC_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
break; break;
case SC_APDU_CASE_2_EXT: case SC_APDU_CASE_2_EXT:
case SC_APDU_CASE_3_EXT: case SC_APDU_CASE_3_EXT:
case SC_APDU_CASE_4_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; return 0;
} }
@ -196,7 +196,7 @@ static int sc_transceive_t0(struct sc_card *card, struct sc_apdu *apdu)
dwRecvLength = apdu->resplen + 2; dwRecvLength = apdu->resplen + 2;
if (dwRecvLength > 255) /* FIXME: PC/SC Lite quirk */ if (dwRecvLength > 255) /* FIXME: PC/SC Lite quirk */
dwRecvLength = 255; dwRecvLength = 255;
if (card->ctx->debug > 3) { if (card->ctx->debug >= 5) {
char buf[2048]; char buf[2048];
sc_hex_dump(card->ctx, s, dwSendLength, buf, sizeof(buf)); 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) if (dwRecvLength < 2)
return SC_ERROR_UNKNOWN_RESPONSE; return SC_ERROR_ILLEGAL_RESPONSE;
apdu->sw1 = r[dwRecvLength-2]; apdu->sw1 = r[dwRecvLength-2];
apdu->sw2 = r[dwRecvLength-1]; apdu->sw2 = r[dwRecvLength-1];
dwRecvLength -= 2; dwRecvLength -= 2;
@ -239,12 +239,12 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
{ {
int r; int r;
SC_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, 4);
r = sc_check_apdu(card->ctx, apdu); r = sc_check_apdu(card->ctx, apdu);
SC_TEST_RET(card->ctx, r, "APDU sanity check failed"); SC_TEST_RET(card->ctx, r, "APDU sanity check failed");
r = sc_transceive_t0(card, apdu); r = sc_transceive_t0(card, apdu);
SC_TEST_RET(card->ctx, r, "transceive_t0() failed"); SC_TEST_RET(card->ctx, r, "transceive_t0() failed");
if (card->ctx->debug > 3) { if (card->ctx->debug >= 5) {
char buf[2048]; char buf[2048];
buf[0] = 0; buf[0] = 0;
@ -273,7 +273,7 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
sc_strerror(r)); sc_strerror(r));
return r; return r;
} }
if (card->ctx->debug > 3) { if (card->ctx->debug >= 5) {
char buf[2048]; char buf[2048];
buf[0] = 0; buf[0] = 0;
if (rspapdu.resplen) { if (rspapdu.resplen) {
@ -315,7 +315,7 @@ int sc_detect_card(struct sc_context *ctx, int reader)
SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS]; SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS];
assert(ctx != NULL); assert(ctx != NULL);
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
if (reader >= ctx->reader_count || reader < 0) if (reader >= ctx->reader_count || reader < 0)
return SC_ERROR_INVALID_ARGUMENTS; 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); ret = SCardGetStatusChange(ctx->pcsc_ctx, 0, rgReaderStates, 1);
if (ret != 0) { if (ret != 0) {
error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(ret)); 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) if (rgReaderStates[0].dwEventState & SCARD_STATE_PRESENT) {
SC_FUNC_RETURN(ctx, 1); if (ctx->debug >= 1)
SC_FUNC_RETURN(ctx, 0); 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) 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; int count = 0, i;
assert(ctx != NULL); assert(ctx != NULL);
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
if (reader >= ctx->reader_count) if (reader >= ctx->reader_count)
return SC_ERROR_INVALID_ARGUMENTS; SC_FUNC_RETURN(ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
if (reader < 0) { if (reader < 0) {
if (ctx->reader_count == 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++) { for (i = 0; i < ctx->reader_count; i++) {
rgReaderStates[i].szReader = ctx->readers[i]; rgReaderStates[i].szReader = ctx->readers[i];
rgReaderStates[i].dwCurrentState = rgReaderStates[i].dwCurrentState =
@ -360,13 +365,13 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout)
count); count);
if (ret != 0) { if (ret != 0) {
error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(ret)); 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++) { for (i = 0; i < count; i++) {
if (rgReaderStates[i].dwEventState & SCARD_STATE_CHANGED) 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) int sc_establish_context(struct sc_context **ctx_out)
@ -417,7 +422,7 @@ int sc_destroy_context(struct sc_context *ctx)
int i; int i;
assert(ctx != NULL); assert(ctx != NULL);
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
for (i = 0; i < ctx->reader_count; i++) for (i = 0; i < ctx->reader_count; i++)
free(ctx->readers[i]); free(ctx->readers[i]);
free(ctx); free(ctx);
@ -462,23 +467,23 @@ int sc_connect_card(struct sc_context *ctx,
const struct sc_defaults *defaults; const struct sc_defaults *defaults;
assert(card_out != NULL); assert(card_out != NULL);
SC_FUNC_CALLED(ctx); SC_FUNC_CALLED(ctx, 1);
if (reader >= ctx->reader_count || reader < 0) 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].szReader = ctx->readers[reader];
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE; rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
rv = SCardGetStatusChange(ctx->pcsc_ctx, 0, rgReaderStates, 1); rv = SCardGetStatusChange(ctx->pcsc_ctx, 0, rgReaderStates, 1);
if (rv != 0) { if (rv != 0) {
error(ctx, "SCardGetStatusChange failed: %s\n", pcsc_stringify_error(rv)); 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)) 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)); card = malloc(sizeof(struct sc_card));
if (card == NULL) 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)); memset(card, 0, sizeof(struct sc_card));
rv = SCardConnect(ctx->pcsc_ctx, ctx->readers[reader], rv = SCardConnect(ctx->pcsc_ctx, ctx->readers[reader],
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
@ -506,17 +511,18 @@ int sc_connect_card(struct sc_context *ctx,
pthread_mutex_init(&card->mutex, NULL); pthread_mutex_init(&card->mutex, NULL);
*card_out = card; *card_out = card;
return 0; SC_FUNC_RETURN(ctx, 1, 0);
} }
int sc_disconnect_card(struct sc_card *card) int sc_disconnect_card(struct sc_card *card)
{ {
struct sc_context *ctx = card->ctx;
assert(card != NULL); assert(card != NULL);
SC_FUNC_CALLED(ctx, 1);
SCardDisconnect(card->pcsc_card, SCARD_LEAVE_CARD); SCardDisconnect(card->pcsc_card, SCARD_LEAVE_CARD);
pthread_mutex_destroy(&card->mutex); pthread_mutex_destroy(&card->mutex);
free(card); free(card);
SC_FUNC_RETURN(ctx, 1, 0);
return 0;
} }
const char *sc_strerror(int error) 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) int sc_lock(struct sc_card *card)
{ {
SC_FUNC_CALLED(card->ctx, 2);
pthread_mutex_lock(&card->mutex); 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) int _sc_unlock_int(struct sc_card *card)
@ -596,8 +603,9 @@ int _sc_unlock_int(struct sc_card *card)
int sc_unlock(struct sc_card *card) int sc_unlock(struct sc_card *card)
{ {
SC_FUNC_CALLED(card->ctx, 2);
pthread_mutex_unlock(&card->mutex); 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) int sc_list_files(struct sc_card *card, u8 *buf, int buflen)
@ -605,13 +613,13 @@ int sc_list_files(struct sc_card *card, u8 *buf, int buflen)
struct sc_apdu apdu; struct sc_apdu apdu;
int r; int r;
SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0); sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0);
apdu.resp = buf; apdu.resp = buf;
apdu.resplen = buflen; apdu.resplen = buflen;
apdu.le = 0; apdu.le = 0;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
if (r) SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return r;
if (apdu.resplen == 0) if (apdu.resplen == 0)
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return apdu.resplen; 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]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
struct sc_apdu apdu; struct sc_apdu apdu;
SC_FUNC_CALLED(card->ctx, 1);
len = SC_MAX_APDU_BUFFER_SIZE; len = SC_MAX_APDU_BUFFER_SIZE;
r = construct_fci(file, sbuf, &len); r = construct_fci(file, sbuf, &len);
if (r) SC_TEST_RET(card->ctx, r, "construct_fci() failed");
return r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
apdu.lc = len; apdu.lc = len;
@ -671,9 +679,8 @@ int sc_create_file(struct sc_card *card, const struct sc_file *file)
apdu.resp = rbuf; apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
if (r) SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return r; SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
} }
int sc_delete_file(struct sc_card *card, int file_id) 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]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
struct sc_apdu apdu; struct sc_apdu apdu;
SC_FUNC_CALLED(card->ctx, 1);
sbuf[0] = (file_id >> 8) & 0xFF; sbuf[0] = (file_id >> 8) & 0xFF;
sbuf[1] = file_id & 0xFF; sbuf[1] = file_id & 0xFF;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00); 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; apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
if (r) SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return r; if (apdu.resplen != 0)
if (apdu.resplen != 2) SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_ILLEGAL_RESPONSE);
return -1; SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
} }
int sc_file_valid(const struct sc_file *file) int sc_file_valid(const struct sc_file *file)

View File

@ -33,7 +33,7 @@ int sc_set_security_env(struct sc_card *card,
int r; int r;
assert(card != NULL && env != NULL); 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); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
if (env->operation == 1) { if (env->operation == 1) {
apdu.p1 = 0x81; apdu.p1 = 0x81;
@ -61,7 +61,7 @@ int sc_set_security_env(struct sc_card *card,
apdu.resplen = 0; apdu.resplen = 0;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 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) 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]; u8 rbuf[MAX_BUFFER_SIZE];
assert(card != NULL); 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); sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, num);
apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf); apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
apdu.resp = rbuf; apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 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, int sc_decipher(struct sc_card *card,
@ -89,9 +89,9 @@ int sc_decipher(struct sc_card *card,
u8 sbuf[MAX_BUFFER_SIZE]; u8 sbuf[MAX_BUFFER_SIZE];
assert(card != NULL && crgram != NULL && out != NULL); assert(card != NULL && crgram != NULL && out != NULL);
SC_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, 2);
if (crgram_len > 255) 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); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x80, 0x86);
apdu.resp = rbuf; apdu.resp = rbuf;
@ -108,9 +108,9 @@ int sc_decipher(struct sc_card *card,
int len = apdu.resplen > outlen ? outlen : apdu.resplen; int len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len); 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, 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]; u8 sbuf[MAX_BUFFER_SIZE];
assert(card != NULL && data != NULL && out != NULL); assert(card != NULL && data != NULL && out != NULL);
SC_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, 2);
if (datalen > 255) 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, sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x9E,
0x9A); 0x9A);
@ -142,9 +142,9 @@ int sc_compute_signature(struct sc_card *card,
int len = apdu.resplen > outlen ? outlen : apdu.resplen; int len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len); 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, 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]; u8 sbuf[MAX_BUFFER_SIZE];
int r; int r;
SC_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, 2);
if (pinlen >= MAX_BUFFER_SIZE) 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); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0, ref);
memcpy(sbuf, pin, pinlen); memcpy(sbuf, pin, pinlen);
apdu.lc = 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 (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) {
if (tries_left != NULL) if (tries_left != NULL)
*tries_left = apdu.sw2 & 0x0F; *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, 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]; u8 sbuf[MAX_BUFFER_SIZE];
int r, p1 = 0, len = oldlen + newlen; int r, p1 = 0, len = oldlen + newlen;
SC_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, 1);
if (len >= MAX_BUFFER_SIZE) 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) if (oldlen == 0)
p1 = 1; p1 = 1;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, ref); 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 (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) {
if (tries_left != NULL) if (tries_left != NULL)
*tries_left = apdu.sw2 & 0x0F; *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, 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; int r, p1 = 0, len = puklen + newlen;
if (len >= MAX_BUFFER_SIZE) 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 (puklen == 0) {
if (newlen == 0) if (newlen == 0)
p1 = 3; 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); r = sc_transmit_apdu(card, &apdu);
memset(sbuf, 0, len); memset(sbuf, 0, len);
SC_TEST_RET(card->ctx, r, "APDU transmit failed"); 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));
} }