Corrected GOSTR3410 public key structure

Working now with GOST R 34.10:
$ pkcs15-init --store-private-key key --key-usage sign,decrypt --auth-id 2 --id 1 --pin "12345678"
$ pkcs15-init --store-certificate my_cert --id 1 --pin "12345678"

But have problem: no CKA_GOSTR3410_PARAMS by retrieve pub_key from certificate, if pub_key object was removed (see parse_x509_cert, asn1_decode_gostr3410_params)


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3859 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
s 2009-11-19 15:41:03 +00:00
parent 5ba09f087b
commit 5320ca6fd1
9 changed files with 107 additions and 63 deletions

View File

@ -683,19 +683,10 @@ static int rtecp_card_ctl(sc_card_t *card, unsigned long request, void *data)
genkey_data->u.rsa.exponent_len = 3;
}
else if (genkey_data->type == SC_ALGORITHM_GOSTR3410 &&
genkey_data->u.gostr3410.x_len <= apdu.resplen &&
genkey_data->u.gostr3410.x_len +
genkey_data->u.gostr3410.y_len >= apdu.resplen)
genkey_data->u.gostr3410.xy_len >= apdu.resplen)
{
memcpy(genkey_data->u.gostr3410.x, apdu.resp,
genkey_data->u.gostr3410.x_len);
memcpy(genkey_data->u.gostr3410.y, apdu.resp +
genkey_data->u.gostr3410.x_len,
genkey_data->u.gostr3410.y_len);
reverse(genkey_data->u.gostr3410.x,
genkey_data->u.gostr3410.x_len);
reverse(genkey_data->u.gostr3410.y,
genkey_data->u.gostr3410.y_len);
memcpy(genkey_data->u.gostr3410.xy, apdu.resp, apdu.resplen);
genkey_data->u.gostr3410.xy_len = apdu.resplen;
}
else
r = SC_ERROR_BUFFER_TOO_SMALL;

View File

@ -704,10 +704,8 @@ typedef struct sc_rtecp_genkey_data {
} rsa;
struct
{
unsigned char *x;
size_t x_len;
unsigned char *y;
size_t y_len;
unsigned char *xy;
size_t xy_len;
} gostr3410;
} u;
} sc_rtecp_genkey_data_t;

View File

@ -68,6 +68,48 @@ asn1_encode_des_params(sc_context_t *ctx, void *params,
return _sc_asn1_encode(ctx, asn1_des_iv, buf, buflen, depth + 1);
}
static const struct sc_asn1_entry c_asn1_gostr3410_params0[] = {
{ "GOSTR3410Params", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
static const struct sc_asn1_entry c_asn1_gostr3410_params[] = {
{ "key_params", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
{ "hash_params", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
{ "cipher_params", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
static int
asn1_decode_gostr3410_params(sc_context_t *ctx, void **paramp,
const u8 *buf, size_t buflen, int depth)
{
struct sc_asn1_entry asn1_gostr3410_params0[2], asn1_gostr3410_params[4];
struct sc_object_id keyp, hashp, cipherp;
int r;
sc_copy_asn1_entry(c_asn1_gostr3410_params0, asn1_gostr3410_params0);
sc_copy_asn1_entry(c_asn1_gostr3410_params, asn1_gostr3410_params);
sc_format_asn1_entry(asn1_gostr3410_params0 + 0, asn1_gostr3410_params, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410_params + 0, &keyp, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410_params + 1, &hashp, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410_params + 2, &cipherp, NULL, 0);
r = _sc_asn1_decode(ctx, asn1_gostr3410_params0, buf, buflen, NULL, NULL, 0, depth + 1);
/* TODO: store in paramp */
(void)paramp; /* no warning */
return r;
}
static int
asn1_encode_gostr3410_params(sc_context_t *ctx, void *params,
u8 **buf, size_t *buflen, int depth)
{
(void)ctx, (void)params, (void)buf, (void)buflen, (void)depth; /* no warning */
return SC_ERROR_NOT_IMPLEMENTED;
}
static const struct sc_asn1_entry c_asn1_pbkdf2_params[] = {
{ "salt", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
{ "count", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
@ -240,7 +282,10 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
NULL },
#endif
#ifdef SC_ALGORITHM_GOSTR3410
{ SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19 }}, NULL, NULL, NULL },
{ SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19 }},
asn1_decode_gostr3410_params,
asn1_encode_gostr3410_params,
NULL },
#endif
/* We do not support PBES1 because the encryption is weak */
#ifdef SC_ALGORITHM_PBKDF2

View File

@ -317,9 +317,8 @@ static struct sc_asn1_entry c_asn1_dsa_pub_coefficients[5] = {
{ NULL, 0, 0, 0, NULL, NULL },
};
static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[3] = {
{ "x", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC/*|SC_ASN1_UNSIGNED*/, NULL, NULL },
{ "y", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC/*|SC_ASN1_UNSIGNED*/, NULL, NULL },
static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[2] = {
{ "xy", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -433,18 +432,13 @@ sc_pkcs15_decode_pubkey_gostr3410(sc_context_t *ctx,
struct sc_pkcs15_pubkey_gostr3410 *key,
const u8 *buf, size_t buflen)
{
struct sc_asn1_entry asn1_public_key[2];
struct sc_asn1_entry asn1_gostr3410_coeff[3];
struct sc_asn1_entry asn1_gostr3410_pub_coeff[2];
int r;
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_gostr3410_coeff, NULL, 0);
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);
sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_coeff);
sc_format_asn1_entry(asn1_gostr3410_coeff + 0, &key->x.data, &key->x.len, 0);
sc_format_asn1_entry(asn1_gostr3410_coeff + 1, &key->y.data, &key->y.len, 0);
r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL);
r = sc_asn1_decode(ctx, asn1_gostr3410_pub_coeff, buf, buflen, NULL, NULL);
SC_TEST_RET(ctx, r, "ASN.1 parsing of public key failed");
return 0;
@ -455,18 +449,13 @@ sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx,
struct sc_pkcs15_pubkey_gostr3410 *key,
u8 **buf, size_t *buflen)
{
struct sc_asn1_entry asn1_public_key[2];
struct sc_asn1_entry asn1_gostr3410_pub_coeff[3];
struct sc_asn1_entry asn1_gostr3410_pub_coeff[2];
int r;
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_gostr3410_pub_coeff, NULL, 1);
sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_pub_coeff);
sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 0, key->x.data, &key->x.len, 1);
sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 1, key->y.data, &key->y.len, 1);
sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 0, key->xy.data, &key->xy.len, 1);
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
r = sc_asn1_encode(ctx, asn1_gostr3410_pub_coeff, buf, buflen);
SC_TEST_RET(ctx, r, "ASN.1 encoding failed");
return 0;
@ -716,10 +705,8 @@ void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
free(key->u.dsa.q.data);
break;
case SC_ALGORITHM_GOSTR3410:
if (key->u.gostr3410.x.data)
free(key->u.gostr3410.x.data);
if (key->u.gostr3410.y.data)
free(key->u.gostr3410.y.data);
if (key->u.gostr3410.xy.data)
free(key->u.gostr3410.xy.data);
break;
}
if (key->data.value)

View File

@ -144,8 +144,7 @@ struct sc_pkcs15_prkey_dsa {
};
struct sc_pkcs15_pubkey_gostr3410 {
sc_pkcs15_bignum_t x;
sc_pkcs15_bignum_t y;
sc_pkcs15_bignum_t xy;
};
struct sc_pkcs15_prkey_gostr3410 {

View File

@ -19,6 +19,7 @@
#ifndef OPENSSL_NO_EC
#include <openssl/ec.h>
#endif /* OPENSSL_NO_EC */
#include <openssl/asn1.h>
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *);
@ -274,6 +275,7 @@ static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len,
EVP_PKEY_CTX *pkey_ctx;
EC_POINT *P;
BIGNUM *X, *Y;
ASN1_OCTET_STRING *octet;
const EC_GROUP *group = NULL;
char paramset[2] = "A";
int r = -1, ret_vrf = 0;
@ -303,10 +305,14 @@ static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len,
if (r == 1 && EVP_PKEY_get0(pkey) != NULL)
group = EC_KEY_get0_group(EVP_PKEY_get0(pkey));
r = -1;
if (group && pubkey_len == 0x20 + 0x20 + 4 + 2) {
X = BN_bin2bn(pubkey + 4, 0x20, NULL);
Y = BN_bin2bn(pubkey + 4 + 2 + 0x20, 0x20, NULL);
if (group)
octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey, (long)pubkey_len);
if (group && octet) {
reverse(octet->data, octet->length);
Y = BN_bin2bn(octet->data, octet->length / 2, NULL);
X = BN_bin2bn((const unsigned char*)octet->data +
octet->length / 2, octet->length / 2, NULL);
ASN1_OCTET_STRING_free(octet);
P = EC_POINT_new(group);
if (P && X && Y)
r = EC_POINT_set_affine_coordinates_GFp(group,

View File

@ -2329,8 +2329,8 @@ static int select_intrinsic_id(sc_pkcs15_card_t *p15card, struct sc_profile *pro
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))
else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 &&
!pubkey->u.gostr3410.xy.data)
goto done;
/* In Mozilla 'GOST R 34.10' is not yet supported.

View File

@ -532,14 +532,11 @@ static int rtecp_generate_key(sc_profile_t *profile, sc_card_t *card,
break;
case SC_ALGORITHM_GOSTR3410:
assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE);
data.u.gostr3410.x_len = key_info->modulus_length / 8;
data.u.gostr3410.x = calloc(1, data.u.gostr3410.x_len);
data.u.gostr3410.y_len = key_info->modulus_length / 8;
data.u.gostr3410.y = calloc(1, data.u.gostr3410.y_len);
if (!data.u.gostr3410.x || !data.u.gostr3410.y)
data.u.gostr3410.xy_len = key_info->modulus_length / 8 * 2;
data.u.gostr3410.xy = calloc(1, data.u.gostr3410.xy_len);
if (!data.u.gostr3410.xy)
{
free(data.u.gostr3410.x);
free(data.u.gostr3410.y);
free(data.u.gostr3410.xy);
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
}
break;
@ -560,10 +557,8 @@ static int rtecp_generate_key(sc_profile_t *profile, sc_card_t *card,
pubkey->u.rsa.exponent.len = data.u.rsa.exponent_len;
break;
case SC_ALGORITHM_GOSTR3410:
pubkey->u.gostr3410.x.data = data.u.gostr3410.x;
pubkey->u.gostr3410.x.len = data.u.gostr3410.x_len;
pubkey->u.gostr3410.y.data = data.u.gostr3410.y;
pubkey->u.gostr3410.y.len = data.u.gostr3410.y_len;
pubkey->u.gostr3410.xy.data = data.u.gostr3410.xy;
pubkey->u.gostr3410.xy.len = data.u.gostr3410.xy_len;
break;
}
}

View File

@ -2188,6 +2188,22 @@ static int do_convert_private_key(struct sc_pkcs15_prkey *key, EVP_PKEY *pk)
return 0;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC)
static void reverse(unsigned char *buf, size_t len)
{
unsigned char tmp;
size_t i;
assert(buf || len == 0);
for (i = 0; i < len / 2; ++i)
{
tmp = buf[i];
buf[i] = buf[len - 1 - i];
buf[len - 1 - i] = tmp;
}
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */
static int do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk)
{
switch (pk->type) {
@ -2232,9 +2248,16 @@ static int do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk)
r = EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(eckey),
point, X, Y, NULL);
if (r == 1) {
do_convert_bignum(&dst->x, X);
do_convert_bignum(&dst->y, Y);
key->algorithm = SC_ALGORITHM_GOSTR3410;
dst->xy.len = BN_num_bytes(X) + BN_num_bytes(Y);
dst->xy.data = malloc(dst->xy.len);
if (dst->xy.data) {
BN_bn2bin(Y, dst->xy.data);
BN_bn2bin(X, dst->xy.data + BN_num_bytes(Y));
reverse(dst->xy.data, dst->xy.len);
key->algorithm = SC_ALGORITHM_GOSTR3410;
}
else
r = -1;
}
BN_free(X);
BN_free(Y);