- 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
This commit is contained in:
jey 2001-12-29 19:03:46 +00:00
parent da88fb7d62
commit 3e96a893ec
7 changed files with 184 additions and 139 deletions

2
NEWS
View File

@ -1,6 +1,6 @@
NEWS for OpenSC -- History of user visible changes 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 * Finished migrating to Autotools
* Rewritten ASN.1 decoder (should work better on all PKCS #15 cards) * Rewritten ASN.1 decoder (should work better on all PKCS #15 cards)
* Abstracted card handling, so adding support for new cards is a whiz, * Abstracted card handling, so adding support for new cards is a whiz,

View File

@ -248,9 +248,11 @@ void sc_asn1_print_tags(const u8 * buf, int buflen)
print_tags_recursive(buf, buf, buflen, 0); 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; const u8 *p = buf;
*taglen_in = 0; *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; *taglen_in = taglen;
return p; return p;
} }
if ((cla | tag) == 0xF0) { /* skip 0xF0 foobar tags */
fprintf(stderr, "Foobar tag skipped\n");
taglen = 0;
}
left -= taglen; left -= taglen;
p += taglen; p += taglen;
} }
return NULL; 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; 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;
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;
if (read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != 1) if (read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != 1)
return NULL; return NULL;
@ -340,9 +320,10 @@ static const u8 *sc_asn1_skip_tag2(struct sc_context *ctx, const u8 ** buf, int
return p; 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, 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, 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; 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; int r = 0;
if (ctx->debug >= 3) { 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) 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;
case SC_ASN1_BIT_STRING_NI:
case SC_ASN1_BIT_STRING: case SC_ASN1_BIT_STRING:
if (parm != NULL && len != NULL) { if (parm != NULL) {
r = sc_asn1_decode_bit_string(obj, objlen, (u8 *) parm, *len); 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) { if (r >= 0) {
*len = r; *len = r;
r = 0; r = 0;
@ -575,6 +572,16 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
if (parm != NULL) { if (parm != NULL) {
int c; int c;
assert(len != NULL); assert(len != NULL);
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; c = objlen > *len ? *len : objlen;
memcpy(parm, obj, c); memcpy(parm, obj, c);
@ -588,6 +595,16 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
case SC_ASN1_UTF8STRING: case SC_ASN1_UTF8STRING:
if (parm != NULL) { if (parm != NULL) {
assert(len != 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); r = sc_asn1_decode_utf8string(obj, objlen, parm, len);
} }
break; break;
@ -608,6 +625,10 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
if (entry->parm != NULL) if (entry->parm != NULL)
r = asn1_parse_p15_object(ctx, obj, objlen, (struct sc_pkcs15_object *) parm, depth); r = asn1_parse_p15_object(ctx, obj, objlen, (struct sc_pkcs15_object *) parm, depth);
break; break;
case SC_ASN1_CALLBACK:
if (entry->parm != NULL)
r = callback_func(ctx, entry->arg, obj, objlen, depth);
break;
default: default:
error(ctx, "invalid ASN.1 type: %d\n", entry->type); error(ctx, "invalid ASN.1 type: %d\n", entry->type);
assert(0); 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++) { for (idx = 0; asn1[idx].name != NULL; idx++) {
entry = &asn1[idx]; entry = &asn1[idx];
r = 0; 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 (obj == NULL) {
if (choice) if (choice)
continue; continue;

View File

@ -30,7 +30,7 @@ struct sc_asn1_struct {
unsigned int tag; unsigned int tag;
unsigned int flags; unsigned int flags;
void *parm; void *parm;
int *len; void *arg;
}; };
struct sc_pkcs15_object { 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, 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 *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_find_tag(struct sc_context *ctx, const u8 * buf,
const u8 *sc_asn1_verify_tag(const u8 * buf, int buflen, int tag, int *taglen); size_t buflen, unsigned int tag, size_t *taglen);
const u8 *sc_asn1_skip_tag(const u8 ** buf, int *buflen, int tag, int *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 */ /* 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_PRESENT 0x00000001
#define SC_ASN1_OPTIONAL 0x00000002 #define SC_ASN1_OPTIONAL 0x00000002
#define SC_ASN1_ALLOC 0x00000004
#define SC_ASN1_BOOLEAN 1 #define SC_ASN1_BOOLEAN 1
#define SC_ASN1_INTEGER 2 #define SC_ASN1_INTEGER 2
#define SC_ASN1_BIT_STRING 3 #define SC_ASN1_BIT_STRING 3
#define SC_ASN1_BIT_STRING_NI 128
#define SC_ASN1_OCTET_STRING 4 #define SC_ASN1_OCTET_STRING 4
#define SC_ASN1_NULL 5 #define SC_ASN1_NULL 5
#define SC_ASN1_OBJECT 6 #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 #define SC_ASN1_GENERALIZEDTIME 24
/* internal structures */ /* internal structures */
#define SC_ASN1_STRUCT 128 #define SC_ASN1_STRUCT 129
#define SC_ASN1_CHOICE 129 #define SC_ASN1_CHOICE 130
/* 'complex' structures */ /* 'complex' structures */
#define SC_ASN1_PATH 256 #define SC_ASN1_PATH 256
#define SC_ASN1_PKCS15_ID 257 #define SC_ASN1_PKCS15_ID 257
#define SC_ASN1_PKCS15_OBJECT 258 #define SC_ASN1_PKCS15_OBJECT 258
/* use callback function */
#define SC_ASN1_CALLBACK 384
#define ASN1_TAG_CLASS 0xC0 #define ASN1_TAG_CLASS 0xC0
#define ASN1_TAG_UNIVERSAL 0x00 #define ASN1_TAG_UNIVERSAL 0x00
#define ASN1_TAG_APPLICATION 0x40 #define ASN1_TAG_APPLICATION 0x40

View File

@ -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, 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; const u8 *tag = NULL, *p = buf;
if (ctx->debug >= 3) if (ctx->debug >= 3)
debug(ctx, "processing FCI bytes\n"); 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) { if (tag != NULL && taglen == 2) {
file->id = (tag[0] << 8) | tag[1]; file->id = (tag[0] << 8) | tag[1];
if (ctx->debug >= 3) if (ctx->debug >= 3)
debug(ctx, " file identifier: 0x%02X%02X\n", tag[0], debug(ctx, " file identifier: 0x%02X%02X\n", tag[0],
tag[1]); 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) { if (tag != NULL && taglen >= 2) {
int bytes = (tag[0] << 8) + tag[1]; int bytes = (tag[0] << 8) + tag[1];
if (ctx->debug >= 3) if (ctx->debug >= 3)
debug(ctx, " bytes in file: %d\n", bytes); debug(ctx, " bytes in file: %d\n", bytes);
file->size = 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 (tag != NULL) {
if (taglen > 0) { if (taglen > 0) {
unsigned char byte = tag[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) { if (tag != NULL && taglen > 0 && taglen <= 16) {
char name[17]; char name[17];
int i; int i;
@ -178,18 +178,18 @@ static void process_fci(struct sc_context *ctx, struct sc_file *file,
if (ctx->debug >= 3) if (ctx->debug >= 3)
debug(ctx, "File name: %s\n", name); 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) { if (tag != NULL && taglen && taglen <= SC_MAX_PROP_ATTR_SIZE) {
memcpy(file->prop_attr, tag, taglen); memcpy(file->prop_attr, tag, taglen);
file->prop_attr_len = taglen; file->prop_attr_len = taglen;
} else } else
file->prop_attr_len = 0; 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) { if (tag != NULL && taglen && taglen <= SC_MAX_PROP_ATTR_SIZE) {
memcpy(file->prop_attr, tag, taglen); memcpy(file->prop_attr, tag, taglen);
file->prop_attr_len = 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) if (tag != NULL && taglen && taglen <= SC_MAX_SEC_ATTR_SIZE)
parse_sec_attr(file, tag, taglen); parse_sec_attr(file, tag, taglen);
else else

View File

@ -31,98 +31,106 @@
#undef CACHE_CERTS #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; struct sc_asn1_struct asn1_rsa_pubkey[] = {
int taglen; { "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;
buf = sc_asn1_verify_tag(buf, buflen, 0x30, &buflen); obj = sc_asn1_verify_tag(ctx, key->data, key->data_len, ASN1_SEQUENCE | SC_ASN1_CONS,
if (buf == NULL) &objlen);
return -1; if (obj == NULL) {
error(ctx, "RSA public key not found\n");
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);
return SC_ERROR_INVALID_ASN1_OBJECT; 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; 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; struct asn1_algorithm_id *alg_id = (struct asn1_algorithm_id *) arg;
u8 *tmpbuf; struct sc_asn1_struct asn1_alg_id[] = {
int taglen, left, r; { "algorithm", SC_ASN1_OBJECT, ASN1_OBJECT, 0, &alg_id->id },
{ "parameters", SC_ASN1_STRUCT, 0, SC_ASN1_OPTIONAL, NULL },
{ NULL }
};
int r;
r = sc_asn1_parse(ctx, asn1_alg_id, obj, objlen, NULL, NULL);
SC_TEST_RET(ctx, r, "ASN.1 parsing failed");
return 0;
}
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 sc_pkcs15_rsa_pubkey *key = &cert->key;
const u8 *buf0 = buf; 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;
buf = sc_asn1_verify_tag(buf, buflen, 0x30, &buflen); /* SEQUENCE */ obj = sc_asn1_verify_tag(ctx, buf, buflen, ASN1_SEQUENCE | SC_ASN1_CONS,
if (buf == NULL) /* Certificate */ &objlen);
if (obj == NULL) {
error(ctx, "X.509 certificate not found\n");
return SC_ERROR_INVALID_ASN1_OBJECT; return SC_ERROR_INVALID_ASN1_OBJECT;
cert->data_len = (buf - buf0) + buflen; }
p = sc_asn1_skip_tag(&buf, &buflen, 0x30, &left); /* SEQUENCE */ cert->data_len = objlen + (obj - buf);
if (p == NULL) /* tbsCertificate */ r = sc_asn1_parse(ctx, asn1_cert, obj, objlen, NULL, NULL);
return SC_ERROR_INVALID_ASN1_OBJECT; SC_TEST_RET(ctx, r, "ASN.1 parsing failed");
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++; cert->version++;
} pklen >>= 3; /* convert number of bits to bytes */
} key->data = pk;
tag = sc_asn1_skip_tag(&p, &left, 0x02, &taglen); /* INTEGER */ key->data_len = pklen;
if (tag == NULL) /* FIXME: ignore the object id for now, and presume it's RSA */
return SC_ERROR_INVALID_ASN1_OBJECT; r = parse_rsa_pubkey(ctx, key);
sc_asn1_decode_integer(tag, taglen, (int *) &cert->serial);
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);
return SC_ERROR_INVALID_ASN1_OBJECT;
}
r >>= 3;
key->data = tmpbuf;
key->data_len = taglen-1;
r = parse_rsa_pubkey(tmpbuf, r, key);
if (r) { if (r) {
free(tmpbuf); free(key->data);
return SC_ERROR_INVALID_ASN1_OBJECT; return SC_ERROR_INVALID_ASN1_OBJECT;
} }
return 0; return 0;
} }
@ -259,7 +267,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
} }
memset(cert, 0, sizeof(struct sc_pkcs15_cert)); 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(data);
free(cert); free(cert);
return SC_ERROR_INVALID_ASN1_OBJECT; return SC_ERROR_INVALID_ASN1_OBJECT;

View File

@ -76,7 +76,7 @@ void parse_tokeninfo(struct sc_pkcs15_card *card, const u8 * buf, int buflen)
{ NULL } { 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) { if (buf == NULL) {
error(card->card->ctx, "invalid EF(TokenInfo)\n"); error(card->card->ctx, "invalid EF(TokenInfo)\n");
goto err; goto err;
@ -134,7 +134,7 @@ static int parse_dir(const u8 * buf, int buflen, struct sc_pkcs15_card *card)
{ NULL } { 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) { if (buf == NULL) {
error(card->card->ctx, "No [APPLICATION 1] tag in EF(DIR)\n"); error(card->card->ctx, "No [APPLICATION 1] tag in EF(DIR)\n");
return -1; return -1;

View File

@ -30,7 +30,7 @@ struct sc_asn1_struct {
unsigned int tag; unsigned int tag;
unsigned int flags; unsigned int flags;
void *parm; void *parm;
int *len; void *arg;
}; };
struct sc_pkcs15_object { 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, 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 *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_find_tag(struct sc_context *ctx, const u8 * buf,
const u8 *sc_asn1_verify_tag(const u8 * buf, int buflen, int tag, int *taglen); size_t buflen, unsigned int tag, size_t *taglen);
const u8 *sc_asn1_skip_tag(const u8 ** buf, int *buflen, int tag, int *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 */ /* 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_PRESENT 0x00000001
#define SC_ASN1_OPTIONAL 0x00000002 #define SC_ASN1_OPTIONAL 0x00000002
#define SC_ASN1_ALLOC 0x00000004
#define SC_ASN1_BOOLEAN 1 #define SC_ASN1_BOOLEAN 1
#define SC_ASN1_INTEGER 2 #define SC_ASN1_INTEGER 2
#define SC_ASN1_BIT_STRING 3 #define SC_ASN1_BIT_STRING 3
#define SC_ASN1_BIT_STRING_NI 128
#define SC_ASN1_OCTET_STRING 4 #define SC_ASN1_OCTET_STRING 4
#define SC_ASN1_NULL 5 #define SC_ASN1_NULL 5
#define SC_ASN1_OBJECT 6 #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 #define SC_ASN1_GENERALIZEDTIME 24
/* internal structures */ /* internal structures */
#define SC_ASN1_STRUCT 128 #define SC_ASN1_STRUCT 129
#define SC_ASN1_CHOICE 129 #define SC_ASN1_CHOICE 130
/* 'complex' structures */ /* 'complex' structures */
#define SC_ASN1_PATH 256 #define SC_ASN1_PATH 256
#define SC_ASN1_PKCS15_ID 257 #define SC_ASN1_PKCS15_ID 257
#define SC_ASN1_PKCS15_OBJECT 258 #define SC_ASN1_PKCS15_OBJECT 258
/* use callback function */
#define SC_ASN1_CALLBACK 384
#define ASN1_TAG_CLASS 0xC0 #define ASN1_TAG_CLASS 0xC0
#define ASN1_TAG_UNIVERSAL 0x00 #define ASN1_TAG_UNIVERSAL 0x00
#define ASN1_TAG_APPLICATION 0x40 #define ASN1_TAG_APPLICATION 0x40