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; genkey_data->u.rsa.exponent_len = 3;
} }
else if (genkey_data->type == SC_ALGORITHM_GOSTR3410 && else if (genkey_data->type == SC_ALGORITHM_GOSTR3410 &&
genkey_data->u.gostr3410.x_len <= apdu.resplen && genkey_data->u.gostr3410.xy_len >= apdu.resplen)
genkey_data->u.gostr3410.x_len +
genkey_data->u.gostr3410.y_len >= apdu.resplen)
{ {
memcpy(genkey_data->u.gostr3410.x, apdu.resp, memcpy(genkey_data->u.gostr3410.xy, apdu.resp, apdu.resplen);
genkey_data->u.gostr3410.x_len); genkey_data->u.gostr3410.xy_len = apdu.resplen;
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);
} }
else else
r = SC_ERROR_BUFFER_TOO_SMALL; r = SC_ERROR_BUFFER_TOO_SMALL;

View File

@ -704,10 +704,8 @@ typedef struct sc_rtecp_genkey_data {
} rsa; } rsa;
struct struct
{ {
unsigned char *x; unsigned char *xy;
size_t x_len; size_t xy_len;
unsigned char *y;
size_t y_len;
} gostr3410; } gostr3410;
} u; } u;
} sc_rtecp_genkey_data_t; } 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); 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[] = { static const struct sc_asn1_entry c_asn1_pbkdf2_params[] = {
{ "salt", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL }, { "salt", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
{ "count", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 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 }, NULL },
#endif #endif
#ifdef SC_ALGORITHM_GOSTR3410 #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 #endif
/* We do not support PBES1 because the encryption is weak */ /* We do not support PBES1 because the encryption is weak */
#ifdef SC_ALGORITHM_PBKDF2 #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 }, { NULL, 0, 0, 0, NULL, NULL },
}; };
static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[3] = { static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[2] = {
{ "x", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC/*|SC_ASN1_UNSIGNED*/, NULL, NULL }, { "xy", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
{ "y", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC/*|SC_ASN1_UNSIGNED*/, NULL, NULL },
{ NULL, 0, 0, 0, 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, struct sc_pkcs15_pubkey_gostr3410 *key,
const u8 *buf, size_t buflen) const u8 *buf, size_t buflen)
{ {
struct sc_asn1_entry asn1_public_key[2]; struct sc_asn1_entry asn1_gostr3410_pub_coeff[2];
struct sc_asn1_entry asn1_gostr3410_coeff[3];
int r; int r;
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_pub_coeff);
sc_format_asn1_entry(asn1_public_key + 0, asn1_gostr3410_coeff, NULL, 0); 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); r = sc_asn1_decode(ctx, asn1_gostr3410_pub_coeff, buf, buflen, NULL, NULL);
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);
SC_TEST_RET(ctx, r, "ASN.1 parsing of public key failed"); SC_TEST_RET(ctx, r, "ASN.1 parsing of public key failed");
return 0; return 0;
@ -455,18 +449,13 @@ sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx,
struct sc_pkcs15_pubkey_gostr3410 *key, struct sc_pkcs15_pubkey_gostr3410 *key,
u8 **buf, size_t *buflen) u8 **buf, size_t *buflen)
{ {
struct sc_asn1_entry asn1_public_key[2]; struct sc_asn1_entry asn1_gostr3410_pub_coeff[2];
struct sc_asn1_entry asn1_gostr3410_pub_coeff[3];
int r; 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_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 + 0, key->xy.data, &key->xy.len, 1);
sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 1, key->y.data, &key->y.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"); SC_TEST_RET(ctx, r, "ASN.1 encoding failed");
return 0; return 0;
@ -716,10 +705,8 @@ void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
free(key->u.dsa.q.data); free(key->u.dsa.q.data);
break; break;
case SC_ALGORITHM_GOSTR3410: case SC_ALGORITHM_GOSTR3410:
if (key->u.gostr3410.x.data) if (key->u.gostr3410.xy.data)
free(key->u.gostr3410.x.data); free(key->u.gostr3410.xy.data);
if (key->u.gostr3410.y.data)
free(key->u.gostr3410.y.data);
break; break;
} }
if (key->data.value) if (key->data.value)

View File

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

View File

@ -19,6 +19,7 @@
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
#include <openssl/ec.h> #include <openssl/ec.h>
#endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_NO_EC */
#include <openssl/asn1.h>
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */ #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *); 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; EVP_PKEY_CTX *pkey_ctx;
EC_POINT *P; EC_POINT *P;
BIGNUM *X, *Y; BIGNUM *X, *Y;
ASN1_OCTET_STRING *octet;
const EC_GROUP *group = NULL; const EC_GROUP *group = NULL;
char paramset[2] = "A"; char paramset[2] = "A";
int r = -1, ret_vrf = 0; 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) if (r == 1 && EVP_PKEY_get0(pkey) != NULL)
group = EC_KEY_get0_group(EVP_PKEY_get0(pkey)); group = EC_KEY_get0_group(EVP_PKEY_get0(pkey));
r = -1; r = -1;
if (group && pubkey_len == 0x20 + 0x20 + 4 + 2) { if (group)
X = BN_bin2bn(pubkey + 4, 0x20, NULL); octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey, (long)pubkey_len);
Y = BN_bin2bn(pubkey + 4 + 2 + 0x20, 0x20, NULL); 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); P = EC_POINT_new(group);
if (P && X && Y) if (P && X && Y)
r = EC_POINT_set_affine_coordinates_GFp(group, 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; goto done;
else if (pubkey->algorithm == SC_ALGORITHM_DSA && !pubkey->u.dsa.pub.data) else if (pubkey->algorithm == SC_ALGORITHM_DSA && !pubkey->u.dsa.pub.data)
goto done; goto done;
else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 && else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 &&
(!pubkey->u.gostr3410.x.data || !pubkey->u.gostr3410.y.data)) !pubkey->u.gostr3410.xy.data)
goto done; goto done;
/* In Mozilla 'GOST R 34.10' is not yet supported. /* 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; break;
case SC_ALGORITHM_GOSTR3410: case SC_ALGORITHM_GOSTR3410:
assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE); assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE);
data.u.gostr3410.x_len = key_info->modulus_length / 8; data.u.gostr3410.xy_len = key_info->modulus_length / 8 * 2;
data.u.gostr3410.x = calloc(1, data.u.gostr3410.x_len); data.u.gostr3410.xy = calloc(1, data.u.gostr3410.xy_len);
data.u.gostr3410.y_len = key_info->modulus_length / 8; if (!data.u.gostr3410.xy)
data.u.gostr3410.y = calloc(1, data.u.gostr3410.y_len);
if (!data.u.gostr3410.x || !data.u.gostr3410.y)
{ {
free(data.u.gostr3410.x); free(data.u.gostr3410.xy);
free(data.u.gostr3410.y);
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY); SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
} }
break; 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; pubkey->u.rsa.exponent.len = data.u.rsa.exponent_len;
break; break;
case SC_ALGORITHM_GOSTR3410: case SC_ALGORITHM_GOSTR3410:
pubkey->u.gostr3410.x.data = data.u.gostr3410.x; pubkey->u.gostr3410.xy.data = data.u.gostr3410.xy;
pubkey->u.gostr3410.x.len = data.u.gostr3410.x_len; pubkey->u.gostr3410.xy.len = data.u.gostr3410.xy_len;
pubkey->u.gostr3410.y.data = data.u.gostr3410.y;
pubkey->u.gostr3410.y.len = data.u.gostr3410.y_len;
break; break;
} }
} }

View File

@ -2188,6 +2188,22 @@ static int do_convert_private_key(struct sc_pkcs15_prkey *key, EVP_PKEY *pk)
return 0; 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) static int do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk)
{ {
switch (pk->type) { 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), r = EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(eckey),
point, X, Y, NULL); point, X, Y, NULL);
if (r == 1) { if (r == 1) {
do_convert_bignum(&dst->x, X); dst->xy.len = BN_num_bytes(X) + BN_num_bytes(Y);
do_convert_bignum(&dst->y, Y); dst->xy.data = malloc(dst->xy.len);
key->algorithm = SC_ALGORITHM_GOSTR3410; 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(X);
BN_free(Y); BN_free(Y);