- added preliminary ASN.1 encoding support
- modified ASN.1 decoding to make it easier to port decoder structures to the encoder - fixed a recently introduced bug in card driver handling - opensc-explorer will now allow only DF's to be cd'd into git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@156 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
26906e7843
commit
9dc7054919
|
@ -8,7 +8,7 @@ libopensc_la_SOURCES = asn1.c base64.c defaults.c \
|
|||
pkcs15.c pkcs15-cert.c pkcs15-pin.c \
|
||||
pkcs15-prkey.c pkcs15-defaults.c \
|
||||
pkcs15-sec.c \
|
||||
card-setec.c card-multiflex.c \
|
||||
card-setec.c card-flex.c \
|
||||
card-emv.c card-default.c
|
||||
libopensc_la_LDFLAGS = -version-info 0:4:0
|
||||
libopensc_la_LIBADD = @LIBPCSC@
|
||||
|
|
|
@ -28,9 +28,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
|
||||
static int asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *len_left,
|
||||
int choice, int depth);
|
||||
static int asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *len_left,
|
||||
int choice, int depth);
|
||||
static int asn1_encode(struct sc_context *ctx, const struct sc_asn1_entry *asn1,
|
||||
u8 **ptr, size_t *size, int depth);
|
||||
|
||||
const char *tag2str(int tag)
|
||||
{
|
||||
|
@ -94,6 +96,26 @@ static int read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
|
|||
return -1;
|
||||
}
|
||||
|
||||
void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg,
|
||||
int set_present)
|
||||
{
|
||||
entry->parm = parm;
|
||||
entry->arg = arg;
|
||||
if (set_present)
|
||||
entry->flags |= SC_ASN1_PRESENT;
|
||||
}
|
||||
|
||||
void sc_copy_asn1_entry(const struct sc_asn1_entry *src,
|
||||
struct sc_asn1_entry *dest)
|
||||
{
|
||||
do {
|
||||
*dest = *src;
|
||||
dest++;
|
||||
src++;
|
||||
} while (src->name != NULL);
|
||||
dest->name = NULL;
|
||||
}
|
||||
|
||||
static void sc_asn1_print_octet_string(const u8 * buf, size_t buflen)
|
||||
{
|
||||
int i;
|
||||
|
@ -381,6 +403,12 @@ int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
|||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0);
|
||||
}
|
||||
|
||||
static int encode_bit_string(const u8 * inbuf, size_t inlen, u8 **outbuf,
|
||||
size_t *outlen, int invert)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out)
|
||||
{
|
||||
int i, a = 0;
|
||||
|
@ -395,6 +423,23 @@ int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_encode_integer(int in, u8 ** obj, size_t * objsize)
|
||||
{
|
||||
int i = sizeof(in) * 8;
|
||||
u8 *p;
|
||||
|
||||
*obj = p = malloc(sizeof(in));
|
||||
if (*obj == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*objsize = sizeof(in);
|
||||
do {
|
||||
i -= 8;
|
||||
*p++ = (in >> i) & 0xFF;
|
||||
} while (i > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
||||
struct sc_object_id *id)
|
||||
{
|
||||
|
@ -430,7 +475,38 @@ int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sc_asn1_decode_utf8string(const u8 * inbuf, size_t inlen,
|
||||
int sc_asn1_encode_object_id(const struct sc_object_id *id, u8 **buf,
|
||||
size_t *buflen)
|
||||
{
|
||||
#if 0
|
||||
u8 buf[128], *p = buf;
|
||||
size_t count = 0
|
||||
int *valuep = id->value, i = 0;
|
||||
|
||||
for (i = 0; *valuep != -1 && i < SC_MAX_OBJECT_ID_OCTETS; i++) {
|
||||
int c = 0;
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (*valuep > 2)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
*p = *valuep * 40;
|
||||
break;
|
||||
case 1:
|
||||
if (*valuep > 39)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
*p++ += *valuep;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: CODEME */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
if (inlen+1 > *outlen)
|
||||
|
@ -463,52 +539,171 @@ int sc_asn1_put_tag(int tag, const u8 * data, int datalen, u8 * out, int outlen,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int asn1_write_element(struct sc_context *ctx, unsigned int tag, const u8 * data,
|
||||
size_t datalen, u8 ** out, size_t * outlen)
|
||||
{
|
||||
u8 t;
|
||||
u8 *buf, *p;
|
||||
int c = 0;
|
||||
|
||||
t = tag & 0x1F;
|
||||
if (t != (tag & SC_ASN1_TAG_MASK)) {
|
||||
error(ctx, "Long tags not supported\n");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
switch (tag & SC_ASN1_CLASS_MASK) {
|
||||
case SC_ASN1_UNI:
|
||||
break;
|
||||
case SC_ASN1_APP:
|
||||
t |= ASN1_TAG_APPLICATION;
|
||||
break;
|
||||
case SC_ASN1_CTX:
|
||||
t |= ASN1_TAG_CONTEXT;
|
||||
break;
|
||||
case SC_ASN1_PRV:
|
||||
t |= ASN1_TAG_PRIVATE;
|
||||
break;
|
||||
}
|
||||
if (tag & SC_ASN1_CONS)
|
||||
t |= ASN1_TAG_CONSTRUCTED;
|
||||
if (datalen > 127) {
|
||||
c = 1;
|
||||
while (datalen >> (c << 3))
|
||||
c++;
|
||||
}
|
||||
*outlen = 2 + c + datalen;
|
||||
buf = malloc(*outlen);
|
||||
if (buf == NULL)
|
||||
SC_FUNC_RETURN(ctx, 1, SC_ERROR_OUT_OF_MEMORY);
|
||||
*out = p = buf;
|
||||
*p++ = t;
|
||||
if (c) {
|
||||
*p++ = 0x80 | c;
|
||||
while (c--)
|
||||
*p++ = (datalen >> (c << 3)) & 0xFF;
|
||||
} else
|
||||
*p++ = datalen & 0x7F;
|
||||
memcpy(p, data, datalen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_path[3] = {
|
||||
{ "path", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, NULL },
|
||||
{ "index", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int asn1_decode_path(struct sc_context *ctx, const u8 *in, size_t len,
|
||||
struct sc_path *path, int depth)
|
||||
{
|
||||
int idx, r;
|
||||
struct sc_asn1_struct asn1_path[] = {
|
||||
{ "path", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, &path->value, &path->len },
|
||||
{ "index", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, &idx },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_entry asn1_path[3];
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_path, asn1_path);
|
||||
sc_format_asn1_entry(asn1_path + 0, &path->value, &path->len, 0);
|
||||
sc_format_asn1_entry(asn1_path + 1, &idx, NULL, 0);
|
||||
path->len = SC_MAX_PATH_SIZE;
|
||||
r = asn1_decode(ctx, asn1_path, in, len, NULL, NULL, 0, depth + 1);
|
||||
if (r)
|
||||
return r;
|
||||
path->type = SC_PATH_TYPE_PATH;
|
||||
|
||||
if (asn1_path[1].flags & SC_ASN1_PRESENT)
|
||||
path->index = idx;
|
||||
else
|
||||
path->index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_encode_path(struct sc_context *ctx, const struct sc_path *path,
|
||||
u8 **buf, size_t *bufsize, int depth)
|
||||
{
|
||||
int r;
|
||||
struct sc_asn1_entry asn1_path[3];
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_path, asn1_path);
|
||||
sc_format_asn1_entry(asn1_path + 0, (void *) &path->value, (void *) &path->len, 1);
|
||||
if (path->index)
|
||||
sc_format_asn1_entry(asn1_path + 1, (void *) &path->index, NULL, 1);
|
||||
r = asn1_encode(ctx, asn1_path, buf, bufsize, depth + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_com_obj_attr[6] = {
|
||||
{ "label", SC_ASN1_UTF8STRING, ASN1_UTF8STRING, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "flags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "authId", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "userConsent", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "accessControlRules", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_p15_obj[5] = {
|
||||
{ "commonObjectAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
|
||||
{ "classAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
|
||||
{ "subClassAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "typeAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in,
|
||||
size_t len, struct sc_pkcs15_object *obj,
|
||||
int depth)
|
||||
{
|
||||
int r;
|
||||
struct sc_pkcs15_common_obj_attr *com_attr = obj->com_attr;
|
||||
struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5];
|
||||
size_t flags_len = sizeof(com_attr->flags);
|
||||
size_t label_len = sizeof(com_attr->label);
|
||||
struct sc_asn1_struct asn1_com_obj_attr[] = {
|
||||
{ "label", SC_ASN1_UTF8STRING, ASN1_UTF8STRING, SC_ASN1_OPTIONAL, com_attr->label, &label_len },
|
||||
{ "flags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, &com_attr->flags, &flags_len },
|
||||
{ "authId", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, SC_ASN1_OPTIONAL, &com_attr->auth_id },
|
||||
{ "userConsent", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, &com_attr->user_consent },
|
||||
{ "accessControlRules", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_p15_obj[] = {
|
||||
{ "commonObjectAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_com_obj_attr },
|
||||
{ "classAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, obj->asn1_class_attr },
|
||||
{ "subClassAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, obj->asn1_subclass_attr },
|
||||
{ "typeAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, obj->asn1_type_attr },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr);
|
||||
sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj);
|
||||
sc_format_asn1_entry(asn1_c_attr + 0, com_attr->label, &label_len, 0);
|
||||
sc_format_asn1_entry(asn1_c_attr + 1, &com_attr->flags, &flags_len, 0);
|
||||
sc_format_asn1_entry(asn1_c_attr + 2, &com_attr->auth_id, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_c_attr + 3, &com_attr->user_consent, NULL, 0);
|
||||
/* FIXME: encode accessControlRules */
|
||||
sc_format_asn1_entry(asn1_c_attr + 4, NULL, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 1, obj->asn1_class_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 2, obj->asn1_subclass_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 3, obj->asn1_type_attr, NULL, 0);
|
||||
|
||||
r = asn1_decode(ctx, asn1_p15_obj, in, len, NULL, NULL, 0, depth + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entry,
|
||||
static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_pkcs15_object *obj,
|
||||
u8 **buf, size_t *bufsize, int depth)
|
||||
{
|
||||
int r;
|
||||
const struct sc_pkcs15_common_obj_attr *com_attr = obj->com_attr;
|
||||
struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5];
|
||||
size_t flags_len = sizeof(com_attr->flags);
|
||||
size_t label_len = strlen(com_attr->label);
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr);
|
||||
sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj);
|
||||
if (label_len != 0)
|
||||
sc_format_asn1_entry(asn1_c_attr + 0, (void *) com_attr->label, &label_len, 1);
|
||||
if (com_attr->flags)
|
||||
sc_format_asn1_entry(asn1_c_attr + 1, (void *) &com_attr->flags, &flags_len, 1);
|
||||
if (com_attr->auth_id.len)
|
||||
sc_format_asn1_entry(asn1_c_attr + 2, (void *) &com_attr->auth_id, NULL, 1);
|
||||
if (com_attr->user_consent)
|
||||
sc_format_asn1_entry(asn1_c_attr + 3, (void *) &com_attr->user_consent, NULL, 1);
|
||||
/* FIXME: decode accessControlRules */
|
||||
sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 1, obj->asn1_class_attr, NULL, 1);
|
||||
if (obj->asn1_subclass_attr != NULL)
|
||||
sc_format_asn1_entry(asn1_p15_obj + 2, obj->asn1_subclass_attr, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_p15_obj + 3, obj->asn1_type_attr, NULL, 1);
|
||||
|
||||
r = asn1_encode(ctx, asn1_p15_obj, buf, bufsize, depth + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry,
|
||||
const u8 *obj, size_t objlen, int depth)
|
||||
{
|
||||
void *parm = entry->parm;
|
||||
|
@ -534,7 +729,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
|
|||
switch (entry->type) {
|
||||
case SC_ASN1_STRUCT:
|
||||
if (parm != NULL)
|
||||
r = asn1_decode(ctx, (struct sc_asn1_struct *) parm, obj,
|
||||
r = asn1_decode(ctx, (struct sc_asn1_entry *) parm, obj,
|
||||
objlen, NULL, NULL, 0, depth + 1);
|
||||
break;
|
||||
case SC_ASN1_BOOLEAN:
|
||||
|
@ -651,13 +846,13 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_struct *entr
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
static int asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *len_left,
|
||||
int choice, int depth)
|
||||
{
|
||||
int r, idx = 0;
|
||||
const u8 *p = in, *obj;
|
||||
struct sc_asn1_struct *entry = asn1;
|
||||
struct sc_asn1_entry *entry = asn1;
|
||||
size_t left = len, objlen;
|
||||
|
||||
if (ctx->debug >= 3)
|
||||
|
@ -710,48 +905,163 @@ static int asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
|||
SC_FUNC_RETURN(ctx, 3, 0);
|
||||
}
|
||||
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *len_left)
|
||||
{
|
||||
return asn1_decode(ctx, asn1, in, len, newp, len_left, 0, 0);
|
||||
}
|
||||
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *len_left)
|
||||
{
|
||||
return asn1_decode(ctx, asn1, in, len, newp, len_left, 1, 0);
|
||||
}
|
||||
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_struct *asn1,
|
||||
u8 *buf, size_t bufleft, size_t *objsize_out)
|
||||
static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry *entry,
|
||||
u8 **obj, size_t *objlen, int depth)
|
||||
{
|
||||
void *parm = entry->parm;
|
||||
int (*callback_func)(struct sc_context *ctx, void *arg, u8 **obj,
|
||||
size_t *objlen, int depth) =
|
||||
(int (*)(struct sc_context *, void *, u8 **, size_t *, int)) parm;
|
||||
const size_t *len = (const size_t *) entry->arg;
|
||||
int r = 0;
|
||||
u8 * buf = NULL;
|
||||
size_t buflen = 0;
|
||||
|
||||
if (ctx->debug >= 3) {
|
||||
u8 line[128], *linep = line;
|
||||
int i;
|
||||
|
||||
line[0] = 0;
|
||||
for (i = 0; i < depth; i++) {
|
||||
strcpy((char *) linep, " ");
|
||||
linep += 2;
|
||||
}
|
||||
sprintf((char *) linep, "encoding '%s'\n", entry->name);
|
||||
debug(ctx, (char *) line);
|
||||
}
|
||||
|
||||
assert(parm != NULL);
|
||||
switch (entry->type) {
|
||||
case SC_ASN1_STRUCT:
|
||||
r = asn1_encode(ctx, (const struct sc_asn1_entry *) parm, &buf,
|
||||
&buflen, depth + 1);
|
||||
break;
|
||||
case SC_ASN1_BOOLEAN:
|
||||
buf = malloc(1);
|
||||
if (buf == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
buf[0] = *((u8 *) parm) ? 0xFF : 0;
|
||||
buflen = 1;
|
||||
break;
|
||||
case SC_ASN1_INTEGER:
|
||||
case SC_ASN1_ENUMERATED:
|
||||
r = asn1_encode_integer(*((int *) entry->parm), &buf, &buflen);
|
||||
break;
|
||||
case SC_ASN1_BIT_STRING_NI:
|
||||
case SC_ASN1_BIT_STRING:
|
||||
assert(len != NULL);
|
||||
if (entry->type == SC_ASN1_BIT_STRING_NI)
|
||||
r = encode_bit_string((const u8 *) parm, *len, &buf, &buflen, 1);
|
||||
else
|
||||
r = encode_bit_string((const u8 *) parm, *len, &buf, &buflen, 0);
|
||||
break;
|
||||
case SC_ASN1_OCTET_STRING:
|
||||
case SC_ASN1_UTF8STRING:
|
||||
assert(len != NULL);
|
||||
buf = malloc(*len);
|
||||
if (buf == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
buflen = *len;
|
||||
memcpy(buf, parm, buflen);
|
||||
break;
|
||||
#if 0
|
||||
case SC_ASN1_OBJECT:
|
||||
if (parm != NULL)
|
||||
r = sc_asn1_decode_object_id(obj, objlen, (struct sc_object_id *) parm);
|
||||
break;
|
||||
#endif
|
||||
case SC_ASN1_PATH:
|
||||
r = asn1_encode_path(ctx, (const struct sc_path *) parm, &buf, &buflen, depth);
|
||||
break;
|
||||
case SC_ASN1_PKCS15_ID:
|
||||
if (entry->parm != NULL) {
|
||||
const struct sc_pkcs15_id *id = parm;
|
||||
|
||||
buf = malloc(id->len);
|
||||
if (buf == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
memcpy(buf, id->value, id->len);
|
||||
buflen = id->len;
|
||||
}
|
||||
break;
|
||||
case SC_ASN1_PKCS15_OBJECT:
|
||||
r = asn1_encode_p15_object(ctx, (const struct sc_pkcs15_object *) parm, &buf, &buflen, depth);
|
||||
break;
|
||||
case SC_ASN1_CALLBACK:
|
||||
r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
|
||||
break;
|
||||
default:
|
||||
error(ctx, "invalid ASN.1 type: %d\n", entry->type);
|
||||
assert(0);
|
||||
}
|
||||
if (r) {
|
||||
error(ctx, "decoding of ASN.1 object '%s' failed: %s\n", entry->name,
|
||||
sc_strerror(r));
|
||||
if (buf)
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
r = asn1_write_element(ctx, entry->tag, buf, buflen, obj, objlen);
|
||||
free(buf);
|
||||
if (r) {
|
||||
error(ctx, "error writing ASN.1 tag and length: %s\n", sc_strerror(r));
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int asn1_encode(struct sc_context *ctx, const struct sc_asn1_entry *asn1,
|
||||
u8 **ptr, size_t *size, int depth)
|
||||
{
|
||||
#if 0
|
||||
int r, idx = 0;
|
||||
const u8 *p = buf;
|
||||
const struct sc_asn1_struct *entry = asn1;
|
||||
u8 *obj, *buf = NULL;
|
||||
const struct sc_asn1_entry *entry = asn1;
|
||||
size_t total = 0, objsize;
|
||||
|
||||
if (ctx->debug >= 3)
|
||||
debug(ctx, "called, depth %d\n", depth);
|
||||
if (left < 2)
|
||||
return SC_ERROR_ASN1_END_OF_CONTENTS;
|
||||
for (idx = 0; asn1[idx].name != NULL; idx++) {
|
||||
entry = &asn1[idx];
|
||||
|
||||
if (!(entry->flags & SC_ASN1_PRESENT))
|
||||
continue;
|
||||
r = asn1_encode_entry(ctx, entry, p, bufleft, &objsize);
|
||||
if (r)
|
||||
r = asn1_encode_entry(ctx, entry, &obj, &objsize, depth);
|
||||
if (r) {
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
buf = realloc(buf, total + objsize);
|
||||
memcpy(buf + total, obj, objsize);
|
||||
free(obj);
|
||||
total += objsize;
|
||||
p += objsize;
|
||||
assert(bufleft >= objsize);
|
||||
bufleft -= objsize;
|
||||
}
|
||||
if (objsize_out != NULL)
|
||||
*objsize_out = total;
|
||||
*ptr = buf;
|
||||
*size = total;
|
||||
SC_FUNC_RETURN(ctx, 3, 0);
|
||||
#else
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_entry *asn1,
|
||||
u8 **ptr, size_t *size)
|
||||
{
|
||||
return asn1_encode(ctx, asn1, ptr, size, 0);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "opensc.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
|
||||
struct sc_asn1_struct {
|
||||
struct sc_asn1_entry {
|
||||
const char *name;
|
||||
unsigned int type;
|
||||
unsigned int tag;
|
||||
|
@ -35,19 +35,24 @@ struct sc_asn1_struct {
|
|||
|
||||
struct sc_pkcs15_object {
|
||||
struct sc_pkcs15_common_obj_attr *com_attr;
|
||||
struct sc_asn1_struct *asn1_class_attr;
|
||||
struct sc_asn1_struct *asn1_subclass_attr;
|
||||
struct sc_asn1_struct *asn1_type_attr;
|
||||
struct sc_asn1_entry *asn1_class_attr;
|
||||
struct sc_asn1_entry *asn1_subclass_attr;
|
||||
struct sc_asn1_entry *asn1_type_attr;
|
||||
};
|
||||
|
||||
/* Utility functions */
|
||||
void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg,
|
||||
int set_present);
|
||||
void sc_copy_asn1_entry(const struct sc_asn1_entry *src,
|
||||
struct sc_asn1_entry *dest);
|
||||
|
||||
/* DER tag and length parsing */
|
||||
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *left);
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *left);
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_struct *asn1,
|
||||
u8 *buf, size_t bufsize, size_t *obj_size);
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_entry *asn1,
|
||||
u8 **buf, size_t *bufsize);
|
||||
|
||||
const u8 *sc_asn1_find_tag(struct sc_context *ctx, const u8 * buf,
|
||||
size_t buflen, unsigned int tag, size_t *taglen);
|
||||
|
|
|
@ -95,7 +95,7 @@ static int autodetect_class(struct sc_card *card)
|
|||
const struct sc_card_driver *drv;
|
||||
if (card->ctx->debug >= 2)
|
||||
debug(card->ctx, "SELECT FILE seems to return Schlumberger 'flex stuff\n");
|
||||
drv = sc_get_mflex_driver();
|
||||
drv = sc_get_flex_driver();
|
||||
card->ops->select_file = drv->ops->select_file;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* card-multiflex.c: Support for Multiflex cards by Schlumberger
|
||||
* card-flex.c: Support for Schlumberger cards
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
@ -21,33 +21,33 @@
|
|||
#include "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
|
||||
static const char *mflex_atrs[] = {
|
||||
static const char *flex_atrs[] = {
|
||||
"3B:95:94:40:FF:63:01:01:02:01", /* CryptoFlex 16k */
|
||||
"3B:19:14:55:90:01:02:02:00:05:04:B0",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct sc_card_operations mflex_ops;
|
||||
static const struct sc_card_driver mflex_drv = {
|
||||
static struct sc_card_operations flex_ops;
|
||||
static const struct sc_card_driver flex_drv = {
|
||||
NULL,
|
||||
"Multiflex/Schlumberger",
|
||||
"mflex",
|
||||
&mflex_ops
|
||||
"Schlumberger Multiflex/CryptoFlex",
|
||||
"slb",
|
||||
&flex_ops
|
||||
};
|
||||
|
||||
static int mflex_finish(struct sc_card *card)
|
||||
static int flex_finish(struct sc_card *card)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mflex_match_card(struct sc_card *card)
|
||||
static int flex_match_card(struct sc_card *card)
|
||||
{
|
||||
int i, match = -1;
|
||||
|
||||
for (i = 0; mflex_atrs[i] != NULL; i++) {
|
||||
for (i = 0; flex_atrs[i] != NULL; i++) {
|
||||
u8 defatr[SC_MAX_ATR_SIZE];
|
||||
size_t len = sizeof(defatr);
|
||||
const char *atrp = mflex_atrs[i];
|
||||
const char *atrp = flex_atrs[i];
|
||||
|
||||
if (sc_hex_to_bin(atrp, defatr, &len))
|
||||
continue;
|
||||
|
@ -64,7 +64,7 @@ static int mflex_match_card(struct sc_card *card)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int mflex_init(struct sc_card *card)
|
||||
static int flex_init(struct sc_card *card)
|
||||
{
|
||||
card->ops_data = NULL;
|
||||
card->cla = 0xC0;
|
||||
|
@ -160,7 +160,7 @@ static int parse_flex_sf_reply(struct sc_context *ctx, const u8 *buf, int buflen
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
static int flex_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
struct sc_file *file)
|
||||
{
|
||||
int r, i;
|
||||
|
@ -188,7 +188,7 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
if (memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
sc_format_path("I3F00", &tmppath);
|
||||
r = mflex_select_file(card, &tmppath, NULL);
|
||||
r = flex_select_file(card, &tmppath, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select Master File (MF)");
|
||||
|
@ -196,7 +196,7 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
while (pathlen > 2) {
|
||||
memcpy(tmppath.value, pathptr, 2);
|
||||
tmppath.len = 2;
|
||||
r = mflex_select_file(card, &tmppath, NULL);
|
||||
r = flex_select_file(card, &tmppath, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select DF");
|
||||
|
@ -251,7 +251,7 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
return parse_flex_sf_reply(card->ctx, apdu.resp, apdu.resplen, file);
|
||||
}
|
||||
|
||||
static int mflex_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||
static int flex_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||
{
|
||||
struct sc_apdu apdu;
|
||||
u8 rbuf[4];
|
||||
|
@ -288,18 +288,18 @@ static const struct sc_card_driver * sc_get_driver(void)
|
|||
{
|
||||
const struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
|
||||
mflex_ops = *iso_drv->ops;
|
||||
mflex_ops.match_card = mflex_match_card;
|
||||
mflex_ops.init = mflex_init;
|
||||
mflex_ops.finish = mflex_finish;
|
||||
mflex_ops.select_file = mflex_select_file;
|
||||
mflex_ops.list_files = mflex_list_files;
|
||||
flex_ops = *iso_drv->ops;
|
||||
flex_ops.match_card = flex_match_card;
|
||||
flex_ops.init = flex_init;
|
||||
flex_ops.finish = flex_finish;
|
||||
flex_ops.select_file = flex_select_file;
|
||||
flex_ops.list_files = flex_list_files;
|
||||
|
||||
return &mflex_drv;
|
||||
return &flex_drv;
|
||||
}
|
||||
|
||||
#if 1
|
||||
const struct sc_card_driver * sc_get_mflex_driver(void)
|
||||
const struct sc_card_driver * sc_get_flex_driver(void)
|
||||
{
|
||||
return sc_get_driver();
|
||||
}
|
|
@ -374,8 +374,8 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
memcpy(card->atr, rgReaderStates[0].rgbAtr, i);
|
||||
card->atr_len = i;
|
||||
|
||||
if (ctx->default_driver != NULL) {
|
||||
card->driver = ctx->default_driver;
|
||||
if (ctx->forced_driver != NULL) {
|
||||
card->driver = ctx->forced_driver;
|
||||
memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations));
|
||||
if (card->ops->init != NULL) {
|
||||
r = card->ops->init(card);
|
||||
|
|
|
@ -176,10 +176,14 @@ struct sc_pkcs15_defaults {
|
|||
int arg;
|
||||
};
|
||||
|
||||
/* Binds a card object to a PKCS#15 card object and initializes
|
||||
* a new PKCS#15 card object */
|
||||
/* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object
|
||||
* and initializes a new PKCS#15 card object. Will return
|
||||
* SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a
|
||||
* valid PKCS #15 file structure. */
|
||||
int sc_pkcs15_bind(struct sc_card *card,
|
||||
struct sc_pkcs15_card **pkcs15_card);
|
||||
/* sc_pkcs_unbind: Releases a PKCS #15 card object, and frees any
|
||||
* memory allocations done on the card object. */
|
||||
int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
|
||||
|
||||
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
||||
|
@ -205,6 +209,12 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert);
|
|||
int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *card,
|
||||
const struct sc_pkcs15_id *id,
|
||||
struct sc_pkcs15_cert_info **out);
|
||||
/* sc_pkcs15_create_cdf: Creates a new certificate DF on a card pointed
|
||||
* by <card>. Information about the file, such as the file ID, is read
|
||||
* from <file>. <certs> has to be NULL-terminated. */
|
||||
int sc_pkcs15_create_cdf(struct sc_pkcs15_card *card,
|
||||
struct sc_file *file,
|
||||
const struct sc_pkcs15_cert_info **certs);
|
||||
|
||||
void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey);
|
||||
int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card);
|
||||
|
|
|
@ -45,7 +45,7 @@ extern "C" {
|
|||
#define SC_ERROR_TRANSMIT_FAILED -1004
|
||||
#define SC_ERROR_FILE_NOT_FOUND -1005
|
||||
#define SC_ERROR_INVALID_ARGUMENTS -1006
|
||||
#define SC_ERROR_PKCS15_CARD_NOT_FOUND -1007
|
||||
#define SC_ERROR_PKCS15_APP_NOT_FOUND -1007
|
||||
#define SC_ERROR_REQUIRED_PARAMETER_NOT_FOUND -1008
|
||||
#define SC_ERROR_OUT_OF_MEMORY -1009
|
||||
#define SC_ERROR_NO_READERS_FOUND -1010
|
||||
|
@ -330,7 +330,7 @@ struct sc_context {
|
|||
|
||||
int use_std_output, use_cache;
|
||||
const struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS+1];
|
||||
const struct sc_card_driver *default_driver;
|
||||
const struct sc_card_driver *forced_driver;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
|
@ -359,7 +359,7 @@ void sc_format_apdu(struct sc_card *card, struct sc_apdu *apdu, int cse, int ins
|
|||
|
||||
int sc_establish_context(struct sc_context **ctx);
|
||||
int sc_destroy_context(struct sc_context *ctx);
|
||||
int sc_set_default_card_driver(struct sc_context *ctx, const char *short_name);
|
||||
int sc_set_card_driver(struct sc_context *ctx, const char *short_name);
|
||||
int sc_connect_card(struct sc_context *ctx,
|
||||
int reader, struct sc_card **card);
|
||||
int sc_disconnect_card(struct sc_card *card);
|
||||
|
@ -424,7 +424,7 @@ extern const char *sc_version;
|
|||
extern const struct sc_card_driver *sc_get_iso7816_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_emv_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_setec_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_mflex_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_flex_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_default_driver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
static int parse_rsa_pubkey(struct sc_context *ctx, struct sc_pkcs15_rsa_pubkey *key)
|
||||
{
|
||||
struct sc_asn1_struct asn1_rsa_pubkey[] = {
|
||||
struct sc_asn1_entry 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 }
|
||||
|
@ -62,7 +62,7 @@ static int parse_algorithm_id(struct sc_context *ctx, void *arg, const u8 *obj,
|
|||
size_t objlen, int depth)
|
||||
{
|
||||
struct asn1_algorithm_id *alg_id = (struct asn1_algorithm_id *) arg;
|
||||
struct sc_asn1_struct asn1_alg_id[] = {
|
||||
struct sc_asn1_entry asn1_alg_id[] = {
|
||||
{ "algorithm", SC_ASN1_OBJECT, ASN1_OBJECT, 0, &alg_id->id },
|
||||
{ "parameters", SC_ASN1_STRUCT, 0, SC_ASN1_OPTIONAL, NULL },
|
||||
{ NULL }
|
||||
|
@ -82,16 +82,16 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen,
|
|||
struct asn1_algorithm_id pk_alg, sig_alg;
|
||||
u8 *pk = NULL;
|
||||
size_t pklen = 0;
|
||||
struct sc_asn1_struct asn1_version[] = {
|
||||
struct sc_asn1_entry asn1_version[] = {
|
||||
{ "version", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &cert->version },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_pkinfo[] = {
|
||||
struct sc_asn1_entry asn1_pkinfo[] = {
|
||||
{ "algorithm", SC_ASN1_CALLBACK, ASN1_SEQUENCE | SC_ASN1_CONS, 0, (void *) 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[] = {
|
||||
struct sc_asn1_entry 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 },
|
||||
|
@ -101,7 +101,7 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen,
|
|||
{ "subjectPublicKeyInfo",SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_pkinfo },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_cert[] = {
|
||||
struct sc_asn1_entry asn1_cert[] = {
|
||||
{ "tbsCertificate", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert },
|
||||
{ "signatureAlgorithm", SC_ASN1_CALLBACK, ASN1_SEQUENCE | SC_ASN1_CONS, 0, (void *) parse_algorithm_id, &sig_alg },
|
||||
{ "signatureValue", SC_ASN1_BIT_STRING,ASN1_BIT_STRING, 0, NULL, 0 },
|
||||
|
@ -277,45 +277,122 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_cred_ident[] = {
|
||||
{ "idType", SC_ASN1_INTEGER, ASN1_INTEGER, 0, NULL },
|
||||
{ "idValue", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct sc_asn1_entry c_asn1_com_cert_attr[] = {
|
||||
{ "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL },
|
||||
{ "authority", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, NULL },
|
||||
{ "identifier", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL },
|
||||
/* FIXME: Add rest of the optional fields */
|
||||
{ NULL }
|
||||
};
|
||||
static const struct sc_asn1_entry c_asn1_x509_cert_attr[] = {
|
||||
{ "value", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct sc_asn1_entry c_asn1_type_cert_attr[] = {
|
||||
{ "x509CertificateAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct sc_asn1_entry c_asn1_cert[] = {
|
||||
{ "x509Certificate", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int parse_x509_cert_info(struct sc_context *ctx,
|
||||
struct sc_pkcs15_cert_info *cert,
|
||||
const u8 ** buf, size_t *buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4],
|
||||
asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
|
||||
asn1_cert[2];
|
||||
struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL,
|
||||
asn1_type_cert_attr };
|
||||
u8 id_value[128];
|
||||
int id_type, id_value_len = sizeof(id_value);
|
||||
int r;
|
||||
|
||||
cert->authority = 0;
|
||||
|
||||
struct sc_asn1_struct asn1_cred_ident[] = {
|
||||
{ "idType", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &id_type },
|
||||
{ "idValue", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, &id_value, &id_value_len },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_com_cert_attr[] = {
|
||||
{ "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, &cert->id, NULL },
|
||||
{ "authority", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, &cert->authority, NULL },
|
||||
{ "identifier", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_cred_ident },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_x509_cert_attr[] = {
|
||||
{ "value", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &cert->path },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_type_cert_attr[] = {
|
||||
{ "x509CertificateAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_x509_cert_attr },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL,
|
||||
asn1_type_cert_attr };
|
||||
struct sc_asn1_struct asn1_cert[] = {
|
||||
{ "x509Certificate", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &cert_obj },
|
||||
{ NULL }
|
||||
};
|
||||
sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
|
||||
sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
|
||||
|
||||
sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0);
|
||||
sc_format_asn1_entry(asn1_com_cert_attr + 0, &cert->id, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_com_cert_attr + 1, &cert->authority, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_com_cert_attr + 2, asn1_cred_ident, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_x509_cert_attr + 0, &cert->path, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_type_cert_attr + 0, asn1_x509_cert_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_cert + 0, &cert_obj, NULL, 0);
|
||||
|
||||
r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int encode_x509_cert_info(struct sc_context *ctx,
|
||||
struct sc_pkcs15_cert_info *cert,
|
||||
u8 ** buf, size_t *buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4],
|
||||
asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
|
||||
asn1_cert[2];
|
||||
const struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL,
|
||||
asn1_type_cert_attr };
|
||||
int r;
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
|
||||
sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
|
||||
sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
|
||||
|
||||
sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &cert->id, NULL, 1);
|
||||
if (cert->authority)
|
||||
sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &cert->authority, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_x509_cert_attr + 0, (void *) &cert->path, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_type_cert_attr + 0, (void *) asn1_x509_cert_attr, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1);
|
||||
|
||||
r = sc_asn1_encode(ctx, asn1_cert, buf, buflen);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sc_pkcs15_create_cdf(struct sc_pkcs15_card *p15card,
|
||||
struct sc_file *file,
|
||||
const struct sc_pkcs15_cert_info **certs)
|
||||
{
|
||||
u8 *buf = NULL, *tmp;
|
||||
size_t bufsize = 0, tmpsize;
|
||||
int i = 0, r;
|
||||
const struct sc_pkcs15_cert_info *cert;
|
||||
u8 str[10240];
|
||||
|
||||
for (i = 0; (cert = certs[i]) != NULL; i++) {
|
||||
r = encode_x509_cert_info(p15card->card->ctx,
|
||||
(struct sc_pkcs15_cert_info *) cert,
|
||||
&tmp, &tmpsize);
|
||||
if (r) {
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
buf = realloc(buf, bufsize + tmpsize);
|
||||
memcpy(buf + bufsize, tmp, tmpsize);
|
||||
bufsize += tmpsize;
|
||||
}
|
||||
sc_hex_dump(p15card->card->ctx, buf, bufsize, str, sizeof(str));
|
||||
printf("\n%s\n", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* sc-pkcs15-pin.c: PKCS#15 PIN functions
|
||||
* pkcs15-pin.c: PKCS#15 PIN functions
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
@ -32,13 +32,13 @@ static int parse_pin_info(struct sc_context *ctx,
|
|||
const u8 ** buf, size_t *buflen)
|
||||
{
|
||||
int r;
|
||||
struct sc_asn1_struct asn1_com_ao_attr[] = {
|
||||
struct sc_asn1_entry 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[] = {
|
||||
struct sc_asn1_entry 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 },
|
||||
|
@ -50,13 +50,13 @@ static int parse_pin_info(struct sc_context *ctx,
|
|||
{ "path", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, &pin->path },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_type_pin_attr[] = {
|
||||
struct sc_asn1_entry 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[] = {
|
||||
struct sc_asn1_entry asn1_pin[] = {
|
||||
{ "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* sc-pkcs15-prkey.c: PKCS#15 private key functions
|
||||
* pkcs15-prkey.c: PKCS#15 private key functions
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
@ -55,7 +55,7 @@ static int parse_rsa_prkey_info(struct sc_context *ctx,
|
|||
int r;
|
||||
int usage_len = sizeof(prkey->usage);
|
||||
int af_len = sizeof(prkey->access_flags);
|
||||
struct sc_asn1_struct asn1_com_key_attr[] = {
|
||||
struct sc_asn1_entry 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 },
|
||||
|
@ -63,23 +63,23 @@ static int parse_rsa_prkey_info(struct sc_context *ctx,
|
|||
{ "keyReference",SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, &prkey->key_reference },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_com_prkey_attr[] = {
|
||||
struct sc_asn1_entry asn1_com_prkey_attr[] = {
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_rsakey_attr[] = {
|
||||
struct sc_asn1_entry 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[] = {
|
||||
struct sc_asn1_entry asn1_type_attr[] = {
|
||||
{ "publicRSAKeyAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_rsakey_attr },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct sc_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr,
|
||||
asn1_com_prkey_attr, asn1_type_attr };
|
||||
struct sc_asn1_struct asn1_prkey[] = {
|
||||
struct sc_asn1_entry asn1_prkey[] = {
|
||||
{ "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* sc-pkcs15-sec.c: PKCS#15 cryptography functions
|
||||
* pkcs15-sec.c: PKCS#15 cryptography functions
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* sc-pkcs15.c: PKCS#15 general functions
|
||||
* pkcs15.c: PKCS#15 general functions
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
@ -64,7 +64,7 @@ void parse_tokeninfo(struct sc_pkcs15_card *card, const u8 * buf, size_t buflen)
|
|||
int mnfid_len = sizeof(mnfid);
|
||||
int flags_len = sizeof(card->flags);
|
||||
|
||||
struct sc_asn1_struct asn1_tokeninfo[] = {
|
||||
struct sc_asn1_entry asn1_tokeninfo[] = {
|
||||
{ "version", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &card->version },
|
||||
{ "serialNumber", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, serial, &serial_len },
|
||||
{ "manufacturerID", SC_ASN1_UTF8STRING, ASN1_UTF8STRING, SC_ASN1_OPTIONAL, mnfid, &mnfid_len },
|
||||
|
@ -119,14 +119,14 @@ static int parse_dir(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card)
|
|||
int aid_len = sizeof(aid), label_len = sizeof(label),
|
||||
path_len = sizeof(path);
|
||||
|
||||
struct sc_asn1_struct asn1_ddo[] = {
|
||||
struct sc_asn1_entry asn1_ddo[] = {
|
||||
{ "oid", SC_ASN1_OBJECT, ASN1_OBJECT, 0, NULL },
|
||||
{ "odfPath", SC_ASN1_PATH, SC_ASN1_CONS | ASN1_SEQUENCE, SC_ASN1_OPTIONAL, &card->file_odf.path },
|
||||
{ "tokenInfoPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, &card->file_tokeninfo.path },
|
||||
{ "unusedPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_dir[] = {
|
||||
struct sc_asn1_entry asn1_dir[] = {
|
||||
{ "aid", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 15, 0, aid, &aid_len },
|
||||
{ "label", SC_ASN1_UTF8STRING, SC_ASN1_APP | 16, SC_ASN1_OPTIONAL, label, &label_len },
|
||||
{ "path", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 17, 0, path, &path_len },
|
||||
|
@ -168,11 +168,11 @@ static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card)
|
|||
size_t left = buflen;
|
||||
int r;
|
||||
struct sc_path path;
|
||||
struct sc_asn1_struct asn1_obj_or_path[] = {
|
||||
struct sc_asn1_entry asn1_obj_or_path[] = {
|
||||
{ "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path },
|
||||
{ NULL }
|
||||
};
|
||||
struct sc_asn1_struct asn1_odf[] = {
|
||||
struct sc_asn1_entry asn1_odf[] = {
|
||||
{ "privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
||||
{ "certificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
||||
{ "trustedCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 5 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
||||
|
@ -254,7 +254,7 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
err = sc_select_file(card, &tmppath, &p15card->file_dir);
|
||||
if (err) {
|
||||
error(ctx, "Error selecting EF(DIR): %s\n", sc_strerror(err));
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
goto error;
|
||||
}
|
||||
err = sc_read_binary(card, 0, buf, p15card->file_dir.size, 0);
|
||||
|
@ -263,13 +263,13 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
goto error;
|
||||
}
|
||||
if (err <= 2) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
error(ctx, "Error reading EF(DIR): too few bytes read\n");
|
||||
goto error;
|
||||
}
|
||||
len = err;
|
||||
if (parse_dir(buf, len, p15card)) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
error(ctx, "Error parsing EF(DIR)\n");
|
||||
goto error;
|
||||
}
|
||||
|
@ -290,12 +290,12 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
if (err < 0)
|
||||
goto error;
|
||||
if (err < 2) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
goto error;
|
||||
}
|
||||
len = err;
|
||||
if (parse_odf(buf, len, p15card)) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
goto error;
|
||||
}
|
||||
if (p15card->file_tokeninfo.path.len == 0) {
|
||||
|
@ -315,7 +315,7 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
if (err < 0)
|
||||
goto error;
|
||||
if (err <= 2) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||
goto error;
|
||||
}
|
||||
parse_tokeninfo(p15card, buf, err);
|
||||
|
|
|
@ -176,10 +176,14 @@ struct sc_pkcs15_defaults {
|
|||
int arg;
|
||||
};
|
||||
|
||||
/* Binds a card object to a PKCS#15 card object and initializes
|
||||
* a new PKCS#15 card object */
|
||||
/* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object
|
||||
* and initializes a new PKCS#15 card object. Will return
|
||||
* SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a
|
||||
* valid PKCS #15 file structure. */
|
||||
int sc_pkcs15_bind(struct sc_card *card,
|
||||
struct sc_pkcs15_card **pkcs15_card);
|
||||
/* sc_pkcs_unbind: Releases a PKCS #15 card object, and frees any
|
||||
* memory allocations done on the card object. */
|
||||
int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
|
||||
|
||||
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
||||
|
@ -205,6 +209,12 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert);
|
|||
int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *card,
|
||||
const struct sc_pkcs15_id *id,
|
||||
struct sc_pkcs15_cert_info **out);
|
||||
/* sc_pkcs15_create_cdf: Creates a new certificate DF on a card pointed
|
||||
* by <card>. Information about the file, such as the file ID, is read
|
||||
* from <file>. <certs> has to be NULL-terminated. */
|
||||
int sc_pkcs15_create_cdf(struct sc_pkcs15_card *card,
|
||||
struct sc_file *file,
|
||||
const struct sc_pkcs15_cert_info **certs);
|
||||
|
||||
void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey);
|
||||
int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "opensc.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
|
||||
struct sc_asn1_struct {
|
||||
struct sc_asn1_entry {
|
||||
const char *name;
|
||||
unsigned int type;
|
||||
unsigned int tag;
|
||||
|
@ -35,19 +35,24 @@ struct sc_asn1_struct {
|
|||
|
||||
struct sc_pkcs15_object {
|
||||
struct sc_pkcs15_common_obj_attr *com_attr;
|
||||
struct sc_asn1_struct *asn1_class_attr;
|
||||
struct sc_asn1_struct *asn1_subclass_attr;
|
||||
struct sc_asn1_struct *asn1_type_attr;
|
||||
struct sc_asn1_entry *asn1_class_attr;
|
||||
struct sc_asn1_entry *asn1_subclass_attr;
|
||||
struct sc_asn1_entry *asn1_type_attr;
|
||||
};
|
||||
|
||||
/* Utility functions */
|
||||
void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg,
|
||||
int set_present);
|
||||
void sc_copy_asn1_entry(const struct sc_asn1_entry *src,
|
||||
struct sc_asn1_entry *dest);
|
||||
|
||||
/* DER tag and length parsing */
|
||||
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *left);
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_struct *asn1,
|
||||
int sc_asn1_decode_choice(struct sc_context *ctx, struct sc_asn1_entry *asn1,
|
||||
const u8 *in, size_t len, const u8 **newp, size_t *left);
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_struct *asn1,
|
||||
u8 *buf, size_t bufsize, size_t *obj_size);
|
||||
int sc_asn1_encode(struct sc_context *ctx, const struct sc_asn1_entry *asn1,
|
||||
u8 **buf, size_t *bufsize);
|
||||
|
||||
const u8 *sc_asn1_find_tag(struct sc_context *ctx, const u8 * buf,
|
||||
size_t buflen, unsigned int tag, size_t *taglen);
|
||||
|
|
|
@ -172,6 +172,7 @@ int sc_establish_context(struct sc_context **ctx_out)
|
|||
} while (p < (reader_buf + reader_buf_size - 1));
|
||||
free(reader_buf);
|
||||
pthread_mutex_init(&ctx->mutex, NULL);
|
||||
ctx->forced_driver = NULL;
|
||||
for (i = 0; i < SC_MAX_CARD_DRIVERS+1; i++)
|
||||
ctx->card_drivers[i] = NULL;
|
||||
i = 0;
|
||||
|
@ -179,7 +180,7 @@ int sc_establish_context(struct sc_context **ctx_out)
|
|||
ctx->card_drivers[i++] = sc_get_setec_driver();
|
||||
#endif
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_mflex_driver();
|
||||
ctx->card_drivers[i++] = sc_get_flex_driver();
|
||||
#endif
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_iso7816_driver();
|
||||
|
@ -208,19 +209,19 @@ int sc_destroy_context(struct sc_context *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sc_set_default_card_driver(struct sc_context *ctx, const char *short_name)
|
||||
int sc_set_card_driver(struct sc_context *ctx, const char *short_name)
|
||||
{
|
||||
int i = 0, match = 0;
|
||||
|
||||
pthread_mutex_lock(&ctx->mutex);
|
||||
if (short_name == NULL) {
|
||||
ctx->default_driver = NULL;
|
||||
ctx->forced_driver = NULL;
|
||||
match = 1;
|
||||
} else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) {
|
||||
const struct sc_card_driver *drv = ctx->card_drivers[i];
|
||||
|
||||
if (strcmp(short_name, drv->short_name) == 0) {
|
||||
ctx->default_driver = drv;
|
||||
ctx->forced_driver = drv;
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* sc-sec.c: Cryptography and security (ISO7816-8) functions
|
||||
* sec.c: Cryptography and security (ISO7816-8) functions
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
|
|
|
@ -280,7 +280,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con
|
|||
printf("%s\n", argv[i]);
|
||||
|
||||
#ifdef TEST
|
||||
user = "root";
|
||||
user = "jey";
|
||||
#else
|
||||
r = pam_get_user(pamh, &user, NULL);
|
||||
if (r != PAM_SUCCESS)
|
||||
|
|
|
@ -186,6 +186,15 @@ int do_cd(const char *arg)
|
|||
check_ret(r, SC_AC_OP_SELECT, "unable to select DF", ¤t_file);
|
||||
return -1;
|
||||
}
|
||||
if (file.type != SC_FILE_TYPE_DF) {
|
||||
printf("Error: file is not a DF.\n");
|
||||
r = sc_select_file(card, ¤t_path, NULL);
|
||||
if (r) {
|
||||
printf("unable to select parent file: %s\n", sc_strerror(r));
|
||||
die(1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
memcpy(current_path.value + current_path.len, path.value, path.len);
|
||||
current_path.len += path.len;
|
||||
current_file = file;
|
||||
|
|
|
@ -393,7 +393,7 @@ int main(int argc, char * const argv[])
|
|||
goto end;
|
||||
}
|
||||
if (opt_driver != NULL) {
|
||||
err = sc_set_default_card_driver(ctx, opt_driver);
|
||||
err = sc_set_card_driver(ctx, opt_driver);
|
||||
if (err) {
|
||||
fprintf(stderr, "Driver '%s' not found!\n", opt_driver);
|
||||
err = 1;
|
||||
|
|
Loading…
Reference in New Issue