- 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:
parent
2d95b18b27
commit
20adb4b39c
2
THANKS
2
THANKS
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Process this file with automake to create Makefile.in
|
||||
|
||||
CC = ccmalloc gcc
|
||||
INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@
|
||||
LDFLAGS = @LDFLAGS@ @LIBOPENSC@
|
||||
|
||||
|
|
|
@ -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", ¤t_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, ¤t_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", ¤t_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, ¤t_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");
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue