Skip to content

Commit

Permalink
pkcs15: encode public key algorithm (issue 202)
Browse files Browse the repository at this point in the history
coding style: use linux style line break
  • Loading branch information
viktorTarasov committed Jan 13, 2014
1 parent 3d3592a commit 5437f87
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 75 deletions.
148 changes: 81 additions & 67 deletions src/libopensc/pkcs15-pubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
struct sc_asn1_entry asn1_rsa_pub_coefficients[C_ASN1_RSA_PUB_COEFFICIENTS_SIZE];
int r;

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coefficients, NULL, 0);

Expand All @@ -488,7 +489,7 @@ sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL);
LOG_TEST_RET(ctx, r, "ASN.1 parsing of public key failed");

return SC_SUCCESS;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}


Expand All @@ -500,6 +501,7 @@ sc_pkcs15_encode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
struct sc_asn1_entry asn1_rsa_pub_coefficients[C_ASN1_RSA_PUB_COEFFICIENTS_SIZE];
int r;

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coefficients, NULL, 1);

Expand All @@ -510,7 +512,7 @@ sc_pkcs15_encode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

return 0;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}


Expand All @@ -522,6 +524,7 @@ sc_pkcs15_decode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key,
struct sc_asn1_entry asn1_dsa_pub_coefficients[C_ASN1_DSA_PUB_COEFFICIENTS_SIZE];
int r;

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coefficients);

Expand All @@ -534,7 +537,7 @@ sc_pkcs15_decode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key,
r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL);
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");

return 0;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}


Expand All @@ -546,6 +549,7 @@ sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key,
struct sc_asn1_entry asn1_dsa_pub_coefficients[C_ASN1_DSA_PUB_COEFFICIENTS_SIZE];
int r;

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coefficients);

Expand All @@ -558,7 +562,7 @@ sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key,
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

return 0;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}


Expand All @@ -571,6 +575,7 @@ sc_pkcs15_decode_pubkey_gostr3410(sc_context_t *ctx, struct sc_pkcs15_pubkey_gos
struct sc_object_id param_key = {{ 1, 2, 643, 2, 2, 35, 1, -1}};
struct sc_object_id param_hash = {{ 1, 2, 643, 2, 2, 30, 1, -1}};

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_pub_coeff);
sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 0, &key->xy.data, &key->xy.len, 0);

Expand All @@ -580,7 +585,7 @@ sc_pkcs15_decode_pubkey_gostr3410(sc_context_t *ctx, struct sc_pkcs15_pubkey_gos
key->params.key = param_key;
key->params.hash = param_hash;

return 0;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}

int
Expand Down Expand Up @@ -614,6 +619,7 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx,
size_t ecpoint_len;
struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE];

LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ);
sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1);
r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL);
Expand All @@ -623,15 +629,15 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx,
sc_log(ctx, "decode-EC key=%p, buf=%p, buflen=%d", key, buf, buflen);

key->ecpointQ.len = ecpoint_len;
key->ecpointQ.value = ecpoint_data;
key->ecpointQ.value = ecpoint_data;

/* An uncompressed ecpoint is of the form 04||x||y
* The 04 indicates uncompressed
* x and y are same size, and field_length = sizeof(x) in bits. */
/* TODO: -DEE support more then uncompressed */
key->params.field_length = (ecpoint_len - 1)/2 * 8;

return r;
LOG_FUNC_RETURN(ctx, r);
}


Expand All @@ -649,7 +655,7 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key,
LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

sc_log(ctx, "EC key->ecpointQ=%p:%d *buf=%p:%d", key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen);
return 0;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}


Expand Down Expand Up @@ -681,64 +687,73 @@ static const struct sc_asn1_entry c_asn1_spki_key[] = {
{ NULL, 0, 0, 0, NULL, NULL }
};

/*
* Encode a pubkey as a SPKI, useful for pkcs15-tool, and for PKCS#15 files.
*/

/*
* Encode a pubkey as a SPKI, useful for pkcs15-tool, and for PKCS#15 files.
*/
int
sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubkey,
sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubkey,
u8 **buf, size_t *len)
{
int r;
struct sc_asn1_entry asn1_spki_key[2],
asn1_spki_key_items[3];
struct sc_pkcs15_u8 pkey;
struct sc_pkcs15_u8 pkey;
size_t key_len;

pkey.value = NULL;
pkey.len = 0;

switch (pubkey->algorithm) {
case SC_ALGORITHM_EC:
/*
* most keys, but not EC have only one encoding.
* For a SPKI, the ecpoint is placed directly in the
* BIT STRING
*/

key_len = pubkey->u.ec.ecpointQ.len * 8;
pkey.value = pubkey->u.ec.ecpointQ.value;
pkey.len = 0; /* flag as do not delete */
/* TODO make sure algorithm params are available*/
/* if not can we copy them from the u.ec */
r = 0;
break;
case SC_ALGORITHM_GOSTR3410:
/* TODO is this needed? does it cause mem leak? */
pubkey->alg_id->params = &pubkey->u.gostr3410.params;
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
break;
default:
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
break;
}

if (r == 0) {
sc_copy_asn1_entry(c_asn1_spki_key, asn1_spki_key);
sc_copy_asn1_entry(c_asn1_spki_key_items, asn1_spki_key_items);
sc_format_asn1_entry(asn1_spki_key + 0, asn1_spki_key_items, NULL, 1);
sc_format_asn1_entry(asn1_spki_key_items + 0, pubkey->alg_id, NULL, 1);
sc_format_asn1_entry(asn1_spki_key_items + 1, pkey.value, &key_len, 1);

r = sc_asn1_encode(ctx, asn1_spki_key, buf, len);
}

if (pkey.len && pkey.value)
free(pkey.value);

return r;
LOG_FUNC_CALLED(ctx);
pkey.value = NULL;
pkey.len = 0;

sc_log(ctx, "Encoding public key with algorithm %i", pubkey->algorithm);
if (!pubkey->alg_id) {
pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);

sc_init_oid(&pubkey->alg_id->oid);
pubkey->alg_id->algorithm = pubkey->algorithm;
}

switch (pubkey->algorithm) {
case SC_ALGORITHM_EC:
/*
* most keys, but not EC have only one encoding.
* For a SPKI, the ecpoint is placed directly in the
* BIT STRING
*/
key_len = pubkey->u.ec.ecpointQ.len * 8;
pkey.value = pubkey->u.ec.ecpointQ.value;
pkey.len = 0; /* flag as do not delete */
/* TODO make sure algorithm params are available*/
/* if not can we copy them from the u.ec */
r = 0;
break;
case SC_ALGORITHM_GOSTR3410:
/* TODO is this needed? does it cause mem leak? */
pubkey->alg_id->params = &pubkey->u.gostr3410.params;
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
break;
default:
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
break;
}

if (r == 0) {
sc_copy_asn1_entry(c_asn1_spki_key, asn1_spki_key);
sc_copy_asn1_entry(c_asn1_spki_key_items, asn1_spki_key_items);
sc_format_asn1_entry(asn1_spki_key + 0, asn1_spki_key_items, NULL, 1);
sc_format_asn1_entry(asn1_spki_key_items + 0, pubkey->alg_id, NULL, 1);
sc_format_asn1_entry(asn1_spki_key_items + 1, pkey.value, &key_len, 1);

r = sc_asn1_encode(ctx, asn1_spki_key, buf, len);
}

if (pkey.len && pkey.value)
free(pkey.value);

LOG_FUNC_RETURN(ctx, r);
}


Expand Down Expand Up @@ -766,16 +781,15 @@ int
sc_pkcs15_decode_pubkey_with_param(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
const u8 *buf, size_t len)
{
/* We assume all algrothims allow SPKI which starts with a sequence*/

if (*buf == 0x30) {
/* Decode Public Key from SPKI */
/* We assume all algrothims allow SPKI which starts with a sequence*/

if (*buf == 0x30)
/* Decode Public Key from SPKI */
return sc_pkcs15_copy_pubkey_from_spki_object(ctx, buf, len, key);
} else {
key->data.value = (u8 *)buf;
key->data.len = len;
return sc_pkcs15_decode_pubkey(ctx, key, buf, len);
}

key->data.value = (u8 *)buf;
key->data.len = len;
return sc_pkcs15_decode_pubkey(ctx, key, buf, len);
}


Expand Down
25 changes: 17 additions & 8 deletions src/pkcs15init/pkcs15-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,8 +1265,9 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15init_pubkeyargs pubkey_args;
struct sc_pkcs15_object *object;
struct sc_pkcs15_prkey_info *key_info;
struct sc_pkcs15_object *object = NULL;
struct sc_pkcs15_prkey_info *key_info = NULL;
struct sc_pkcs15_pubkey *pubkey = NULL;
int r, caller_supplied_id = 0;

LOG_FUNC_CALLED(ctx);
Expand Down Expand Up @@ -1333,16 +1334,25 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr
/* Caller not supplied ID, so,
* if intrinsic ID can be calculated -- overwrite the native one */
memset(&iid, 0, sizeof(iid));
r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY,
&iid, &pubkey_args.key);
r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &iid, &pubkey_args.key);
LOG_TEST_RET(ctx, r, "Select intrinsic ID error");

if (iid.len)
key_info->id = iid;
}

pubkey = &pubkey_args.key;
if (!pubkey->alg_id) {
pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);

sc_init_oid(&pubkey->alg_id->oid);
pubkey->alg_id->algorithm = pubkey->algorithm;
}

pubkey_args.id = key_info->id;
r = sc_pkcs15_encode_pubkey(ctx, &pubkey_args.key, &object->content.value, &object->content.len);
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &object->content.value, &object->content.len);
LOG_TEST_RET(ctx, r, "Failed to encode public key");

r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
Expand Down Expand Up @@ -1536,8 +1546,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
key_info->field_length = keybits;

/* Select a intrinsic Key ID if the user didn't specify one */
r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY,
&keyargs->id, &key);
r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, &key);
LOG_TEST_RET(ctx, r, "Get intrinsic ID error");

/* Select a Key ID if the user didn't specify one and there is no intrinsic ID,
Expand All @@ -1556,7 +1565,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,

/* DER encode public key components */
/* EC key are encoded as SPKI to preserve domain parameter */
r = sc_pkcs15_encode_pubkey_as_spki(p15card->card->ctx, &key, &object->content.value, &object->content.len);
r = sc_pkcs15_encode_pubkey_as_spki(p15card->card->ctx, &key, &object->content.value, &object->content.len);
LOG_TEST_RET(ctx, r, "Encode public key error");

/* Now create key file and store key */
Expand Down

0 comments on commit 5437f87

Please sign in to comment.