- 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:
parent
da88fb7d62
commit
3e96a893ec
2
NEWS
2
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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue