- continued to improve PKCS #15 generation

- fixed a few problems in sc_set_security_env
- started to implement Better (tm) object handling for
  PKCS #15 objects


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@167 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2002-01-16 23:59:18 +00:00
parent 2d95b18b27
commit 20adb4b39c
21 changed files with 455 additions and 213 deletions

2
THANKS
View File

@ -2,4 +2,4 @@ The following people provided inspiration, moral support and/or valuable
information during the development of OpenSC:
Antti Partanen <antti.partanen@vrk.intermin.fi>
Antti Siltanen <antti.siltanen@siltanet.fi>
David Corcoran <corcoran@linuxnet.com>

View File

@ -703,7 +703,7 @@ static const struct sc_asn1_entry c_asn1_p15_obj[5] = {
};
static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in,
size_t len, struct sc_pkcs15_object *obj,
size_t len, struct sc_asn1_pkcs15_object *obj,
int depth)
{
int r;
@ -729,7 +729,7 @@ static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in,
return r;
}
static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_pkcs15_object *obj,
static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_asn1_pkcs15_object *obj,
u8 **buf, size_t *bufsize, int depth)
{
int r;
@ -885,7 +885,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry
break;
case SC_ASN1_PKCS15_OBJECT:
if (entry->parm != NULL)
r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_pkcs15_object *) parm, depth);
r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_asn1_pkcs15_object *) parm, depth);
break;
case SC_ASN1_CALLBACK:
if (entry->parm != NULL)
@ -1061,7 +1061,7 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry
}
break;
case SC_ASN1_PKCS15_OBJECT:
r = asn1_encode_p15_object(ctx, (const struct sc_pkcs15_object *) parm, &buf, &buflen, depth);
r = asn1_encode_p15_object(ctx, (const struct sc_asn1_pkcs15_object *) parm, &buf, &buflen, depth);
break;
case SC_ASN1_CALLBACK:
r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
@ -1071,7 +1071,7 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry
assert(0);
}
if (r) {
error(ctx, "decoding of ASN.1 object '%s' failed: %s\n", entry->name,
error(ctx, "encoding of ASN.1 object '%s' failed: %s\n", entry->name,
sc_strerror(r));
if (buf)
free(buf);

View File

@ -33,7 +33,7 @@ struct sc_asn1_entry {
void *arg;
};
struct sc_pkcs15_object {
struct sc_asn1_pkcs15_object {
struct sc_pkcs15_common_obj_attr *com_attr;
struct sc_asn1_entry *asn1_class_attr;
struct sc_asn1_entry *asn1_subclass_attr;

View File

@ -538,6 +538,98 @@ static int iso7816_verify(struct sc_card *card, unsigned int type, int ref,
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
}
static int iso7816_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
struct sc_apdu apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 *p;
int r, locked = 0;
assert(card != NULL && env != NULL);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
apdu.p1 = 0x41;
apdu.p2 = 0xB8;
break;
case SC_SEC_OPERATION_SIGN:
apdu.p1 = 0x81;
apdu.p2 = 0xB6;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
apdu.le = 0;
p = sbuf;
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
*p++ = 0x80; /* algorithm reference */
*p++ = env->algorithm_ref >> 8;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
*p++ = 0x81;
*p++ = env->key_file_id.len;
memcpy(p, env->key_file_id.value, env->key_file_id.len);
p += env->key_file_id.len;
}
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
*p++ = 0x84;
*p++ = env->key_ref >> 8;
*p++ = env->key_ref & 0xFF;
}
r = p - sbuf;
apdu.lc = r;
apdu.datalen = r;
apdu.data = sbuf;
apdu.resplen = 0;
if (se_num > 0) {
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
locked = 1;
}
if (apdu.datalen != 0) {
r = sc_transmit_apdu(card, &apdu);
if (r) {
sc_perror(card->ctx, r, "APDU transmit failed");
goto err;
}
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
if (r) {
sc_perror(card->ctx, r, "Card returned error");
goto err;
}
}
if (se_num <= 0)
return 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
r = sc_transmit_apdu(card, &apdu);
sc_unlock(card);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
err:
if (locked)
sc_unlock(card);
return r;
}
static int iso7816_restore_security_env(struct sc_card *card, int se_num)
{
struct sc_apdu apdu;
int r;
u8 rbuf[MAX_BUFFER_SIZE];
assert(card != NULL);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
}
static struct sc_card_operations iso_ops = {
NULL,
};
@ -566,9 +658,11 @@ const struct sc_card_driver * sc_get_iso7816_driver(void)
iso_ops.select_file = iso7816_select_file;
iso_ops.get_challenge = iso7816_get_challenge;
iso_ops.create_file = iso7816_create_file;
iso_ops.delete_file = iso7816_delete_file;
iso_ops.list_files = iso7816_list_files;
iso_ops.verify = iso7816_verify;
iso_ops.delete_file = iso7816_delete_file;
iso_ops.list_files = iso7816_list_files;
iso_ops.verify = iso7816_verify;
iso_ops.set_security_env = iso7816_set_security_env;
iso_ops.restore_security_env = iso7816_restore_security_env;
}
return &iso_driver;
}

View File

@ -173,3 +173,8 @@ void sc_hex_dump(struct sc_context *ctx, const u8 *in, size_t count,
lines++;
}
}
void sc_perror(struct sc_context *ctx, int error, const char *str)
{
error(ctx, "%s: %s\n", sc_strerror(error), str);
}

View File

@ -66,5 +66,6 @@ void do_log2(struct sc_context *ctx, int facility, const char *file,
void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len,
char *out, size_t outlen);
void sc_perror(struct sc_context *ctx, int error, const char *str);
#endif

View File

@ -125,6 +125,13 @@ struct sc_pkcs15_cert_info {
#define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08
#define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10
#define SC_PKCS15_TYPE_PRKEY_RSA 0x100
#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200
#define SC_PKCS15_TYPE_CERT_X509 0x400
#define SC_PKCS15_TYPE_CERT_SPKI 0x402
#define SC_PKCS15_TYPE_DATA_OBJECT 0x500
#define SC_PKCS15_TYPE_AUTH_PIN 0x600
struct sc_pkcs15_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr;
@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info {
int modulus_length;
};
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
struct sc_pkcs15_object {
int type;
void *data;
/* For linked list purposes */
struct sc_pkcs15_object *next;
};
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_MAX_DFS 4
struct sc_pkcs15_df {
struct sc_file *file[SC_PKCS15_MAX_DFS];
int count, record_length;
struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS];
int count, record_length, type;
};
struct sc_pkcs15_card {
@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card,
* memory allocations done on the card object. */
int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
const u8 *in, int inlen, u8 *out, int outlen);
@ -248,11 +268,19 @@ int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id,
struct sc_pkcs15_pin_info **out);
int sc_pkcs15_encode_df(struct sc_pkcs15_card *card,
struct sc_pkcs15_df *df, int file_nr,
u8 **buf, size_t *bufsize);
int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2);
void sc_pkcs15_print_id(const struct sc_pkcs15_id *id);
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out);
int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df,
int file_nr, struct sc_pkcs15_object *new_obj);
extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[];
#ifdef __cplusplus

View File

@ -195,12 +195,18 @@ struct sc_file {
#define SC_SEC_OPERATION_DECIPHER 0
#define SC_SEC_OPERATION_SIGN 1
/* sc_security_env flags */
#define SC_SEC_ENV_ALG_REF_PRESENT 0x01
#define SC_SEC_ENV_FILE_REF_PRESENT 0x02
#define SC_SEC_ENV_KEY_REF_PRESENT 0x04
struct sc_security_env {
int algorithm_ref;
struct sc_path key_file_id;
int operation;
int key_ref;
int flags;
};
/*
@ -291,8 +297,7 @@ struct sc_card_operations {
/* restore_security_env: Restores a previously saved security
* environment, and stores information about the environment to
* <env_out>, if not NULL. */
int (*restore_security_env)(struct sc_card *card, int se_num,
struct sc_security_env *env_out);
int (*restore_security_env)(struct sc_card *card, int se_num);
/* set_security_env: Initializes the security environment on card
* according to <env>, and stores the environment as <se_num> on the
@ -470,7 +475,7 @@ int sc_get_challenge(struct sc_card *card, u8 * rndout, size_t len);
/* ISO 7816-8 related functions */
int sc_restore_security_env(struct sc_card *card, int se_num);
int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env);
const struct sc_security_env *env, int se_num);
int sc_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len,
u8 * out, size_t outlen);
int sc_compute_signature(struct sc_card *card, const u8 * data,

View File

@ -309,7 +309,7 @@ static int parse_x509_cert_info(struct sc_context *ctx,
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,
struct sc_asn1_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);
@ -337,14 +337,16 @@ static int parse_x509_cert_info(struct sc_context *ctx,
return r;
}
static int encode_x509_cert_info(struct sc_context *ctx,
struct sc_pkcs15_cert_info *cert,
u8 ** buf, size_t *buflen)
int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize)
{
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,
struct sc_pkcs15_cert_info *infop =
(struct sc_pkcs15_cert_info *) obj->data;
const struct sc_asn1_pkcs15_object cert_obj = { &infop->com_attr, asn1_com_cert_attr, NULL,
asn1_type_cert_attr };
int r;
@ -354,45 +356,18 @@ static int encode_x509_cert_info(struct sc_context *ctx,
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_com_cert_attr + 0, (void *) &infop->id, NULL, 1);
if (infop->authority)
sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1);
sc_format_asn1_entry(asn1_x509_cert_attr + 0, (void *) &infop->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);
r = sc_asn1_encode(p15card->card->ctx, asn1_cert, buf, bufsize);
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;
char 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("CDF:\n%s\n", str);
return 0;
}
void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert)
{
int i;
@ -408,36 +383,57 @@ void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert)
printf("\n");
}
static int get_certs_from_file(struct sc_pkcs15_card *card,
struct sc_file *file)
static int get_certs_from_file(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_df *df,
int file_nr)
{
int r;
size_t bytes_left;
u8 buf[2048];
const u8 *p = buf;
struct sc_file *file = df->file[file_nr];
r = sc_select_file(card->card, &file->path, file);
r = sc_select_file(p15card->card, &file->path, file);
if (r)
return r;
if (file->size > sizeof(buf))
return SC_ERROR_BUFFER_TOO_SMALL;
r = sc_read_binary(card->card, 0, buf, file->size, 0);
r = sc_read_binary(p15card->card, 0, buf, file->size, 0);
if (r < 0)
return r;
bytes_left = r;
do {
struct sc_pkcs15_cert_info tmp;
struct sc_pkcs15_cert_info info, *infop;
struct sc_pkcs15_object *objp;
r = parse_x509_cert_info(card->card->ctx,
&tmp, &p, &bytes_left);
memset(&info, 0, sizeof(info));
r = parse_x509_cert_info(p15card->card->ctx,
&info, &p, &bytes_left);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
break;
if (r)
return r;
if (card->cert_count >= SC_PKCS15_MAX_CERTS)
return SC_ERROR_TOO_MANY_OBJECTS;
card->cert_info[card->cert_count] = tmp;
card->cert_count++;
infop = malloc(sizeof(info));
if (infop == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(infop, &info, sizeof(info));
objp = malloc(sizeof(struct sc_pkcs15_object));
if (objp == NULL) {
free(infop);
return SC_ERROR_OUT_OF_MEMORY;
}
objp->type = SC_PKCS15_TYPE_CERT_X509;
objp->data = infop;
r = sc_pkcs15_add_object(p15card->card->ctx, df, file_nr, objp);
if (r) {
free(infop);
free(objp);
return r;
}
if (p15card->cert_count >= SC_PKCS15_MAX_PRKEYS)
break;
p15card->cert_info[p15card->cert_count] = info;
p15card->cert_count++;
} while (bytes_left);
return 0;
@ -461,7 +457,7 @@ int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card)
type = df_types[j];
for (i = 0; i < card->df[type].count; i++) {
r = get_certs_from_file(card, card->df[type].file[i]);
r = get_certs_from_file(card, &card->df[type], i);
if (r != 0)
break;
}

View File

@ -54,7 +54,7 @@ static int parse_pin_info(struct sc_context *ctx,
{ "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,
struct sc_asn1_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL,
asn1_type_pin_attr };
struct sc_asn1_entry asn1_pin[] = {
{ "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj },

View File

@ -77,7 +77,7 @@ static int parse_rsa_prkey_info(struct sc_context *ctx,
{ NULL }
};
struct sc_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr,
struct sc_asn1_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_type_attr };
struct sc_asn1_entry asn1_prkey[] = {
{ "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj },

View File

@ -39,6 +39,8 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
senv.key_file_id = prkey->file_id;
senv.operation = SC_SEC_OPERATION_DECIPHER;
senv.key_ref = 0x0100 | prkey->key_reference;
senv.flags = SC_SEC_ENV_ALG_REF_PRESENT | SC_SEC_ENV_FILE_REF_PRESENT;
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path,
@ -49,7 +51,7 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
#endif
r = sc_set_security_env(p15card->card, &senv);
r = sc_set_security_env(p15card->card, &senv, 0);
SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
r = sc_decipher(p15card->card, in, inlen, out, outlen);
SC_TEST_RET(ctx, r, "sc_decipher() failed");
@ -77,6 +79,8 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
senv.key_file_id = prkey->file_id;
senv.operation = SC_SEC_OPERATION_SIGN;
senv.key_ref = 0x0100 | prkey->key_reference;
senv.flags = SC_SEC_ENV_ALG_REF_PRESENT | SC_SEC_ENV_FILE_REF_PRESENT;
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path,
@ -87,7 +91,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
#endif
r = sc_set_security_env(p15card->card, &senv);
r = sc_set_security_env(p15card->card, &senv, 0);
SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
r = sc_compute_signature(p15card->card, in, inlen, out, outlen);
SC_TEST_RET(ctx, r, "sc_compute_signature() failed");

View File

@ -128,7 +128,7 @@ err:
return;
}
int encode_tokeninfo(struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen)
int encode_tokeninfo(struct sc_context *ctx, struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen)
{
int i, r;
u8 serial[128];
@ -170,27 +170,27 @@ int encode_tokeninfo(struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen)
}
sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1);
r = sc_asn1_encode(card->card->ctx, asn1_tokeninfo, buf, buflen);
r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
if (r) {
error(card->card->ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
return r;
}
return 0;
}
int sc_pkcs15_create_tokeninfo(struct sc_pkcs15_card *card)
int sc_pkcs15_create_tokeninfo(struct sc_card *card, struct sc_pkcs15_card *p15card)
{
int r;
u8 *buf;
size_t buflen;
char line[10240];
r = encode_tokeninfo(card, &buf, &buflen);
r = encode_tokeninfo(card->ctx, p15card, &buf, &buflen);
if (r) {
error(card->card->ctx, "Error encoding EF(TokenInfo): %s\n", sc_strerror(r));
error(card->ctx, "Error encoding EF(TokenInfo): %s\n", sc_strerror(r));
return r;
}
sc_hex_dump(card->card->ctx, buf, buflen, line, sizeof(line));
sc_hex_dump(card->ctx, buf, buflen, line, sizeof(line));
printf("%s\n", line);
return 0;
}
@ -260,10 +260,9 @@ static int parse_dir(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card)
return 0;
}
static int encode_dir(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
static int encode_dir(struct sc_context *ctx, struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
{
struct sc_asn1_entry asn1_ddo[5], asn1_dirrecord[5], asn1_dir[2];
struct sc_context *ctx = card->card->ctx;
int r;
size_t label_len;
@ -290,20 +289,17 @@ static int encode_dir(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
#endif
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
if (r) {
error(card->card->ctx, "sc_asn1_encode() failed: %s\n",
error(ctx, "sc_asn1_encode() failed: %s\n",
sc_strerror(r));
return r;
}
return 0;
}
/* FIXME: This should be done using sc_update_binary(),
* and be generally wiser */
int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card)
int sc_pkcs15_create_dir(struct sc_card *card, struct sc_pkcs15_card *p15card)
{
struct sc_card *card = p15card->card;
struct sc_path path;
u8 *buf;
size_t bufsize;
@ -314,9 +310,9 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card)
sc_format_path("3F00", &path);
r = sc_select_file(card, &path, NULL);
SC_TEST_RET(card->ctx, r, "sc_select_file(MF) failed");
r = encode_dir(p15card, &buf, &bufsize);
r = encode_dir(card->ctx, p15card, &buf, &bufsize);
SC_TEST_RET(card->ctx, r, "EF(DIR) encoding failed");
sc_hex_dump(p15card->card->ctx, buf, bufsize, line, sizeof(line));
sc_hex_dump(card->ctx, buf, bufsize, line, sizeof(line));
free(buf);
printf("%s", line);
@ -380,11 +376,13 @@ static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card)
return 0;
}
static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
static int encode_odf(struct sc_context *ctx, struct sc_pkcs15_card *card,
u8 **buf, size_t *buflen)
{
struct sc_path 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_entry *asn1_paths = NULL;
struct sc_asn1_entry *asn1_odf = NULL;
@ -415,7 +413,7 @@ static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
break;
}
if (type == -1) {
error(card->card->ctx, "Unsupported DF type.\n");
error(ctx, "Unsupported DF type.\n");
continue;
}
for (j = 0; j < df->count; j++) {
@ -427,7 +425,7 @@ static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
}
}
asn1_odf[df_count].name = NULL;
r = sc_asn1_encode(card->card->ctx, asn1_odf, buf, buflen);
r = sc_asn1_encode(ctx, asn1_odf, buf, buflen);
err:
if (asn1_paths != NULL)
free(asn1_paths);
@ -436,16 +434,16 @@ err:
return r;
}
int sc_pkcs15_create_odf(struct sc_pkcs15_card *p15card)
int sc_pkcs15_create_odf(struct sc_card *card, struct sc_pkcs15_card *p15card)
{
u8 *buf;
size_t buflen;
char line[10240];
int r;
r = encode_odf(p15card, &buf, &buflen);
SC_TEST_RET(p15card->card->ctx, r, "ODF encoding failed");
sc_hex_dump(p15card->card->ctx, buf, buflen, line, sizeof(line));
r = encode_odf(card->ctx, p15card, &buf, &buflen);
SC_TEST_RET(card->ctx, r, "ODF encoding failed");
sc_hex_dump(card->ctx, buf, buflen, line, sizeof(line));
printf("ODF:\n%s", line);
return 0;
}
@ -456,6 +454,44 @@ static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen)
return NULL;
}
struct sc_pkcs15_card * sc_pkcs15_card_new()
{
struct sc_pkcs15_card *p15card;
int i;
p15card = malloc(sizeof(struct sc_pkcs15_card));
if (p15card == NULL)
return NULL;
memset(p15card, 0, sizeof(struct sc_pkcs15_card));
for (i = 0; i < SC_PKCS15_DF_TYPE_COUNT; i++)
p15card->df[i].type = i;
return p15card;
}
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
{
int i, j;
for (j = 0; j < SC_PKCS15_DF_TYPE_COUNT; j++)
for (i = 0; i < p15card->df[j].count; i++) {
struct sc_pkcs15_object *p;
if (p15card->df[j].file[i])
free(p15card->df[j].file[i]);
p = p15card->df[j].obj[i];
while (p != NULL) {
struct sc_pkcs15_object *p2 = p->next;
if (p->data != NULL)
free(p->data);
free(p);
p = p2;
}
}
free(p15card->label);
free(p15card->serial_number);
free(p15card->manufacturer_id);
free(p15card);
}
int sc_pkcs15_bind(struct sc_card *card,
struct sc_pkcs15_card **p15card_out)
{
@ -470,10 +506,9 @@ int sc_pkcs15_bind(struct sc_card *card,
assert(sc_card_valid(card) && p15card_out != NULL);
ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1);
p15card = malloc(sizeof(struct sc_pkcs15_card));
p15card = sc_pkcs15_card_new();
if (p15card == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memset(p15card, 0, sizeof(struct sc_pkcs15_card));
p15card->card = card;
sc_format_path("2F00", &tmppath);
@ -577,21 +612,73 @@ int sc_pkcs15_detect(struct sc_card *card)
int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)
{
int i, j;
assert(p15card != NULL);
SC_FUNC_CALLED(p15card->card->ctx, 1);
for (j = 0; j < SC_PKCS15_DF_TYPE_COUNT; j++)
for (i = 0; i < p15card->df[j].count; i++)
if (p15card->df[j].file[i])
free(p15card->df[j].file[i]);
free(p15card->label);
free(p15card->serial_number);
free(p15card->manufacturer_id);
free(p15card);
sc_pkcs15_card_free(p15card);
return 0;
}
int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df,
int file_nr, struct sc_pkcs15_object *obj)
{
struct sc_pkcs15_object *p = df->obj[file_nr];
obj->next = NULL;
if (p == NULL) {
df->obj[file_nr] = obj;
return 0;
}
while (p->next != NULL)
p = p->next;
p->next = obj;
return 0;
}
int sc_pkcs15_encode_df(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_df *df,
int file_no,
u8 **buf_out, size_t *bufsize_out)
{
u8 *buf = NULL, *tmp;
size_t bufsize = 0, tmpsize;
int r;
const struct sc_pkcs15_object *obj = df->obj[file_no];
char str[10240];
int (* func)(struct sc_pkcs15_card *, const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize) = NULL;
switch (df->type) {
case SC_PKCS15_PRKDF:
break;
case SC_PKCS15_CDF:
case SC_PKCS15_CDF_TRUSTED:
case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_encode_cdf_entry;
break;
}
if (func == NULL) {
error(p15card->card->ctx, "unknown DF type\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
while (obj != NULL) {
r = func(p15card, obj, &tmp, &tmpsize);
if (r) {
free(buf);
return r;
}
buf = realloc(buf, bufsize + tmpsize);
memcpy(buf + bufsize, tmp, tmpsize);
bufsize += tmpsize;
obj = obj->next;
}
sc_hex_dump(p15card->card->ctx, buf, bufsize, str, sizeof(str));
printf("DF:\n%s\n", str);
*buf_out = buf;
*bufsize_out = bufsize;
return 0;
}
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2)
{

View File

@ -125,6 +125,13 @@ struct sc_pkcs15_cert_info {
#define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08
#define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10
#define SC_PKCS15_TYPE_PRKEY_RSA 0x100
#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200
#define SC_PKCS15_TYPE_CERT_X509 0x400
#define SC_PKCS15_TYPE_CERT_SPKI 0x402
#define SC_PKCS15_TYPE_DATA_OBJECT 0x500
#define SC_PKCS15_TYPE_AUTH_PIN 0x600
struct sc_pkcs15_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr;
@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info {
int modulus_length;
};
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
struct sc_pkcs15_object {
int type;
void *data;
/* For linked list purposes */
struct sc_pkcs15_object *next;
};
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_MAX_DFS 4
struct sc_pkcs15_df {
struct sc_file *file[SC_PKCS15_MAX_DFS];
int count, record_length;
struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS];
int count, record_length, type;
};
struct sc_pkcs15_card {
@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card,
* memory allocations done on the card object. */
int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
const u8 *in, int inlen, u8 *out, int outlen);
@ -248,11 +268,19 @@ int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id,
struct sc_pkcs15_pin_info **out);
int sc_pkcs15_encode_df(struct sc_pkcs15_card *card,
struct sc_pkcs15_df *df, int file_nr,
u8 **buf, size_t *bufsize);
int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2);
void sc_pkcs15_print_id(const struct sc_pkcs15_id *id);
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out);
int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df,
int file_nr, struct sc_pkcs15_object *new_obj);
extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[];
#ifdef __cplusplus

View File

@ -33,7 +33,7 @@ struct sc_asn1_entry {
void *arg;
};
struct sc_pkcs15_object {
struct sc_asn1_pkcs15_object {
struct sc_pkcs15_common_obj_attr *com_attr;
struct sc_asn1_entry *asn1_class_attr;
struct sc_asn1_entry *asn1_subclass_attr;

View File

@ -66,5 +66,6 @@ void do_log2(struct sc_context *ctx, int facility, const char *file,
void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len,
char *out, size_t outlen);
void sc_perror(struct sc_context *ctx, int error, const char *str);
#endif

View File

@ -33,7 +33,7 @@
#ifdef VERSION
const char *sc_version = VERSION;
#else
#warning FIXME: version info
#warning FIXME: version info undefined
const char *sc_version = "(undef)";
#endif

View File

@ -24,74 +24,6 @@
#include <stdio.h>
#include <assert.h>
int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env)
{
struct sc_apdu apdu;
u8 sbuf[MAX_BUFFER_SIZE];
u8 *p;
int r;
assert(card != NULL && env != NULL);
SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
apdu.p1 = 0x41;
apdu.p2 = 0xB8;
break;
case SC_SEC_OPERATION_SIGN:
apdu.p1 = 0x81;
apdu.p2 = 0xB6;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
apdu.le = 0;
p = sbuf;
if (env->algorithm_ref >= 0) {
*p++ = 0x80; /* algorithm reference */
*p++ = env->algorithm_ref >> 8;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->key_file_id.len >= 0) {
*p++ = 0x81;
*p++ = env->key_file_id.len;
memcpy(p, env->key_file_id.value, env->key_file_id.len);
p += env->key_file_id.len;
}
if (env->key_ref >= 0) {
*p++ = 0x84;
*p++ = env->key_ref >> 8;
*p++ = env->key_ref & 0xFF;
}
r = p - sbuf;
apdu.lc = r;
apdu.datalen = r;
apdu.data = sbuf;
apdu.resplen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
}
int sc_restore_security_env(struct sc_card *card, int num)
{
struct sc_apdu apdu;
int r;
u8 rbuf[MAX_BUFFER_SIZE];
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, num);
apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
}
int sc_decipher(struct sc_card *card,
const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
{
@ -159,6 +91,32 @@ int sc_compute_signature(struct sc_card *card,
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
}
int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
int r;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
if (card->ops->set_security_env == NULL)
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
r = card->ops->set_security_env(card, env, se_num);
SC_FUNC_RETURN(card->ctx, 2, r);
}
int sc_restore_security_env(struct sc_card *card, int se_num)
{
int r;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
if (card->ops->restore_security_env == NULL)
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
r = card->ops->restore_security_env(card, se_num);
SC_FUNC_RETURN(card->ctx, 2, r);
}
int sc_verify(struct sc_card *card, unsigned int type, int ref,
const u8 *pin, size_t pinlen, int *tries_left)
{

View File

@ -1,5 +1,6 @@
# Process this file with automake to create Makefile.in
CC = ccmalloc gcc
INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@
LDFLAGS = @LDFLAGS@ @LIBOPENSC@

View File

@ -42,7 +42,7 @@ const char *option_help[] = { NULL };
const char *cmds[] = {
"ls", "cd", "debug", "cat", "info", "create", "delete",
"verify", "put", "get"
"verify", "put", "get", "mkdir"
};
const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]);
@ -376,12 +376,31 @@ int do_info(const char *arg)
return 0;
}
int create_file(const struct sc_file *file)
{
int r;
r = sc_create_file(card, file);
if (r) {
check_ret(r, SC_AC_OP_CREATE, "CREATE FILE failed", &current_file);
return -1;
}
/* Make sure we're back in the parent directory, because on some cards
* CREATE FILE also selects the newly created file. */
r = sc_select_file(card, &current_path, NULL);
if (r) {
printf("unable to select parent file: %s\n", sc_strerror(r));
die(1);
}
return 0;
}
int do_create(const char *arg, const char *arg2)
{
struct sc_path path;
struct sc_file file;
int size;
int i, r;
int i;
if (arg_to_path(arg, &path) != 0)
goto usage;
@ -397,24 +416,37 @@ int do_create(const char *arg, const char *arg2)
file.size = (size_t) size;
file.status = SC_FILE_STATUS_ACTIVATED;
r = sc_create_file(card, &file);
if (r) {
check_ret(r, SC_AC_OP_CREATE, "CREATE FILE failed", &current_file);
return -1;
}
/* Make sure we're back in the parent directory, because on some cards
* CREATE FILE also selects the newly created file. */
r = sc_select_file(card, &current_path, NULL);
if (r) {
printf("unable to select parent file: %s\n", sc_strerror(r));
die(1);
}
return 0;
return create_file(&file);
usage:
printf("Usage: create <file_id> <file_size>\n");
return -1;
}
int do_mkdir(const char *arg, const char *arg2)
{
struct sc_path path;
struct sc_file file;
size_t size;
int i;
if (arg_to_path(arg, &path) != 0)
goto usage;
if (sscanf(arg2, "%d", &size) != 1)
goto usage;
memset(&file, 0, sizeof(file));
file.id = (path.value[0] << 8) | path.value[1];
file.type = SC_FILE_TYPE_DF;
for (i = 0; i < SC_MAX_AC_OPS; i++)
file.acl[i] = SC_AC_NONE;
file.size = size;
file.status = SC_FILE_STATUS_ACTIVATED;
return create_file(&file);
usage:
printf("Usage: mkdir <file_id> <df_size>\n");
return -1;
}
int do_delete(const char *arg)
{
struct sc_path path;
@ -657,6 +689,8 @@ int handle_cmd(int cmd, const char *arg, const char *arg2)
return do_put(arg, arg2);
case 9:
return do_get(arg, arg2);
case 10:
return do_mkdir(arg, arg2);
default:
printf("Don't know how to handle command.\n");
}

View File

@ -1,5 +1,5 @@
/*
* opensc-crypt.c: Tool for cryptography operations with SmartCards
* pkcs15-crypt.c: Tool for cryptography operations with SmartCards
*
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
*
@ -198,7 +198,7 @@ int main(int argc, char * const argv[])
if (c == -1)
break;
if (c == '?')
print_usage_and_die("opensc-crypt");
print_usage_and_die("pkcs15-crypt");
switch (c) {
case 's':
do_sign++;
@ -236,7 +236,7 @@ int main(int argc, char * const argv[])
}
}
if (action_count == 0)
print_usage_and_die("opensc-crypt");
print_usage_and_die("pkcs15-crypt");
r = sc_establish_context(&ctx);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));