From 3e96a893ec8be3a7e8196204af4ce8bc595658f6 Mon Sep 17 00:00:00 2001 From: jey Date: Sat, 29 Dec 2001 19:03:46 +0000 Subject: [PATCH] - ported certificate reading to new ASN.1 code git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@119 c6295689-39f2-0310-b995-f0e70906c6a9 --- NEWS | 2 +- src/libopensc/asn1.c | 93 ++++++++++++-------- src/libopensc/asn1.h | 20 +++-- src/libopensc/iso7816.c | 18 ++-- src/libopensc/pkcs15-cert.c | 166 +++++++++++++++++++----------------- src/libopensc/pkcs15.c | 4 +- src/libopensc/sc-asn1.h | 20 +++-- 7 files changed, 184 insertions(+), 139 deletions(-) diff --git a/NEWS b/NEWS index de95291d..eaf18ad7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ NEWS for OpenSC -- History of user visible changes -New in 0.4.0; 2001-12-xx; Juha Yrjölä: +New in 0.4.0; 2001-12-29; Juha Yrjölä: * Finished migrating to Autotools * Rewritten ASN.1 decoder (should work better on all PKCS #15 cards) * Abstracted card handling, so adding support for new cards is a whiz, diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 141198d8..0813bb87 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -248,9 +248,11 @@ void sc_asn1_print_tags(const u8 * buf, int buflen) print_tags_recursive(buf, buf, buflen, 0); } -const u8 *sc_asn1_find_tag(const u8 * buf, int buflen, int tag_in, int *taglen_in) +const u8 *sc_asn1_find_tag(struct sc_context *ctx, const u8 * buf, + size_t buflen, unsigned int tag_in, size_t *taglen_in) { - int left = buflen, cla, tag, taglen; + size_t left = buflen, taglen; + unsigned int cla, tag; const u8 *p = buf; *taglen_in = 0; @@ -265,40 +267,18 @@ const u8 *sc_asn1_find_tag(const u8 * buf, int buflen, int tag_in, int *taglen_i *taglen_in = taglen; return p; } - if ((cla | tag) == 0xF0) { /* skip 0xF0 foobar tags */ - fprintf(stderr, "Foobar tag skipped\n"); - taglen = 0; - } left -= taglen; p += taglen; } return NULL; } -const u8 *sc_asn1_skip_tag(const u8 ** buf, int *buflen, int tag_in, int *taglen_out) +const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf, size_t *buflen, + unsigned int tag_in, size_t *taglen_out) { const u8 *p = *buf; - int len = *buflen, cla, tag, taglen; - - if (read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != 1) - return NULL; - if ((tag | cla) != tag_in) - return NULL; - len -= (p - *buf); /* header size */ - if (taglen > len) { - fprintf(stderr, "skip_tag(): too long tag\n"); - return NULL; - } - *buflen -= (p - *buf) + taglen; - *buf = p + taglen; /* point to next tag */ - *taglen_out = taglen; - return p; -} - -static const u8 *sc_asn1_skip_tag2(struct sc_context *ctx, const u8 ** buf, int *buflen, unsigned int tag_in, int *taglen_out) -{ - const u8 *p = *buf; - int len = *buflen, cla, tag, taglen; + size_t len = *buflen, taglen; + unsigned int cla, tag; if (read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != 1) return NULL; @@ -340,9 +320,10 @@ static const u8 *sc_asn1_skip_tag2(struct sc_context *ctx, const u8 ** buf, int return p; } -const u8 *sc_asn1_verify_tag(const u8 * buf, int buflen, int tag_in, int *taglen_out) +const u8 *sc_asn1_verify_tag(struct sc_context *ctx, const u8 * buf, size_t buflen, + unsigned int tag_in, size_t *taglen_out) { - return sc_asn1_skip_tag(&buf, &buflen, tag_in, taglen_out); + return sc_asn1_skip_tag(ctx, &buf, &buflen, tag_in, taglen_out); } static int decode_bit_string(const u8 * inbuf, int inlen, void *outbuf, @@ -523,10 +504,13 @@ static int asn1_parse_p15_object(struct sc_context *ctx, const u8 *in, int len, } static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entry, - const u8 *obj, int objlen, int depth) + const u8 *obj, size_t objlen, int depth) { void *parm = entry->parm; - int *len = entry->len; + int (*callback_func)(struct sc_context *ctx, void *arg, const u8 *obj, + size_t objlen, int depth) = + (int (*)(struct sc_context *, void *, const u8 *, size_t, int)) parm; + int *len = (int *) entry->arg; int r = 0; if (ctx->debug >= 3) { @@ -562,9 +546,22 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr if (parm != NULL) r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm); break; + case SC_ASN1_BIT_STRING_NI: case SC_ASN1_BIT_STRING: - if (parm != NULL && len != NULL) { - r = sc_asn1_decode_bit_string(obj, objlen, (u8 *) parm, *len); + if (parm != NULL) { + int invert = entry->type == SC_ASN1_BIT_STRING ? 1 : 0; + assert(len != NULL); + if (entry->flags & SC_ASN1_ALLOC) { + u8 **buf = (u8 **) parm; + *buf = malloc(objlen-1); + if (*buf == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + break; + } + *len = objlen-1; + parm = *buf; + } + r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert); if (r >= 0) { *len = r; r = 0; @@ -575,7 +572,17 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr if (parm != NULL) { int c; assert(len != NULL); - c = objlen > *len ? *len : objlen; + if (entry->flags & SC_ASN1_ALLOC) { + u8 **buf = (u8 **) parm; + *buf = malloc(objlen); + if (*buf == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + break; + } + c = *len = objlen; + parm = *buf; + } else + c = objlen > *len ? *len : objlen; memcpy(parm, obj, c); *len = c; @@ -588,6 +595,16 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr case SC_ASN1_UTF8STRING: if (parm != NULL) { assert(len != NULL); + if (entry->flags & SC_ASN1_ALLOC) { + u8 **buf = (u8 **) parm; + *buf = malloc(objlen-1); + if (*buf == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + break; + } + *len = objlen-1; + parm = *buf; + } r = sc_asn1_decode_utf8string(obj, objlen, parm, len); } break; @@ -608,6 +625,10 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr if (entry->parm != NULL) r = asn1_parse_p15_object(ctx, obj, objlen, (struct sc_pkcs15_object *) parm, depth); break; + case SC_ASN1_CALLBACK: + if (entry->parm != NULL) + r = callback_func(ctx, entry->arg, obj, objlen, depth); + break; default: error(ctx, "invalid ASN.1 type: %d\n", entry->type); assert(0); @@ -639,7 +660,7 @@ static int asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, for (idx = 0; asn1[idx].name != NULL; idx++) { entry = &asn1[idx]; r = 0; - obj = sc_asn1_skip_tag2(ctx, &p, &left, entry->tag, &objlen); + obj = sc_asn1_skip_tag(ctx, &p, &left, entry->tag, &objlen); if (obj == NULL) { if (choice) continue; diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index 4693bb99..8456eae7 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -30,7 +30,7 @@ struct sc_asn1_struct { unsigned int tag; unsigned int flags; void *parm; - int *len; + void *arg; }; struct sc_pkcs15_object { @@ -47,9 +47,12 @@ int sc_asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, int sc_asn1_parse_choice(struct sc_context *ctx, struct sc_asn1_struct *asn1, const u8 *in, int len, const u8 **newp, int *left); -const u8 *sc_asn1_find_tag(const u8 * buf, int buflen, int tag, int *taglen); -const u8 *sc_asn1_verify_tag(const u8 * buf, int buflen, int tag, int *taglen); -const u8 *sc_asn1_skip_tag(const u8 ** buf, int *buflen, int tag, int *taglen); +const u8 *sc_asn1_find_tag(struct sc_context *ctx, const u8 * buf, + size_t buflen, unsigned int tag, size_t *taglen); +const u8 *sc_asn1_verify_tag(struct sc_context *ctx, const u8 * buf, + size_t buflen, unsigned int tag, size_t *taglen); +const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf, + size_t *buflen, unsigned int tag, size_t *taglen); /* DER encoding */ @@ -82,10 +85,12 @@ int sc_asn1_decode_object_id(const u8 * inbuf, int inlen, #define SC_ASN1_PRESENT 0x00000001 #define SC_ASN1_OPTIONAL 0x00000002 +#define SC_ASN1_ALLOC 0x00000004 #define SC_ASN1_BOOLEAN 1 #define SC_ASN1_INTEGER 2 #define SC_ASN1_BIT_STRING 3 +#define SC_ASN1_BIT_STRING_NI 128 #define SC_ASN1_OCTET_STRING 4 #define SC_ASN1_NULL 5 #define SC_ASN1_OBJECT 6 @@ -98,14 +103,17 @@ int sc_asn1_decode_object_id(const u8 * inbuf, int inlen, #define SC_ASN1_GENERALIZEDTIME 24 /* internal structures */ -#define SC_ASN1_STRUCT 128 -#define SC_ASN1_CHOICE 129 +#define SC_ASN1_STRUCT 129 +#define SC_ASN1_CHOICE 130 /* 'complex' structures */ #define SC_ASN1_PATH 256 #define SC_ASN1_PKCS15_ID 257 #define SC_ASN1_PKCS15_OBJECT 258 +/* use callback function */ +#define SC_ASN1_CALLBACK 384 + #define ASN1_TAG_CLASS 0xC0 #define ASN1_TAG_UNIVERSAL 0x00 #define ASN1_TAG_APPLICATION 0x40 diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index cd36ea23..c23190f6 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -103,28 +103,28 @@ static void parse_sec_attr(struct sc_file *file, const u8 *buf, size_t len) } static void process_fci(struct sc_context *ctx, struct sc_file *file, - const u8 *buf, int buflen) + const u8 *buf, size_t buflen) { - int taglen, len = buflen; + size_t taglen, len = buflen; const u8 *tag = NULL, *p = buf; if (ctx->debug >= 3) debug(ctx, "processing FCI bytes\n"); - tag = sc_asn1_find_tag(p, len, 0x83, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); if (tag != NULL && taglen == 2) { file->id = (tag[0] << 8) | tag[1]; if (ctx->debug >= 3) debug(ctx, " file identifier: 0x%02X%02X\n", tag[0], tag[1]); } - tag = sc_asn1_find_tag(p, len, 0x81, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen); if (tag != NULL && taglen >= 2) { int bytes = (tag[0] << 8) + tag[1]; if (ctx->debug >= 3) debug(ctx, " bytes in file: %d\n", bytes); file->size = bytes; } - tag = sc_asn1_find_tag(p, len, 0x82, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); if (tag != NULL) { if (taglen > 0) { unsigned char byte = tag[0]; @@ -159,7 +159,7 @@ static void process_fci(struct sc_context *ctx, struct sc_file *file, } } } - tag = sc_asn1_find_tag(p, len, 0x84, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen); if (tag != NULL && taglen > 0 && taglen <= 16) { char name[17]; int i; @@ -178,18 +178,18 @@ static void process_fci(struct sc_context *ctx, struct sc_file *file, if (ctx->debug >= 3) debug(ctx, "File name: %s\n", name); } - tag = sc_asn1_find_tag(p, len, 0x85, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen); if (tag != NULL && taglen && taglen <= SC_MAX_PROP_ATTR_SIZE) { memcpy(file->prop_attr, tag, taglen); file->prop_attr_len = taglen; } else file->prop_attr_len = 0; - tag = sc_asn1_find_tag(p, len, 0xA5, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen); if (tag != NULL && taglen && taglen <= SC_MAX_PROP_ATTR_SIZE) { memcpy(file->prop_attr, tag, taglen); file->prop_attr_len = taglen; } - tag = sc_asn1_find_tag(p, len, 0x86, &taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen); if (tag != NULL && taglen && taglen <= SC_MAX_SEC_ATTR_SIZE) parse_sec_attr(file, tag, taglen); else diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 4c6ffabf..f0cd1ee7 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -31,98 +31,106 @@ #undef CACHE_CERTS -static int parse_rsa_pubkey(const u8 *buf, int buflen, struct sc_pkcs15_rsa_pubkey *key) +static int parse_rsa_pubkey(struct sc_context *ctx, struct sc_pkcs15_rsa_pubkey *key) { - const u8 *tag; - int taglen; - - buf = sc_asn1_verify_tag(buf, buflen, 0x30, &buflen); - if (buf == NULL) - return -1; - - tag = sc_asn1_verify_tag(buf, buflen, 0x02, &taglen); - if (tag == NULL) - return -1; - key->modulus = malloc(taglen); - memcpy(key->modulus, tag, taglen); - key->modulus_len = taglen; - tag += taglen; - buflen -= tag - buf; - tag = sc_asn1_verify_tag(tag, buflen, 0x02, &taglen); - if (sc_asn1_decode_integer(tag, taglen, (int *) &key->exponent)) { - free(key->modulus); + struct sc_asn1_struct asn1_rsa_pubkey[] = { + { "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, &key->modulus, &key->modulus_len }, + { "publicExponent", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &key->exponent }, + { NULL } + }; + const u8 *obj; + size_t objlen; + int r; + + obj = sc_asn1_verify_tag(ctx, key->data, key->data_len, ASN1_SEQUENCE | SC_ASN1_CONS, + &objlen); + if (obj == NULL) { + error(ctx, "RSA public key not found\n"); return SC_ERROR_INVALID_ASN1_OBJECT; } + r = sc_asn1_parse(ctx, asn1_rsa_pubkey, obj, objlen, NULL, NULL); + SC_TEST_RET(ctx, r, "ASN.1 parsing failed"); + return 0; } -static int parse_cert(const u8 *buf, int buflen, struct sc_pkcs15_cert *cert) +struct asn1_algorithm_id { + struct sc_object_id id; +}; + +static int parse_algorithm_id(struct sc_context *ctx, void *arg, const u8 *obj, + size_t objlen, int depth) { - const u8 *tag, *p; - u8 *tmpbuf; - int taglen, left, r; - struct sc_pkcs15_rsa_pubkey *key = &cert->key; - const u8 *buf0 = buf; + struct asn1_algorithm_id *alg_id = (struct asn1_algorithm_id *) arg; + struct sc_asn1_struct asn1_alg_id[] = { + { "algorithm", SC_ASN1_OBJECT, ASN1_OBJECT, 0, &alg_id->id }, + { "parameters", SC_ASN1_STRUCT, 0, SC_ASN1_OPTIONAL, NULL }, + { NULL } + }; + int r; - buf = sc_asn1_verify_tag(buf, buflen, 0x30, &buflen); /* SEQUENCE */ - if (buf == NULL) /* Certificate */ - return SC_ERROR_INVALID_ASN1_OBJECT; - cert->data_len = (buf - buf0) + buflen; - p = sc_asn1_skip_tag(&buf, &buflen, 0x30, &left); /* SEQUENCE */ - if (p == NULL) /* tbsCertificate */ - return SC_ERROR_INVALID_ASN1_OBJECT; - cert->version = 0; - tag = sc_asn1_skip_tag(&p, &left, 0xA0, &taglen); /* Version */ - if (tag != NULL) { - tag = sc_asn1_verify_tag(tag, taglen, 0x02, &taglen); - if (tag != NULL) { - sc_asn1_decode_integer(tag, taglen, &cert->version); - cert->version++; - } - } - tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); /* INTEGER */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - sc_asn1_decode_integer(tag, taglen, (int *) &cert->serial); + r = sc_asn1_parse(ctx, asn1_alg_id, obj, objlen, NULL, NULL); + SC_TEST_RET(ctx, r, "ASN.1 parsing failed"); + + return 0; +} - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* signatureId */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* issuer */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* validity */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* subject */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - - tag = sc_asn1_skip_tag(&p, &left, 0x30, &taglen); /* subjectPKInfo */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - /* FIXME: get the algorithm ID */ - tag = sc_asn1_find_tag(tag, taglen, 0x03, &taglen); /* subjectPubKey */ - if (tag == NULL) - return SC_ERROR_INVALID_ASN1_OBJECT; - tmpbuf = malloc(taglen-1); - - r = sc_asn1_decode_bit_string_ni(tag, taglen, tmpbuf, taglen-1); - if (r < 0) { - free(tmpbuf); +static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen, struct sc_pkcs15_cert *cert) +{ + int r; + struct sc_pkcs15_rsa_pubkey *key = &cert->key; + struct asn1_algorithm_id pk_alg, sig_alg; + u8 *pk = NULL; + size_t pklen = 0; + struct sc_asn1_struct asn1_version[] = { + { "version", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &cert->version }, + { NULL } + }; + struct sc_asn1_struct asn1_pkinfo[] = { + { "algorithm", SC_ASN1_CALLBACK, ASN1_SEQUENCE | SC_ASN1_CONS, 0, parse_algorithm_id, &pk_alg }, + { "subjectPublicKey", SC_ASN1_BIT_STRING_NI, ASN1_BIT_STRING, SC_ASN1_ALLOC, &pk, &pklen }, + { NULL } + }; + struct sc_asn1_struct asn1_tbscert[] = { + { "version", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, asn1_version }, + { "serialNumber", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &cert->serial }, + { "signature", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { "issuer", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { "validity", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { "subject", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { "subjectPublicKeyInfo",SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_pkinfo }, + { NULL } + }; + struct sc_asn1_struct asn1_cert[] = { + { "tbsCertificate", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert }, + { "signatureAlgorithm", SC_ASN1_CALLBACK, ASN1_SEQUENCE | SC_ASN1_CONS, 0, parse_algorithm_id, &sig_alg }, + { "signatureValue", SC_ASN1_BIT_STRING,ASN1_BIT_STRING, 0, NULL, 0 }, + { NULL } + }; + const u8 *obj; + size_t objlen; + + obj = sc_asn1_verify_tag(ctx, buf, buflen, ASN1_SEQUENCE | SC_ASN1_CONS, + &objlen); + if (obj == NULL) { + error(ctx, "X.509 certificate not found\n"); return SC_ERROR_INVALID_ASN1_OBJECT; } - r >>= 3; - key->data = tmpbuf; - key->data_len = taglen-1; - r = parse_rsa_pubkey(tmpbuf, r, key); + cert->data_len = objlen + (obj - buf); + r = sc_asn1_parse(ctx, asn1_cert, obj, objlen, NULL, NULL); + SC_TEST_RET(ctx, r, "ASN.1 parsing failed"); + + cert->version++; + pklen >>= 3; /* convert number of bits to bytes */ + key->data = pk; + key->data_len = pklen; + /* FIXME: ignore the object id for now, and presume it's RSA */ + r = parse_rsa_pubkey(ctx, key); if (r) { - free(tmpbuf); + free(key->data); return SC_ERROR_INVALID_ASN1_OBJECT; } + return 0; } @@ -259,7 +267,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, return SC_ERROR_OUT_OF_MEMORY; } memset(cert, 0, sizeof(struct sc_pkcs15_cert)); - if (parse_cert(data, len, cert)) { + if (parse_x509_cert(p15card->card->ctx, data, len, cert)) { free(data); free(cert); return SC_ERROR_INVALID_ASN1_OBJECT; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 92e54a27..90669e43 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -76,7 +76,7 @@ void parse_tokeninfo(struct sc_pkcs15_card *card, const u8 * buf, int buflen) { NULL } }; - buf = sc_asn1_verify_tag(buf, buflen, 0x30, &buflen); /* SEQUENCE */ + buf = sc_asn1_verify_tag(card->card->ctx, buf, buflen, SC_ASN1_CONS | ASN1_SEQUENCE, &buflen); if (buf == NULL) { error(card->card->ctx, "invalid EF(TokenInfo)\n"); goto err; @@ -134,7 +134,7 @@ static int parse_dir(const u8 * buf, int buflen, struct sc_pkcs15_card *card) { NULL } }; - buf = sc_asn1_verify_tag(buf, buflen, 0x61, &buflen); + buf = sc_asn1_verify_tag(card->card->ctx, buf, buflen, SC_ASN1_APP | 1 | SC_ASN1_CONS, &buflen); if (buf == NULL) { error(card->card->ctx, "No [APPLICATION 1] tag in EF(DIR)\n"); return -1; diff --git a/src/libopensc/sc-asn1.h b/src/libopensc/sc-asn1.h index 4693bb99..8456eae7 100644 --- a/src/libopensc/sc-asn1.h +++ b/src/libopensc/sc-asn1.h @@ -30,7 +30,7 @@ struct sc_asn1_struct { unsigned int tag; unsigned int flags; void *parm; - int *len; + void *arg; }; struct sc_pkcs15_object { @@ -47,9 +47,12 @@ int sc_asn1_parse(struct sc_context *ctx, struct sc_asn1_struct *asn1, int sc_asn1_parse_choice(struct sc_context *ctx, struct sc_asn1_struct *asn1, const u8 *in, int len, const u8 **newp, int *left); -const u8 *sc_asn1_find_tag(const u8 * buf, int buflen, int tag, int *taglen); -const u8 *sc_asn1_verify_tag(const u8 * buf, int buflen, int tag, int *taglen); -const u8 *sc_asn1_skip_tag(const u8 ** buf, int *buflen, int tag, int *taglen); +const u8 *sc_asn1_find_tag(struct sc_context *ctx, const u8 * buf, + size_t buflen, unsigned int tag, size_t *taglen); +const u8 *sc_asn1_verify_tag(struct sc_context *ctx, const u8 * buf, + size_t buflen, unsigned int tag, size_t *taglen); +const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf, + size_t *buflen, unsigned int tag, size_t *taglen); /* DER encoding */ @@ -82,10 +85,12 @@ int sc_asn1_decode_object_id(const u8 * inbuf, int inlen, #define SC_ASN1_PRESENT 0x00000001 #define SC_ASN1_OPTIONAL 0x00000002 +#define SC_ASN1_ALLOC 0x00000004 #define SC_ASN1_BOOLEAN 1 #define SC_ASN1_INTEGER 2 #define SC_ASN1_BIT_STRING 3 +#define SC_ASN1_BIT_STRING_NI 128 #define SC_ASN1_OCTET_STRING 4 #define SC_ASN1_NULL 5 #define SC_ASN1_OBJECT 6 @@ -98,14 +103,17 @@ int sc_asn1_decode_object_id(const u8 * inbuf, int inlen, #define SC_ASN1_GENERALIZEDTIME 24 /* internal structures */ -#define SC_ASN1_STRUCT 128 -#define SC_ASN1_CHOICE 129 +#define SC_ASN1_STRUCT 129 +#define SC_ASN1_CHOICE 130 /* 'complex' structures */ #define SC_ASN1_PATH 256 #define SC_ASN1_PKCS15_ID 257 #define SC_ASN1_PKCS15_OBJECT 258 +/* use callback function */ +#define SC_ASN1_CALLBACK 384 + #define ASN1_TAG_CLASS 0xC0 #define ASN1_TAG_UNIVERSAL 0x00 #define ASN1_TAG_APPLICATION 0x40