Merge [3804:3822/trunk]

git-svn-id: https://www.opensc-project.org/svnp/opensc/branches/martin/0.12@3824 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
martin 2009-11-13 09:45:21 +00:00
parent 36f26b6357
commit 3ea5bb7987
17 changed files with 925 additions and 524 deletions

File diff suppressed because it is too large Load Diff

View File

@ -97,7 +97,8 @@ static struct sc_card_driver rutoken_drv = {
};
static struct sc_atr_table rutoken_atrs[] = {
{ "3b:6f:00:ff:00:56:72:75:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL },
{ "3b:6f:00:ff:00:56:72:75:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL }, /* Aktiv Rutoken S */
{ "3b:6f:00:ff:00:56:75:61:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL }, /* Aktiv uaToken S */
{ NULL, NULL, NULL, 0, 0, NULL }
};
@ -162,7 +163,11 @@ static int rutoken_init(sc_card_t *card)
int ret;
SC_FUNC_CALLED(card->ctx, 1);
ret = token_init(card, "Rutoken card");
/* &rutoken_atrs[1] : { uaToken S ATR, NULL ATR } */
if (_sc_match_atr(card, &rutoken_atrs[1], &card->type) >= 0)
ret = token_init(card, "uaToken S card");
else
ret = token_init(card, "Rutoken S card");
SC_FUNC_RETURN(card->ctx, 1, ret);
}

View File

@ -164,6 +164,8 @@ sc_pkcs15_read_data_object
sc_pkcs15_read_file
sc_pkcs15_read_prkey
sc_pkcs15_read_pubkey
sc_pkcs15_pubkey_from_prvkey
sc_pkcs15_pubkey_from_cert
sc_pkcs15_remove_df
sc_pkcs15_remove_object
sc_pkcs15_remove_unusedspace

View File

@ -111,6 +111,12 @@ extern "C" {
#define SC_AC_OP_WRITE 3
/* rehab and invalidate are the same as in DF case */
/* Special 'Oberthur IdOne AuthentIC's case:
* re-use the existing DF ACLs that are not relevant to this card. */
#define SC_AC_OP_PIN_DEFINE SC_AC_OP_LOCK
#define SC_AC_OP_PIN_CHANGE SC_AC_OP_REHABILITATE
#define SC_AC_OP_PIN_RESET SC_AC_OP_DELETE_SELF
/* various maximum values */
#define SC_MAX_READER_DRIVERS 6
#define SC_MAX_READERS 16

View File

@ -26,6 +26,12 @@
#include <stdio.h>
#include <assert.h>
#ifdef ENABLE_OPENSSL
#include <openssl/evp.h>
#include <openssl/pem.h>
#endif
static const struct sc_asn1_entry c_asn1_com_key_attr[] = {
{ "iD", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
{ "usage", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
@ -36,7 +42,7 @@ static const struct sc_asn1_entry c_asn1_com_key_attr[] = {
};
static const struct sc_asn1_entry c_asn1_com_pubkey_attr[] = {
/* FIXME */
/* FIXME */
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -63,7 +69,7 @@ static const struct sc_asn1_entry c_asn1_dsa_type_attr[] = {
};
static const struct sc_asn1_entry c_asn1_gostr3410key_attr[] = {
{ "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "params_r3410", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "params_r3411", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "params_28147", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
@ -556,26 +562,168 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
return 0;
}
static int
sc_pkcs15_dup_bignum (struct sc_pkcs15_bignum *dst, struct sc_pkcs15_bignum *src)
{
assert(dst && src);
if (src->data && src->len) {
dst->data = calloc(1, src->len);
if (!dst->data)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(dst->data, src->data, src->len);
dst->len = src->len;
}
return 0;
}
int
sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx,
struct sc_pkcs15_prkey *prvkey, struct sc_pkcs15_pubkey **out)
{
struct sc_pkcs15_pubkey *pubkey;
int rv = SC_SUCCESS;
assert(prvkey && out);
*out = NULL;
pubkey = (struct sc_pkcs15_pubkey *) calloc(1, sizeof(struct sc_pkcs15_pubkey));
if (!pubkey)
return SC_ERROR_OUT_OF_MEMORY;
pubkey->algorithm = prvkey->algorithm;
switch (prvkey->algorithm) {
case SC_ALGORITHM_RSA:
rv = sc_pkcs15_dup_bignum(&pubkey->u.rsa.modulus, &prvkey->u.rsa.modulus);
if (!rv)
rv = sc_pkcs15_dup_bignum(&pubkey->u.rsa.exponent, &prvkey->u.rsa.exponent);
break;
case SC_ALGORITHM_DSA:
rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.pub, &prvkey->u.dsa.pub);
if (!rv)
rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.p, &prvkey->u.dsa.p);
if (!rv)
rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.q, &prvkey->u.dsa.q);
if (!rv)
rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.g, &prvkey->u.dsa.g);
break;
case SC_ALGORITHM_GOSTR3410:
break;
default:
sc_debug(ctx, "Unsupported private key algorithm");
return SC_ERROR_NOT_SUPPORTED;
}
if (rv)
sc_pkcs15_free_pubkey(pubkey);
else
*out = pubkey;
return SC_SUCCESS;
}
int
sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
{
#ifndef ENABLE_OPENSSL
SC_FUNC_RETURN(ctx, 1, SC_ERROR_NOT_SUPPORTED);
#else
EVP_PKEY *pkey = NULL;
X509 *x = NULL;
BIO *mem = NULL;
struct sc_pkcs15_pubkey *pubkey = NULL;
int rv = 0;
assert(cert_blob && out);
pubkey = (struct sc_pkcs15_pubkey *) calloc(1, sizeof(struct sc_pkcs15_pubkey));
if (!pubkey)
SC_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate pubkey");
pubkey->algorithm = SC_ALGORITHM_RSA;
do {
rv = SC_ERROR_INVALID_DATA;
mem = BIO_new_mem_buf(cert_blob->value, cert_blob->len);
if (!mem)
break;
x = d2i_X509_bio(mem, NULL);
if (!x)
break;
pkey=X509_get_pubkey(x);
if (!pkey || pkey->type != EVP_PKEY_RSA)
break;
pubkey->u.rsa.modulus.len = BN_num_bytes(pkey->pkey.rsa->n);
pubkey->u.rsa.modulus.data = calloc(1, pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = BN_num_bytes(pkey->pkey.rsa->e);
pubkey->u.rsa.exponent.data = calloc(1, pubkey->u.rsa.exponent.len);
rv = SC_ERROR_OUT_OF_MEMORY;
if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data)
break;
BN_bn2bin(pkey->pkey.rsa->n, pubkey->u.rsa.modulus.data);
BN_bn2bin(pkey->pkey.rsa->e, pubkey->u.rsa.exponent.data);
rv = SC_SUCCESS;
} while (0);
if (pkey)
EVP_PKEY_free(pkey);
if (x)
X509_free(x);
if (mem)
BIO_free(mem);
if (rv) {
sc_pkcs15_free_pubkey(pubkey);
pubkey = NULL;
}
*out = pubkey;
SC_FUNC_RETURN(ctx, 1, rv);
#endif
}
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
{
assert(key != NULL);
switch (key->algorithm) {
case SC_ALGORITHM_RSA:
free(key->u.rsa.modulus.data);
free(key->u.rsa.exponent.data);
if (key->u.rsa.modulus.data)
free(key->u.rsa.modulus.data);
if (key->u.rsa.exponent.data)
free(key->u.rsa.exponent.data);
break;
case SC_ALGORITHM_DSA:
free(key->u.dsa.pub.data);
free(key->u.dsa.g.data);
free(key->u.dsa.p.data);
free(key->u.dsa.q.data);
if (key->u.dsa.pub.data)
free(key->u.dsa.pub.data);
if (key->u.dsa.g.data)
free(key->u.dsa.g.data);
if (key->u.dsa.p.data)
free(key->u.dsa.p.data);
if (key->u.dsa.q.data)
free(key->u.dsa.q.data);
break;
case SC_ALGORITHM_GOSTR3410:
free(key->u.gostr3410.x.data);
free(key->u.gostr3410.y.data);
if (key->u.gostr3410.x.data)
free(key->u.gostr3410.x.data);
if (key->u.gostr3410.y.data)
free(key->u.gostr3410.y.data);
break;
}
free(key->data.value);
if (key->data.value)
free(key->data.value);
sc_mem_clear(key, sizeof(*key));
}

View File

@ -149,7 +149,7 @@ sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card)
}
}
}
if (builtin_enabled) {
else if (builtin_enabled) {
sc_debug(ctx, "no emulator list in config file, trying all builtin emulators\n");
for (i = 0; builtin_emulators[i].name; i++) {
sc_debug(ctx, "trying %s\n", builtin_emulators[i].name);

View File

@ -759,8 +759,8 @@ done:
if (strcmp(p15card->card->driver->short_name,"cardos") == 0) {
/* D-Trust cards (D-TRUST, D-SIGN) */
if (strstr(p15card->label,"D-TRUST") == 0
|| strstr(p15card->label,"D-SIGN") == 0) {
if (strstr(p15card->label,"D-TRUST") != NULL
|| strstr(p15card->label,"D-SIGN") != NULL) {
/* D-TRUST Card 2.0 2cc (standard cards, which always add
* SHA1 prefix itself */

View File

@ -434,12 +434,14 @@ typedef struct sc_pkcs15_card {
char *preferred_language;
} sc_pkcs15_card_t;
#define SC_PKCS15_CARD_FLAG_READONLY 0x01
#define SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED 0x02
#define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04
#define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08
#define SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT 0x10
#define SC_PKCS15_CARD_FLAG_EMULATED 0x20
#define SC_PKCS15_CARD_FLAG_READONLY 0x01
#define SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED 0x02
#define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04
#define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08
#define SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT 0x10
#define SC_PKCS15_CARD_FLAG_EMULATED 0x20
#define SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED 0x40
#define SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED 0x80
/* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object
* and initializes a new PKCS #15 card object. Will return
@ -475,16 +477,16 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
unsigned long alg_flags, const u8 *in,
size_t inlen, u8 *out, size_t outlen);
int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj,
struct sc_pkcs15_pubkey **out);
int sc_pkcs15_decode_pubkey_rsa(struct sc_context *ctx,
struct sc_pkcs15_pubkey_rsa *pubkey,
int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *,
struct sc_pkcs15_pubkey **);
int sc_pkcs15_decode_pubkey_rsa(struct sc_context *,
struct sc_pkcs15_pubkey_rsa *,
const u8 *, size_t);
int sc_pkcs15_encode_pubkey_rsa(struct sc_context *,
struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey_dsa(struct sc_context *ctx,
struct sc_pkcs15_pubkey_dsa *pubkey,
int sc_pkcs15_decode_pubkey_dsa(struct sc_context *,
struct sc_pkcs15_pubkey_dsa *,
const u8 *, size_t);
int sc_pkcs15_encode_pubkey_dsa(struct sc_context *,
struct sc_pkcs15_pubkey_dsa *, u8 **, size_t *);
@ -492,13 +494,16 @@ int sc_pkcs15_decode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, u8 **, size_t *);
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *pubkey);
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *pubkey);
int sc_pkcs15_read_prkey(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj,
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *);
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *);
int sc_pkcs15_pubkey_from_prvkey(struct sc_context *, struct sc_pkcs15_prkey *,
struct sc_pkcs15_pubkey **);
int sc_pkcs15_pubkey_from_cert(struct sc_context *, struct sc_pkcs15_der *,
struct sc_pkcs15_pubkey **);
int sc_pkcs15_read_prkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *,
const char *passphrase,
struct sc_pkcs15_prkey **out);
struct sc_pkcs15_prkey **);
int sc_pkcs15_decode_prkey(struct sc_context *,
struct sc_pkcs15_prkey *,
const u8 *, size_t);

View File

@ -1735,12 +1735,23 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
goto kpgen_done;
}
/* Write the new public and private keys to the pkcs15 files */
rc = sc_pkcs15init_store_private_key(p15card, profile,
&keygen_args.prkey_args, &priv_key_obj);
if (rc >= 0)
rc = sc_pkcs15init_store_public_key(p15card, profile,
&pub_args, &pub_key_obj);
/* Write the new public and private keys to the pkcs15 files */
/* To support smartcards that require different keybobjects for signing and encryption */
if (sc_pkcs15init_requires_restrictive_usage(p15card, &keygen_args.prkey_args, 0)) {
sc_debug(context, "store split key required for this card", rv);
/* second key is the signature keyobject */
rc = sc_pkcs15init_store_split_key(p15card, profile, &keygen_args.prkey_args, NULL, &priv_key_obj);
}
else {
rc = sc_pkcs15init_store_private_key(p15card, profile, &keygen_args.prkey_args, &priv_key_obj);
}
if (rc >= 0) {
/* copy ID from private key(s) here to avoid bad link between private and public key */
memcpy(&pub_args.id.value, &keygen_args.prkey_args.id.value, keygen_args.prkey_args.id.len);
pub_args.id.len = keygen_args.prkey_args.id.len;
rc = sc_pkcs15init_store_public_key(p15card, profile, &pub_args, &pub_key_obj);
}
if (rc < 0) {
sc_debug(context, "private/public keys not stored: %d\n", rc);
rv = sc_to_cryptoki_error(rc, p11card->reader);

View File

@ -53,8 +53,9 @@ filesystem {
DF OberthurAWP-AppDF {
ACL = *=NONE;
#ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78;
ACL = CREATE=CHV4, CRYPTO=NEVER;
#ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78;
ACL = CREATE=CHV4, CRYPTO=NEVER, PIN-DEFINE=CHV4, PIN-RESET=CHV4;
#ACL = CREATE=CHV4, CRYPTO=NEVER;
file-id = 5011;
size = 40;

View File

@ -175,6 +175,10 @@ struct sc_pkcs15init_operations {
};
/* Do not change these or reorder these */
#define SC_PKCS15INIT_ID_STYLE_NATIVE 0
#define SC_PKCS15INIT_ID_STYLE_MOZILLA 1
#define SC_PKCS15INIT_ID_STYLE_RFC2459 2
#define SC_PKCS15INIT_SO_PIN 0
#define SC_PKCS15INIT_SO_PUK 1
#define SC_PKCS15INIT_USER_PIN 2

View File

@ -119,6 +119,8 @@ static int check_key_compatibility(struct sc_pkcs15_card *,
static int prkey_fixup(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *);
static int prkey_bits(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *);
static int prkey_pkcs15_algo(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *);
static int select_intrinsic_id(sc_pkcs15_card_t *, struct sc_profile *,
int, sc_pkcs15_id_t *, void *);
static int select_id(sc_pkcs15_card_t *, int, sc_pkcs15_id_t *,
int (*)(const sc_pkcs15_object_t *, void *), void *,
sc_pkcs15_object_t **);
@ -1220,8 +1222,8 @@ sc_pkcs15init_init_prkdf(sc_pkcs15_card_t *p15card,
/* Split key; this ID exists already, don't check for
* the pkcs15 object */
} else {
/* Select a Key ID if the user didn't specify one, otherwise
* make sure it's compatible with our intended use */
/* Select a Key ID if the user didn't specify one,
* otherwise make sure it's compatible with our intended use */
r = select_id(p15card, SC_PKCS15_TYPE_PRKEY, &keyargs->id,
can_reuse_prkey_obj, object, res_obj);
if (r < 0)
@ -1302,7 +1304,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
struct sc_pkcs15init_pubkeyargs pubkey_args;
struct sc_pkcs15_object *object;
struct sc_pkcs15_prkey_info *key_info;
int r;
int r, caller_supplied_id = 0;
/* check supported key size */
r = check_key_size(p15card->card, keygen_args->prkey_args.key.algorithm, keybits);
@ -1328,6 +1330,8 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
if ((r = set_so_pin_from_card(p15card, profile)) < 0)
return r;
caller_supplied_id = keygen_args->prkey_args.id.len != 0;
/* Set up the PrKDF object */
r = sc_pkcs15init_init_prkdf(p15card, profile, &keygen_args->prkey_args,
&keygen_args->prkey_args.key, keybits, &object);
@ -1342,7 +1346,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
#if 0
pubkey_args.auth_id = keygen_args->prkey_args.auth_id;
#endif
pubkey_args.label = keygen_args->pubkey_label;
pubkey_args.label = keygen_args->pubkey_label ? keygen_args->pubkey_label : object->label;
pubkey_args.usage = keygen_args->prkey_args.usage;
pubkey_args.x509_usage = keygen_args->prkey_args.x509_usage;
pubkey_args.gost_params = keygen_args->prkey_args.gost_params;
@ -1368,8 +1372,23 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
/* update PrKDF entry */
if (r >= 0) {
r = sc_pkcs15init_add_object(p15card, profile,
SC_PKCS15_PRKDF, object);
if (!caller_supplied_id) {
struct sc_pkcs15_id iid;
/* Caller not supplied ID, so,
* if intrinsic ID can be calculated -- overwrite the native one */
memset(&iid, 0, sizeof(iid));
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &iid, &pubkey_args.key);
if (r < 0)
return r;
if (iid.len) {
key_info->id = iid;
pubkey_args.id = iid;
}
}
r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
}
if (r >= 0) {
@ -1439,6 +1458,11 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
if ((r = set_so_pin_from_card(p15card, profile)) < 0)
return r;
/* Select a intrinsic Key ID if user didn't specify one */
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PRKEY, &keyargs->id, &keyargs->key);
if (r < 0)
return r;
/* Set up the PrKDF object */
r = sc_pkcs15init_init_prkdf(p15card, profile, keyargs, &key, keybits, &object);
if (r < 0)
@ -1649,9 +1673,14 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
keyinfo_gostparams->gost28147 = keyargs->gost_params.gost28147;
}
/* Select a Key ID if the user didn't specify one, otherwise
* make sure it's unique */
*res_obj = NULL;
/* Select a intrinsic Key ID if the user didn't specify one */
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, &key);
if (r < 0)
return r;
/* Select a Key ID if the user didn't specify one and there is no intrinsic ID,
* otherwise make sure it's unique */
r = select_id(p15card, SC_PKCS15_TYPE_PUBKEY, &keyargs->id,
can_reuse_pubkey_obj, object, res_obj);
if (r < 0)
@ -1728,6 +1757,10 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
if ((r = set_so_pin_from_card(p15card, profile)) < 0)
return r;
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &args->id, &args->der_encoded);
if (r < 0)
return r;
/* Select an ID if the user didn't specify one, otherwise
* make sure it's unique */
if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id, NULL, NULL, NULL)) < 0)
@ -1992,7 +2025,7 @@ static size_t sc_pkcs15init_keybits(sc_pkcs15_bignum_t *bn)
if (!bn || !bn->len)
return 0;
bits = bn->len << 3;
for (mask = 0x80; !(bn->data[0] & mask); mask >>= 1)
for (mask = 0x80; mask && !(bn->data[0] & mask); mask >>= 1)
bits--;
return bits;
}
@ -2247,6 +2280,102 @@ find_df_by_type(struct sc_pkcs15_card *p15card, unsigned int type)
return df;
}
static int select_intrinsic_id(sc_pkcs15_card_t *p15card, struct sc_profile *profile,
int type, sc_pkcs15_id_t *id, void *data)
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_pubkey *pubkey = NULL;
unsigned id_style = profile->id_style;
int rv, allocated = 0;
SC_FUNC_CALLED(ctx, 1);
#ifndef ENABLE_OPENSSL
SC_FUNC_RETURN(ctx, 1, 0);
#else
/* ID already exists */
if (id->len)
SC_FUNC_RETURN(ctx, 1, 0);
/* Native ID style is not an intrisic one */
if (profile->id_style == SC_PKCS15INIT_ID_STYLE_NATIVE)
SC_FUNC_RETURN(ctx, 1, 0);
/* Get PKCS15 public key */
switch(type) {
case SC_PKCS15_TYPE_CERT_X509:
rv = sc_pkcs15_pubkey_from_cert(ctx, (struct sc_pkcs15_der *)data, &pubkey);
SC_TEST_RET(ctx, rv, "X509 parse error");
allocated = 1;
break;
case SC_PKCS15_TYPE_PRKEY:
rv = sc_pkcs15_pubkey_from_prvkey(ctx, (struct sc_pkcs15_prkey *)data, &pubkey);
SC_TEST_RET(ctx, rv, "Cannot get public key");
allocated = 1;
break;
case SC_PKCS15_TYPE_PUBKEY:
pubkey = (struct sc_pkcs15_pubkey *)data;
allocated = 0;
break;
default:
sc_debug(ctx, "Intrinsic ID is not implemented for the object type 0x%X\n", type);
SC_FUNC_RETURN(ctx, 1, 0);
}
/* Skip silently if key is not inintialized. */
if (pubkey->algorithm == SC_ALGORITHM_RSA && !pubkey->u.rsa.modulus.len)
goto done;
else if (pubkey->algorithm == SC_ALGORITHM_DSA && !pubkey->u.dsa.pub.data)
goto done;
else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 &&
(!pubkey->u.gostr3410.x.data || !pubkey->u.gostr3410.y.data))
goto done;
/* In Mozilla 'GOST R 34.10' is not yet supported.
* So, switch to the ID recommended by RFC2459 */
if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 && id_style == SC_PKCS15INIT_ID_STYLE_MOZILLA)
id_style = SC_PKCS15INIT_ID_STYLE_RFC2459;
if (id_style == SC_PKCS15INIT_ID_STYLE_MOZILLA) {
if (pubkey->algorithm == SC_ALGORITHM_RSA)
SHA1(pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len, id->value);
else if (pubkey->algorithm == SC_ALGORITHM_DSA)
SHA1(pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len, id->value);
else
goto done;
id->len = SHA_DIGEST_LENGTH;
}
else if (id_style == SC_PKCS15INIT_ID_STYLE_RFC2459) {
unsigned char *id_data = NULL;
size_t id_data_len = 0;
rv = sc_pkcs15_encode_pubkey(ctx, pubkey, &id_data, &id_data_len);
SC_TEST_RET(ctx, rv, "Encoding public key error");
if (!id_data || !id_data_len)
SC_TEST_RET(ctx, SC_ERROR_INTERNAL, "Encoding public key error");
SHA1(id_data, id_data_len, id->value);
id->len = SHA_DIGEST_LENGTH;
free(id_data);
}
else {
sc_debug(ctx, "Unsupported ID style: %i", profile->id_style);
SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non supported ID style");
}
done:
if (allocated)
sc_pkcs15_free_pubkey(pubkey);
SC_FUNC_RETURN(ctx, 1, id->len);
#endif
}
static int select_id(sc_pkcs15_card_t *p15card, int type, sc_pkcs15_id_t *id,
int (*can_reuse)(const sc_pkcs15_object_t *, void *),
void *data, sc_pkcs15_object_t **reuse_obj)

View File

@ -47,7 +47,7 @@
#define COSM_TITLE "OberthurAWP"
#define TLV_TYPE_V 0
#define TLV_TYPE_LV 1
#define TLV_TYPE_LV 1
#define TLV_TYPE_TLV 2
/* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */
@ -56,19 +56,133 @@
#define COSM_TYPE_PRKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PRKEY_RSA)
#define COSM_TYPE_PUBKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PUBKEY_RSA)
#define COSM_TOKEN_FLAG_PRN_GENERATION 0x01
#define COSM_TOKEN_FLAG_LOGIN_REQUIRED 0x04
#define COSM_TOKEN_FLAG_USER_PIN_INITIALIZED 0x08
#define COSM_TOKEN_FLAG_TOKEN_INITIALIZED 0x0400
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len);
static int cosm_create_reference_data(struct sc_profile *, struct sc_card *,
struct sc_pkcs15_pin_info *,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len);
static int cosm_update_pin(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *info, const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len);
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
sc_file_t *df);
int cosm_delete_file(struct sc_card *card, struct sc_profile *profile,
struct sc_file *df);
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
sc_file_t *df)
static int
cosm_write_tokeninfo (struct sc_card *card, struct sc_profile *profile,
char *label, unsigned p15_flags)
{
sc_path_t path;
sc_file_t *parent;
struct sc_file *file = NULL;
unsigned mask = SC_PKCS15_CARD_FLAG_PRN_GENERATION
| SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED
| SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED
| SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED;
int rv, sz, flags = 0;
char *buffer = NULL;
if (!card || !profile)
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "cosm_write_tokeninfo() label '%s'; flags 0x%X\n", label, p15_flags);
if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file))
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find "COSM_TITLE"-token-info");
if (file->size < 16)
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Unsufficient size of the "COSM_TITLE"-token-info file");
buffer = calloc(1, file->size);
if (!buffer)
SC_TEST_RET(card->ctx, SC_ERROR_MEMORY_FAILURE, "Allocation error in cosm_write_tokeninfo()");
if (label)
strncpy(buffer, label, file->size - 4);
else if (profile->p15_data && profile->p15_data->label)
snprintf(buffer, file->size - 4, profile->p15_data->label);
else if (profile->p15_spec && profile->p15_spec->label)
snprintf(buffer, file->size - 4, profile->p15_spec->label);
else
snprintf(buffer, file->size - 4, "OpenSC-Token");
sz = strlen(buffer);
if (sz < file->size - 4)
memset(buffer + sz, ' ', file->size - sz);
if (p15_flags & SC_PKCS15_CARD_FLAG_PRN_GENERATION)
flags |= COSM_TOKEN_FLAG_PRN_GENERATION;
if (p15_flags & SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED)
flags |= COSM_TOKEN_FLAG_LOGIN_REQUIRED;
if (p15_flags & SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED)
flags |= COSM_TOKEN_FLAG_USER_PIN_INITIALIZED;
if (p15_flags & SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED)
flags |= COSM_TOKEN_FLAG_TOKEN_INITIALIZED;
sc_debug(card->ctx, "cosm_write_tokeninfo() token label '%s'; oberthur flags 0x%X\n", buffer, flags);
memset(buffer + file->size - 4, 0, 4);
*(buffer + file->size - 1) = flags & 0xFF;
*(buffer + file->size - 2) = (flags >> 8) & 0xFF;
rv = sc_pkcs15init_update_file(profile, card, file, buffer, file->size);
if (rv > 0)
rv = 0;
if (profile->p15_data)
profile->p15_data->flags = (profile->p15_data->flags & ~mask) | p15_flags;
if (profile->p15_spec)
profile->p15_spec->flags = (profile->p15_spec->flags & ~mask) | p15_flags;
free(buffer);
SC_FUNC_RETURN(card->ctx, 1, rv);
}
static int
cosm_update_pukfile (struct sc_card *card, struct sc_profile *profile,
unsigned char *data, size_t data_len)
{
struct sc_pkcs15_pin_info profile_puk;
struct sc_file *file = NULL;
int rv, sz, flags = 0;
unsigned char buffer[16];
SC_FUNC_CALLED(card->ctx, 1);
if (!data || data_len > 16)
return SC_ERROR_INVALID_ARGUMENTS;
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_puk);
if (profile_puk.max_length > 16)
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Invalid PUK settings");
if (sc_profile_get_file(profile, COSM_TITLE"-puk-file", &file))
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find PUKFILE");
memset(buffer, profile_puk.pad_char, 16);
memcpy(buffer, data, data_len);
rv = sc_pkcs15init_update_file(profile, card, file, buffer, sizeof(buffer));
if (rv > 0)
rv = 0;
SC_FUNC_RETURN(card->ctx, 1, rv);
}
int
cosm_delete_file(struct sc_card *card, struct sc_profile *profile,
struct sc_file *df)
{
struct sc_path path;
struct sc_file *parent;
int rv = 0;
SC_FUNC_CALLED(card->ctx, 1);
@ -104,9 +218,10 @@ int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
/*
* Erase the card
*/
static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
static int
cosm_erase_card(struct sc_profile *profile, struct sc_card *card)
{
sc_file_t *df = profile->df_info->file, *dir;
struct sc_file *df = profile->df_info->file, *dir;
int rv;
SC_FUNC_CALLED(card->ctx, 1);
@ -150,6 +265,7 @@ static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
sc_file_free(dir);
}
sc_free_apps(card);
done:
sc_keycache_forget_key(NULL, -1, -1);
@ -164,14 +280,14 @@ done:
* Initialize the Application DF
*/
static int
cosm_init_app(struct sc_profile *profile, sc_card_t *card,
cosm_init_app(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pinfo,
const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len)
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
{
int rv;
struct sc_file *file = NULL;
size_t ii;
sc_file_t *file = NULL;
int rv;
static const char *create_dfs[] = {
COSM_TITLE"-AppDF",
"private-DF",
@ -192,7 +308,7 @@ cosm_init_app(struct sc_profile *profile, sc_card_t *card,
};
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "pin_len %i; puk_len %i\n", pin_len, puk_len);
sc_debug(card->ctx, "cosm_init_app() pin_len %i; puk_len %i\n", pin_len, puk_len);
/* Oberthur AWP file system is expected.*/
/* Create private objects DF */
@ -206,22 +322,43 @@ cosm_init_app(struct sc_profile *profile, sc_card_t *card,
sc_debug(card->ctx, "rv %i\n", rv);
sc_file_free(file);
if (rv && rv!=SC_ERROR_FILE_ALREADY_EXISTS)
SC_TEST_RET(card->ctx, rv, "sc_pkcs15init_create_file() failed");
SC_TEST_RET(card->ctx, rv, "cosm_init_app() sc_pkcs15init_create_file failed");
}
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
rv = cosm_write_tokeninfo(card, profile, NULL,
SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED | SC_PKCS15_CARD_FLAG_PRN_GENERATION);
if (pin && pin_len) {
/* Create local SOPIN */
struct sc_pkcs15_pin_info pin_info;
sc_profile_get_file(profile, COSM_TITLE"-AppDF", &file);
pin_info.flags = SC_PKCS15_PIN_FLAG_SO_PIN;
pin_info.reference = 4;
memcpy(&pin_info.path, &file->path, sizeof(pin_info.path));
sc_file_free(file);
rv = cosm_create_reference_data(profile, card, &pin_info, pin, pin_len, NULL, 0);
SC_TEST_RET(card->ctx, rv, "cosm_init_app() cosm_update_pin failed");
}
SC_FUNC_RETURN(card->ctx, 1, rv);
}
static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *card,
static int
cosm_create_reference_data(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pinfo,
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len )
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len )
{
int rv;
int puk_buff_len = 0;
unsigned char *puk_buff = NULL;
sc_pkcs15_pin_info_t profile_pin;
sc_pkcs15_pin_info_t profile_puk;
struct sc_pkcs15_pin_info profile_pin;
struct sc_pkcs15_pin_info profile_puk;
struct sc_cardctl_oberthur_createpin_info args;
unsigned char *puk_buff = NULL;
int rv, puk_buff_len = 0;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "pin lens %i/%i\n", pin_len, puk_len);
@ -233,9 +370,14 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car
rv = sc_select_file(card, &pinfo->path, NULL);
SC_TEST_RET(card->ctx, rv, "Cannot select file");
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin);
if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &profile_pin);
else
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin);
if (profile_pin.max_length > 0x100)
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCONSISTENT_PROFILE);
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Invalid (SO)PIN profile settings");
if (puk) {
int ii, jj;
@ -277,7 +419,13 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car
args.puk_len = puk_buff_len;
args.puk_tries = profile_puk.tries_left;
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args);
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args);
SC_TEST_RET(card->ctx, rv, "'CREATE_PIN' card specific command failed");
if (puk_buff_len == 16) {
rv = cosm_update_pukfile (card, profile, puk_buff, puk_buff_len);
SC_TEST_RET(card->ctx, rv, "Failed to update pukfile");
}
if (puk_buff)
free(puk_buff);
@ -288,46 +436,53 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car
/*
* Update PIN
*/
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
struct sc_pkcs15_pin_info *pinfo, const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len )
static int
cosm_update_pin(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pinfo, const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len )
{
int rv;
int tries_left = -1;
int rv, tries_left = -1;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags);
if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
sc_debug(card->ctx,"Pin references should be only in the profile"
"and in the card-oberthur.\n");
if (pinfo->reference != 4)
return SC_ERROR_INVALID_PIN_REFERENCE;
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "cosm_update_pin() invalid SOPIN reference");
rv = sc_change_reference_data(card, SC_AC_CHV, pinfo->reference, puk, puk_len,
pin, pin_len, &tries_left);
sc_debug(card->ctx, "return value %X; tries left %i\n", rv, tries_left);
if (tries_left != -1)
sc_debug(card->ctx, "Failed to change reference data for soPin: rv %X", rv);
SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to change SOPIN");
if (tries_left != -1)
SC_TEST_RET(card->ctx, SC_ERROR_INTERNAL, "cosm_update_pin() failed to change SOPIN");
}
else {
rv = cosm_create_reference_data(profile, card, pinfo,
pin, pin_len, puk, puk_len);
SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to change PIN");
rv = cosm_write_tokeninfo(card, profile, NULL,
SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED
| SC_PKCS15_CARD_FLAG_PRN_GENERATION
| SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED
| SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED);
SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to update tokeninfo");
}
SC_FUNC_RETURN(card->ctx, 1, rv);
}
static int
cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_pin_info_t *pin_info)
cosm_select_pin_reference(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pin_info)
{
sc_file_t *pinfile;
struct sc_file *pinfile;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "ref %i; flags %X\n", pin_info->reference, pin_info->flags);
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
return SC_ERROR_INCONSISTENT_PROFILE;
}
@ -337,37 +492,36 @@ cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
if (!pin_info->reference) {
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
pin_info->reference = 4;
pin_info->reference = 4;
else
pin_info->reference = 1;
pin_info->reference = 1;
}
if (pin_info->reference < 0 || pin_info->reference > 4)
if (pin_info->reference < 0 || pin_info->reference > 4)
return SC_ERROR_INVALID_PIN_REFERENCE;
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
}
/*
* Store a PIN
*/
static int
cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
sc_pkcs15_object_t *pin_obj,
cosm_create_pin(struct sc_profile *profile, struct sc_card *card, struct sc_file *df,
struct sc_pkcs15_object *pin_obj,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
{
sc_pkcs15_pin_info_t *pinfo = (sc_pkcs15_pin_info_t *) pin_obj->data;
sc_file_t *pinfile;
struct sc_pkcs15_pin_info *pinfo = (struct sc_pkcs15_pin_info *) pin_obj->data;
struct sc_file *pinfile;
int rv = 0, type;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags);
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
return SC_ERROR_INCONSISTENT_PROFILE;
}
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0)
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "\""COSM_TITLE"-AppDF\" not defined");
pinfo->path = pinfile->path;
sc_file_free(pinfile);
@ -375,23 +529,20 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
type = SC_PKCS15INIT_SO_PIN;
if (pinfo->reference != 4)
return SC_ERROR_INVALID_ARGUMENTS;
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid SOPIN reference");
}
else {
type = SC_PKCS15INIT_USER_PIN;
if (pinfo->reference !=1 && pinfo->reference != 2)
return SC_ERROR_INVALID_PIN_REFERENCE;
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid PIN reference");
}
if (pin && pin_len) {
rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len);
rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len);
SC_TEST_RET(card->ctx, rv, "Update PIN failed");
}
else {
sc_debug(card->ctx, "User PIN not updated");
}
sc_debug(card->ctx, "return %i\n", rv);
sc_keycache_set_pin_name(&pinfo->path, pinfo->reference, type);
pinfo->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
@ -403,15 +554,15 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
* Allocate a file
*/
static int
cosm_new_file(struct sc_profile *profile, sc_card_t *card,
unsigned int type, unsigned int num, sc_file_t **out)
cosm_new_file(struct sc_profile *profile, struct sc_card *card,
unsigned int type, unsigned int num, struct sc_file **out)
{
struct sc_file *file;
const char *_template = NULL, *desc = NULL;
unsigned int structure = 0xFFFFFFFF;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "type %X; num %i\n",type, num);
sc_debug(card->ctx, "cosm_new_file() type %X; num %i\n",type, num);
while (1) {
switch (type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
@ -457,20 +608,20 @@ cosm_new_file(struct sc_profile *profile, sc_card_t *card,
type &= SC_PKCS15_TYPE_CLASS_MASK;
}
sc_debug(card->ctx, "template %s; num %i\n",_template, num);
sc_debug(card->ctx, "cosm_new_file() template %s; num %i\n",_template, num);
if (sc_profile_get_file(profile, _template, &file) < 0) {
sc_debug(card->ctx, "Profile doesn't define %s template '%s'\n",
desc, _template);
return SC_ERROR_NOT_SUPPORTED;
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
}
file->id |= (num & 0xFF);
file->path.value[file->path.len-1] |= (num & 0xFF);
if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
file->ef_structure = structure;
}
sc_debug(card->ctx, "file size %i; ef type %i/%i; id %04X\n",file->size,
sc_debug(card->ctx, "cosm_new_file() file size %i; ef type %i/%i; id %04X\n",file->size,
file->type, file->ef_structure, file->id);
*out = file;
@ -482,9 +633,9 @@ cosm_new_file(struct sc_profile *profile, sc_card_t *card,
* RSA key generation
*/
static int
cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card,
unsigned int idx, unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey,
struct sc_pkcs15_pubkey *pubkey,
struct sc_pkcs15_prkey_info *info)
{
struct sc_cardctl_oberthur_genkey_info args;
@ -493,45 +644,37 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
int rv;
SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "index %i; nn %i\n", idx, keybits);
sc_debug(card->ctx, "cosm_generate_key() index %i; nn %i\n", idx, keybits);
if (keybits < 512 || keybits > 2048 || (keybits%0x20)) {
sc_debug(card->ctx, "Unsupported key size %u\n", keybits);
return SC_ERROR_INVALID_ARGUMENTS;
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size");
}
/* Get private key file from profile. */
if ((rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
&prkf)) < 0)
goto failed;
sc_debug(card->ctx, "prv ef type 0x%X\n",prkf->ef_structure);
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, &prkf);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() cannot allocate new file SC_PKCS15_TYPE_PRKEY_RSA");
prkf->size = keybits;
/* Access condition of private object DF. */
path = prkf->path;
path.len -= 2;
rv = sc_select_file(card, &path, &tmpf);
SC_TEST_RET(card->ctx, rv, "Generate RSA: no private object DF");
rv = sc_select_file(card, &path, &tmpf);
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() no private object DF");
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO);
sc_debug(card->ctx, "rv %i\n",rv);
if (rv < 0)
goto failed;
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CRYPTO) failed");
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE);
sc_debug(card->ctx, "rv %i\n",rv);
if (rv < 0)
goto failed;
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CREATE) failed");
sc_file_free(tmpf);
/* In the private key DF create the temporary public RSA file. */
sc_debug(card->ctx, "ready to create public key\n");
sc_debug(card->ctx, "cosm_generate_key() ready to create temporary public key\n");
sc_file_dup(&tmpf, prkf);
if (tmpf == NULL) {
rv = SC_ERROR_OUT_OF_MEMORY;
goto failed;
}
if (!tmpf)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot duplicate private key file");
tmpf->type = SC_FILE_TYPE_INTERNAL_EF;
tmpf->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
tmpf->id = 0x1012;
@ -539,18 +682,10 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
tmpf->path.value[tmpf->path.len - 1] = 0x12;
rv = sc_pkcs15init_create_file(profile, card, prkf);
sc_debug(card->ctx, "rv %i\n",rv);
if (rv) {
sc_debug(card->ctx, "prkf create file failed\n");
goto failed;
}
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create private key EF");
rv = sc_pkcs15init_create_file(profile, card, tmpf);
sc_debug(card->ctx, "rv %i\n",rv);
if (rv) {
sc_debug(card->ctx, "pubf create failed\n");
goto failed;
}
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create temporary public key EF");
memset(&args, 0, sizeof(args));
args.id_prv = prkf->id;
@ -559,49 +694,37 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
args.key_bits = keybits;
args.pubkey_len = keybits/8;
args.pubkey = (unsigned char *) malloc(keybits/8);
if (!args.pubkey) {
rv = SC_ERROR_OUT_OF_MEMORY;
goto failed;
}
if (!args.pubkey)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey");
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_GENERATE_KEY, &args);
if (rv < 0)
goto failed;
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() CARDCTL_OBERTHUR_GENERATE_KEY failed");
/* extract public key */
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = keybits / 8;
pubkey->u.rsa.modulus.data = (u8 *) malloc(keybits / 8);
if (!pubkey->u.rsa.modulus.data) {
rv = SC_ERROR_MEMORY_FAILURE;
goto failed;
}
pubkey->u.rsa.modulus.data = (unsigned char *) malloc(keybits / 8);
if (!pubkey->u.rsa.modulus.data)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf");
/* FIXME and if the exponent length is not 3? */
pubkey->u.rsa.exponent.len = 3;
pubkey->u.rsa.exponent.data = (u8 *) malloc(3);
if (!pubkey->u.rsa.exponent.data) {
rv = SC_ERROR_MEMORY_FAILURE;
goto failed;
}
pubkey->u.rsa.exponent.data = (unsigned char *) malloc(3);
if (!pubkey->u.rsa.exponent.data)
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate exponent buf");
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len);
info->key_reference = 1;
info->path = prkf->path;
if (rv) {
sc_debug(card->ctx, "rv %i\n", rv);
goto failed;
}
sc_debug(card->ctx, "cosm_generate_key() now delete temporary public key\n");
rv = cosm_delete_file(card, profile, tmpf);
sc_debug(card->ctx, "delete temporary public key\n");
if ((rv = cosm_delete_file(card, profile, tmpf)))
goto failed;
failed:
if (tmpf) sc_file_free(tmpf);
if (prkf) sc_file_free(prkf);
if (tmpf)
sc_file_free(tmpf);
if (prkf)
sc_file_free(prkf);
SC_FUNC_RETURN(card->ctx, 1, rv);
}
@ -611,7 +734,7 @@ failed:
* Store a private key
*/
static int
cosm_new_key(struct sc_profile *profile, sc_card_t *card,
cosm_new_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_prkey *key, unsigned int idx,
struct sc_pkcs15_prkey_info *info)
{
@ -652,7 +775,8 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card,
rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE);
SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation");
#ifdef ENABLE_OPENSSL
#ifdef ENABLE_OPENSSL
/* Mozilla style ID */
if (!info->id.len) {
SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value);
info->id.len = SHA_DIGEST_LENGTH;

View File

@ -21,7 +21,13 @@ pkcs15 {
# Put the DF length into the ODF file?
encode-df-length = no;
# Have a lastUpdate field in the EF(TokenInfo)?
do-last-update = yes;
do-last-update = yes;
# Method to calculate ID of the crypto objects
# mozilla: SHA1(modulus) for RSA, SHA1(pub) for DSA
# rfc2459: SHA1(SequenceASN1 of public key components as ASN1 integers)
# native: 'E' + number_of_present_objects_of_the_same_type
# default value: 'native'
# pkcs15-id-style = mozilla;
}
# Default settings.

View File

@ -104,7 +104,10 @@ static struct map fileOpNames[] = {
{ "UPDATE", SC_AC_OP_UPDATE },
{ "WRITE", SC_AC_OP_WRITE },
{ "ERASE", SC_AC_OP_ERASE },
{ "CRYPTO", SC_AC_OP_CRYPTO },
{ "CRYPTO", SC_AC_OP_CRYPTO },
{ "PIN-DEFINE", SC_AC_OP_PIN_DEFINE },
{ "PIN-CHANGE", SC_AC_OP_PIN_CHANGE },
{ "PIN-RESET", SC_AC_OP_PIN_RESET },
{ NULL, 0 }
};
static struct map fileTypeNames[] = {
@ -169,6 +172,12 @@ static struct map pinFlagNames[] = {
{ "exchangeRefData", 0x0800 },
{ NULL, 0 }
};
static struct map idStyleNames[] = {
{ "native", SC_PKCS15INIT_ID_STYLE_NATIVE },
{ "mozilla", SC_PKCS15INIT_ID_STYLE_MOZILLA },
{ "rfc2459", SC_PKCS15INIT_ID_STYLE_RFC2459 },
{ NULL, 0 }
};
static struct {
const char * name;
struct map * addr;
@ -280,6 +289,7 @@ sc_profile_new(void)
pro->pin_minlen = 4;
pro->pin_maxlen = 8;
pro->keep_public_key = 1;
pro->id_style = SC_PKCS15INIT_ID_STYLE_NATIVE;
return pro;
}
@ -780,6 +790,12 @@ do_encode_update_field(struct state *cur, int argc, char **argv)
return get_bool(cur, argv[0], &cur->profile->pkcs15.do_last_update);
}
static int
do_pkcs15_id_style(struct state *cur, int argc, char **argv)
{
return map_str2int(cur, argv[0], &cur->profile->id_style, idStyleNames);
}
/*
* Process an option block
*/
@ -1525,6 +1541,7 @@ static struct command p15_commands[] = {
{ "direct-certificates", 1, 1, do_direct_certificates },
{ "encode-df-length", 1, 1, do_encode_df_length },
{ "do-last-update", 1, 1, do_encode_update_field },
{ "pkcs15-id-style", 1, 1, do_pkcs15_id_style },
{ NULL, 0, 0, NULL }
};

View File

@ -120,6 +120,9 @@ struct sc_profile {
* needs to be updated (in other words: if the card content
* has been changed) */
int dirty;
/* PKCS15 object ID style */
unsigned int id_style;
};
struct sc_profile *sc_profile_new(void);

View File

@ -68,7 +68,7 @@ enum {
#endif
OPT_PIN,
OPT_NEWPIN,
OPT_PUK,
OPT_PUK
};
#define NELEMENTS(x) (sizeof(x)/sizeof((x)[0]))
@ -119,7 +119,9 @@ static const char *option_help[] = {
"Lists private keys",
"Lists public keys",
"Reads public key with ID <arg>",
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
"Reads public key with ID <arg>, outputs ssh format",
#endif
"Test if the card needs a security update",
"Update the card with a security update",
"Uses reader number <arg>",
@ -402,6 +404,7 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj)
{
unsigned int i;
struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data;
const char *types[] = { "", "RSA", "DSA", "GOSTR3410" };
const char *usages[] = {
"encrypt", "decrypt", "sign", "signRecover",
"wrap", "unwrap", "verify", "verifyRecover",
@ -414,13 +417,13 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj)
};
const unsigned int af_count = NELEMENTS(access_flags);
printf("Private RSA Key [%s]\n", obj->label);
printf("Private %s Key [%s]\n", types[3 & obj->type], obj->label);
printf("\tCom. Flags : %X\n", obj->flags);
printf("\tUsage : [0x%X]", prkey->usage);
for (i = 0; i < usage_count; i++)
if (prkey->usage & (1 << i)) {
printf(", %s", usages[i]);
}
if (prkey->usage & (1 << i)) {
printf(", %s", usages[i]);
}
printf("\n");
printf("\tAccess Flags: [0x%X]", prkey->access_flags);
for (i = 0; i < af_count; i++)
@ -440,9 +443,9 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj)
static int list_private_keys(void)
{
int r, i;
struct sc_pkcs15_object *objs[32];
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, objs, 32);
struct sc_pkcs15_object *objs[32];
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, objs, 32);
if (r < 0) {
fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r));
return 1;
@ -460,6 +463,7 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj)
{
unsigned int i;
const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data;
const char *types[] = { "", "RSA", "DSA", "GOSTR3410" };
const char *usages[] = {
"encrypt", "decrypt", "sign", "signRecover",
"wrap", "unwrap", "verify", "verifyRecover",
@ -472,7 +476,7 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj)
};
const unsigned int af_count = NELEMENTS(access_flags);
printf("Public RSA Key [%s]\n", obj->label);
printf("Public %s Key [%s]\n", types[3 & obj->type], obj->label);
printf("\tCom. Flags : %X\n", obj->flags);
printf("\tUsage : [0x%X]", pubkey->usage);
for (i = 0; i < usage_count; i++)
@ -498,8 +502,8 @@ static int list_public_keys(void)
{
int r, i;
struct sc_pkcs15_object *objs[32];
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PUBKEY_RSA, objs, 32);
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PUBKEY, objs, 32);
if (r < 0) {
fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
return 1;
@ -906,7 +910,7 @@ static void print_pin_info(const struct sc_pkcs15_object *obj)
(unsigned long)pin->stored_length);
printf("\tPad char : 0x%02X\n", pin->pad_char);
printf("\tReference : %d\n", pin->reference);
if (pin->type >= 0 && pin->type < sizeof(pin_types)/sizeof(pin_types[0]))
if (pin->type < sizeof(pin_types)/sizeof(pin_types[0]))
printf("\tType : %s\n", pin_types[pin->type]);
else
printf("\tType : [encoding %d]\n", pin->type);
@ -1146,7 +1150,7 @@ static int learn_card(void)
return 1;
}
cert_count = r;
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, NULL, 0);
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0);
if (r < 0) {
fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r));
return 1;
@ -1241,7 +1245,7 @@ static int test_update(sc_card_t *in_card)
}
{
int i=0;
size_t i=0;
while(i < rbuf[1]) {
if (rbuf[2+i] == 0x86) { /* found our buffer */
break;