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:
parent
5ba09f087b
commit
5320ca6fd1
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue