add GOST R 34.10-2001 algorithm (only PKCS#11) by Aktiv Co.

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3757 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
s 2009-10-05 18:40:51 +00:00
parent 45e12e6ff5
commit 97a8f73b9c
17 changed files with 930 additions and 157 deletions

View File

@ -53,6 +53,7 @@ static int rtecp_match_card(sc_card_t *card)
static int rtecp_init(sc_card_t *card)
{
sc_algorithm_info_t info;
unsigned long flags;
assert(card && card->ctx);
@ -72,6 +73,13 @@ static int rtecp_init(sc_card_t *card)
_sc_card_add_rsa_alg(card, 1792, flags, 0);
_sc_card_add_rsa_alg(card, 2048, flags, 0);
memset(&info, 0, sizeof(info));
info.algorithm = SC_ALGORITHM_GOSTR3410;
info.key_length = 256;
info.flags = SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN
| SC_ALGORITHM_GOSTR3410_HASH_NONE;
_sc_card_add_algorithm(card, &info);
SC_FUNC_RETURN(card->ctx, 2, 0);
}
@ -375,7 +383,7 @@ static int rtecp_logout(sc_card_t *card)
SC_FUNC_RETURN(card->ctx, 2, r);
}
static int rtecp_rsa_cipher(sc_card_t *card, const u8 *data, size_t data_len,
static int rtecp_cipher(sc_card_t *card, const u8 *data, size_t data_len,
u8 *out, size_t out_len, int sign)
{
sc_apdu_t apdu;
@ -384,7 +392,7 @@ static int rtecp_rsa_cipher(sc_card_t *card, const u8 *data, size_t data_len,
int r;
assert(card && card->ctx && data && out);
buf_out = malloc(data_len + 2);
buf_out = malloc(out_len + 2);
buf = malloc(data_len);
if (!buf || !buf_out)
{
@ -405,8 +413,8 @@ static int rtecp_rsa_cipher(sc_card_t *card, const u8 *data, size_t data_len,
apdu.datalen = data_len;
apdu.sensitive = 1;
apdu.resp = buf_out;
apdu.resplen = data_len + 2;
apdu.le = data_len;
apdu.resplen = out_len + 2;
apdu.le = out_len;
if (apdu.lc > 255)
apdu.flags |= SC_APDU_FLAGS_CHAINING;
r = sc_transmit_apdu(card, &apdu);
@ -424,8 +432,8 @@ static int rtecp_rsa_cipher(sc_card_t *card, const u8 *data, size_t data_len,
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
{
assert(buf_out);
for (i = 0; i < out_len && i < data_len && i < apdu.resplen; ++i)
out[i] = buf_out[data_len - 1 - i];
for (i = 0; i < out_len && i < apdu.resplen; ++i)
out[i] = buf_out[out_len - 1 - i];
r = (i > 0) ? (int)i : SC_ERROR_INTERNAL;
}
else
@ -434,7 +442,7 @@ static int rtecp_rsa_cipher(sc_card_t *card, const u8 *data, size_t data_len,
if (!sign)
{
assert(buf_out);
sc_mem_clear(buf_out, data_len + 2);
sc_mem_clear(buf_out, out_len + 2);
}
assert(buf_out);
free(buf_out);
@ -449,7 +457,7 @@ static int rtecp_decipher(sc_card_t *card,
assert(card && card->ctx && data && out);
/* decipher */
r = rtecp_rsa_cipher(card, data, data_len, out, out_len, 0);
r = rtecp_cipher(card, data, data_len, out, out_len, 0);
SC_FUNC_RETURN(card->ctx, 3, r);
}
@ -460,7 +468,7 @@ static int rtecp_compute_signature(sc_card_t *card,
assert(card && card->ctx && data && out);
/* compute digital signature */
r = rtecp_rsa_cipher(card, data, data_len, out, out_len, 1);
r = rtecp_cipher(card, data, data_len, out, out_len, 1);
SC_FUNC_RETURN(card->ctx, 2, r);
}
@ -666,14 +674,31 @@ static int rtecp_card_ctl(sc_card_t *card, unsigned long request, void *data)
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (!r && request == SC_CARDCTL_RTECP_GENERATE_KEY)
{
if (genkey_data->modulus_len >= apdu.resplen &&
genkey_data->exponent_len >= 3)
if (genkey_data->type == SC_ALGORITHM_RSA &&
genkey_data->u.rsa.modulus_len >= apdu.resplen &&
genkey_data->u.rsa.exponent_len >= 3)
{
memcpy(genkey_data->modulus, apdu.resp, apdu.resplen);
genkey_data->modulus_len = apdu.resplen;
reverse(genkey_data->modulus, genkey_data->modulus_len);
memcpy(genkey_data->exponent, "\x01\x00\x01", 3);
genkey_data->exponent_len = 3;
memcpy(genkey_data->u.rsa.modulus, apdu.resp, apdu.resplen);
genkey_data->u.rsa.modulus_len = apdu.resplen;
reverse(genkey_data->u.rsa.modulus,
genkey_data->u.rsa.modulus_len);
memcpy(genkey_data->u.rsa.exponent, "\x01\x00\x01", 3);
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)
{
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);
}
else
r = SC_ERROR_BUFFER_TOO_SMALL;

View File

@ -691,11 +691,25 @@ typedef struct sc_entersafe_gen_key_data_st {
* Rutoken ECP stuff
*/
typedef struct sc_rtecp_genkey_data {
unsigned int type;
unsigned int key_id;
unsigned char *exponent;
size_t exponent_len;
unsigned char *modulus;
size_t modulus_len;
union
{
struct
{
unsigned char *exponent;
size_t exponent_len;
unsigned char *modulus;
size_t modulus_len;
} rsa;
struct
{
unsigned char *x;
size_t x_len;
unsigned char *y;
size_t y_len;
} gostr3410;
} u;
} sc_rtecp_genkey_data_t;
/*

View File

@ -109,6 +109,7 @@ sc_pkcs15_decode_prkey
sc_pkcs15_decode_pubkey
sc_pkcs15_decode_pubkey_dsa
sc_pkcs15_decode_pubkey_rsa
sc_pkcs15_decode_pubkey_gostr3410
sc_pkcs15_decode_pukdf_entry
sc_pkcs15_encode_aodf_entry
sc_pkcs15_encode_cdf_entry
@ -121,6 +122,7 @@ sc_pkcs15_encode_prkey
sc_pkcs15_encode_pubkey
sc_pkcs15_encode_pubkey_dsa
sc_pkcs15_encode_pubkey_rsa
sc_pkcs15_encode_pubkey_gostr3410
sc_pkcs15_encode_pukdf_entry
sc_pkcs15_encode_tokeninfo
sc_pkcs15_encode_unusedspace

View File

@ -147,6 +147,7 @@ extern "C" {
#define SC_ALGORITHM_RSA 0
#define SC_ALGORITHM_DSA 1
#define SC_ALGORITHM_EC 2
#define SC_ALGORITHM_GOSTR3410 3
/* Symmetric algorithms */
#define SC_ALGORITHM_DES 64
@ -156,7 +157,11 @@ extern "C" {
/* Hash algorithms */
#define SC_ALGORITHM_MD5 128
#define SC_ALGORITHM_SHA1 129
#define SC_ALGORITHM_GOSTR3411 130
/* FIXME: */
/*
#define SC_ALGORITHM_GOSTHASH 130
*/
/* Key derivation algorithms */
#define SC_ALGORITHM_PBKDF2 192
@ -190,6 +195,12 @@ extern "C" {
#define SC_ALGORITHM_RSA_HASH_SHA224 0x00001000
#define SC_ALGORITHM_RSA_HASHES 0x00001FE0
#define SC_ALGORITHM_GOSTR3410_RAW 0x00002000
#define SC_ALGORITHM_GOSTR3410_HASH_NONE 0x00004000
#define SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411 0x00008000
#define SC_ALGORITHM_GOSTR3410_HASHES 0x00008000
/* FIXME: */
#define SC_ALGORITHM_GOST_CRYPT_PZ 0x0
#define SC_ALGORITHM_GOST_CRYPT_GAMM 0x1
#define SC_ALGORITHM_GOST_CRYPT_GAMMOS 0x2

View File

@ -239,6 +239,9 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
NULL,
NULL },
#endif
#ifdef SC_ALGORITHM_GOSTR3410
{ SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19 }}, NULL, NULL, NULL },
#endif
/* We do not support PBES1 because the encryption is weak */
#ifdef SC_ALGORITHM_PBKDF2
{ SC_ALGORITHM_PBKDF2, {{ 1, 2, 840, 113549, 1, 5, 12 }},

View File

@ -52,6 +52,19 @@ static const struct sc_asn1_entry c_asn1_prk_rsa_attr[] = {
{ NULL, 0, 0, 0, NULL, NULL }
};
static const struct sc_asn1_entry c_asn1_gostr3410key_attr[] = {
{ "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 },
{ NULL, 0, 0, 0, NULL, NULL }
};
static const struct sc_asn1_entry c_asn1_prk_gostr3410_attr[] = {
{ "privateGOSTR3410KeyAttributes", 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_dsakey_i_p_attr[] = {
{ "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
@ -76,8 +89,9 @@ static const struct sc_asn1_entry c_asn1_prk_dsa_attr[] = {
static const struct sc_asn1_entry c_asn1_prkey[] = {
{ "privateRSAKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "privateDSAKey", SC_ASN1_PKCS15_OBJECT, 2 | SC_ASN1_CTX | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "privateGOSTR3410Key", SC_ASN1_PKCS15_OBJECT, 3 | SC_ASN1_CTX | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
};
int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
@ -85,7 +99,8 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
{
sc_context_t *ctx = p15card->card->ctx;
struct sc_pkcs15_prkey_info info;
int r;
int r, gostr3410_params[3];
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
size_t usage_len = sizeof(info.usage);
size_t af_len = sizeof(info.access_flags);
struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[1];
@ -93,30 +108,37 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2],
asn1_dsakey_i_p_attr[2],
asn1_dsakey_value_attr[3];
struct sc_asn1_entry asn1_prkey[3];
struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_prk_gostr3410_attr[2];
struct sc_asn1_entry asn1_prkey[4];
struct sc_asn1_pkcs15_object rsa_prkey_obj = { obj, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_prk_rsa_attr };
struct sc_asn1_pkcs15_object dsa_prkey_obj = { obj, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_prk_dsa_attr };
struct sc_asn1_pkcs15_object gostr3410_prkey_obj = { obj, asn1_com_key_attr,
asn1_com_prkey_attr,
asn1_prk_gostr3410_attr };
sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);
sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);
sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr);
sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr,
asn1_dsakey_i_p_attr);
sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr);
sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr);
sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 0);
sc_format_asn1_entry(asn1_prkey + 1, &dsa_prkey_obj, NULL, 0);
sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 0);
sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 0);
sc_format_asn1_entry(asn1_prk_dsa_attr + 0, asn1_dsakey_attr, NULL, 0);
sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 0);
sc_format_asn1_entry(asn1_rsakey_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0);
@ -126,6 +148,10 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
sc_format_asn1_entry(asn1_dsakey_value_attr + 1, asn1_dsakey_i_p_attr, NULL, 0);
sc_format_asn1_entry(asn1_dsakey_i_p_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &gostr3410_params[0], NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &gostr3410_params[1], NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &gostr3410_params[2], NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0);
@ -137,6 +163,7 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
memset(&info, 0, sizeof(info));
info.key_reference = -1;
info.native = 1;
memset(gostr3410_params, 0, sizeof(gostr3410_params));
r = sc_asn1_decode_choice(ctx, asn1_prkey, *buf, *buflen, buf, buflen);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
@ -149,16 +176,36 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
/* If the value was indirect-protected, mark the path */
if (asn1_dsakey_i_p_attr[0].flags & SC_ASN1_PRESENT)
info.path.type = SC_PATH_TYPE_PATH_PROT;
} else if (asn1_prkey[2].flags & SC_ASN1_PRESENT) {
obj->type = SC_PKCS15_TYPE_PRKEY_GOSTR3410;
assert(info.modulus_length == 0);
info.modulus_length = SC_PKCS15_GOSTR3410_KEYSIZE;
assert(info.params_len == 0);
info.params_len = sizeof(struct sc_pkcs15_keyinfo_gostparams);
info.params = malloc(info.params_len);
if (info.params == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
assert(sizeof(*keyinfo_gostparams) == info.params_len);
keyinfo_gostparams = info.params;
keyinfo_gostparams->gostr3410 = gostr3410_params[0];
keyinfo_gostparams->gostr3411 = gostr3410_params[1];
keyinfo_gostparams->gost28147 = gostr3410_params[2];
} else {
sc_error(ctx, "Neither RSA or DSA key in PrKDF entry.\n");
sc_error(ctx, "Neither RSA or DSA or GOSTR3410 key in PrKDF entry.\n");
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INVALID_ASN1_OBJECT);
}
r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
if (r < 0)
if (r < 0) {
if (info.params)
free(info.params);
return r;
}
obj->data = malloc(sizeof(info));
if (obj->data == NULL)
if (obj->data == NULL) {
if (info.params)
free(info.params);
SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(obj->data, &info, sizeof(info));
return 0;
@ -173,27 +220,34 @@ int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2],
asn1_dsakey_value_attr[3],
asn1_dsakey_i_p_attr[2];
struct sc_asn1_entry asn1_prkey[3];
struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_prk_gostr3410_attr[2];
struct sc_asn1_entry asn1_prkey[4];
struct sc_asn1_pkcs15_object rsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_prk_rsa_attr };
struct sc_asn1_pkcs15_object dsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_prk_dsa_attr };
struct sc_asn1_pkcs15_object gostr3410_prkey_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_key_attr, asn1_com_prkey_attr,
asn1_prk_gostr3410_attr };
struct sc_pkcs15_prkey_info *prkey =
(struct sc_pkcs15_prkey_info *) obj->data;
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
int r;
size_t af_len, usage_len;
sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);
sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);
sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr);
sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr);
sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr);
sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
switch (obj->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
@ -217,6 +271,21 @@ int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
&prkey->path, NULL, 1);
}
break;
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 1);
sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &prkey->path, NULL, 1);
if (prkey->params_len == sizeof(*keyinfo_gostparams))
{
keyinfo_gostparams = prkey->params;
sc_format_asn1_entry(asn1_gostr3410key_attr + 1,
&keyinfo_gostparams->gostr3410, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 2,
&keyinfo_gostparams->gostr3411, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 3,
&keyinfo_gostparams->gost28147, NULL, 1);
}
break;
default:
sc_error(ctx, "Invalid private key type: %X\n", obj->type);
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
@ -404,6 +473,10 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key)
free(key->u.dsa.g.data);
free(key->u.dsa.priv.data);
break;
case SC_ALGORITHM_GOSTR3410:
assert(key->u.gostr3410.d.data);
free(key->u.gostr3410.d.data);
break;
}
sc_mem_clear(key, sizeof(key));
}
@ -419,5 +492,7 @@ void sc_pkcs15_free_prkey_info(sc_pkcs15_prkey_info_t *key)
{
if (key->subject)
free(key->subject);
if (key->params)
free(key->params);
free(key);
}

View File

@ -62,9 +62,23 @@ static const struct sc_asn1_entry c_asn1_dsa_type_attr[] = {
{ NULL, 0, 0, 0, NULL, NULL }
};
static const struct sc_asn1_entry c_asn1_gostr3410key_attr[] = {
{ "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 },
{ NULL, 0, 0, 0, NULL, NULL }
};
static const struct sc_asn1_entry c_asn1_gostr3410_type_attr[] = {
{ "publicGOSTR3410KeyAttributes", 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_pubkey_choice[] = {
{ "publicRSAKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "publicDSAKey", SC_ASN1_PKCS15_OBJECT, 2 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL },
{ "publicGOSTR3410Key", SC_ASN1_PKCS15_OBJECT, 3 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -77,32 +91,39 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 ** buf, size_t *buflen)
{
sc_context_t *ctx = p15card->card->ctx;
struct sc_pkcs15_pubkey_info info;
int r;
sc_context_t *ctx = p15card->card->ctx;
struct sc_pkcs15_pubkey_info info;
int r, gostr3410_params[3];
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
size_t usage_len = sizeof(info.usage);
size_t af_len = sizeof(info.access_flags);
struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1];
struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2];
struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2];
struct sc_asn1_entry asn1_pubkey_choice[3];
struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2];
struct sc_asn1_entry asn1_pubkey_choice[4];
struct sc_asn1_entry asn1_pubkey[2];
struct sc_asn1_pkcs15_object rsakey_obj = { obj, asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_rsa_type_attr };
struct sc_asn1_pkcs15_object dsakey_obj = { obj, asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_dsa_type_attr };
struct sc_asn1_pkcs15_object gostr3410key_obj = { obj, asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_gostr3410_type_attr };
sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr);
sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 0);
sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 0);
sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 0);
sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 0);
@ -113,6 +134,13 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
sc_format_asn1_entry(asn1_dsakey_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &gostr3410_params[0], NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &gostr3410_params[1], NULL, 0);
sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &gostr3410_params[2], NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0);
sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0);
@ -121,10 +149,11 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 0);
/* Fill in defaults */
memset(&info, 0, sizeof(info));
/* Fill in defaults */
memset(&info, 0, sizeof(info));
info.key_reference = -1;
info.native = 1;
memset(gostr3410_params, 0, sizeof(gostr3410_params));
r = sc_asn1_decode(ctx, asn1_pubkey, *buf, *buflen, buf, buflen);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
@ -132,19 +161,40 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
SC_TEST_RET(ctx, r, "ASN.1 decoding failed");
if (asn1_pubkey_choice[0].flags & SC_ASN1_PRESENT) {
obj->type = SC_PKCS15_TYPE_PUBKEY_RSA;
} else if (asn1_pubkey_choice[2].flags & SC_ASN1_PRESENT) {
obj->type = SC_PKCS15_TYPE_PUBKEY_GOSTR3410;
assert(info.modulus_length == 0);
info.modulus_length = SC_PKCS15_GOSTR3410_KEYSIZE;
assert(info.params_len == 0);
info.params_len = sizeof(struct sc_pkcs15_keyinfo_gostparams);
info.params = malloc(info.params_len);
if (info.params == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
assert(sizeof(*keyinfo_gostparams) == info.params_len);
keyinfo_gostparams = info.params;
keyinfo_gostparams->gostr3410 = (unsigned int)gostr3410_params[0];
keyinfo_gostparams->gostr3411 = (unsigned int)gostr3410_params[1];
keyinfo_gostparams->gost28147 = (unsigned int)gostr3410_params[2];
} else {
obj->type = SC_PKCS15_TYPE_PUBKEY_DSA;
}
r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
if (r < 0)
if (r < 0) {
if (info.params)
free(info.params);
return r;
}
obj->data = malloc(sizeof(info));
if (obj->data == NULL)
if (obj->data == NULL) {
if (info.params)
free(info.params);
SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(obj->data, &info, sizeof(info));
return 0;
}
int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
const struct sc_pkcs15_object *obj,
u8 **buf, size_t *buflen)
@ -152,27 +202,34 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1];
struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2];
struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2];
struct sc_asn1_entry asn1_pubkey_choice[3];
struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2];
struct sc_asn1_entry asn1_pubkey_choice[4];
struct sc_asn1_entry asn1_pubkey[2];
struct sc_pkcs15_pubkey_info *pubkey =
(struct sc_pkcs15_pubkey_info *) obj->data;
(struct sc_pkcs15_pubkey_info *) obj->data;
struct sc_asn1_pkcs15_object rsakey_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_rsa_type_attr };
struct sc_asn1_pkcs15_object dsakey_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_dsa_type_attr };
struct sc_asn1_pkcs15_object gostr3410key_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_gostr3410_type_attr };
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
int r;
size_t af_len, usage_len;
sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr);
sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr);
sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
switch (obj->type) {
case SC_PKCS15_TYPE_PUBKEY_RSA:
@ -191,6 +248,24 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
sc_format_asn1_entry(asn1_dsakey_attr + 0, &pubkey->path, NULL, 1);
break;
case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &pubkey->path, NULL, 1);
if (pubkey->params_len == sizeof(*keyinfo_gostparams))
{
keyinfo_gostparams = pubkey->params;
sc_format_asn1_entry(asn1_gostr3410key_attr + 1,
&keyinfo_gostparams->gostr3410, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 2,
&keyinfo_gostparams->gostr3411, NULL, 1);
sc_format_asn1_entry(asn1_gostr3410key_attr + 3,
&keyinfo_gostparams->gost28147, NULL, 1);
}
break;
default:
sc_error(ctx, "Unsupported public key type: %X\n", obj->type);
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
@ -236,6 +311,12 @@ 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 },
{ NULL, 0, 0, 0, NULL, NULL }
};
int
sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx,
struct sc_pkcs15_pubkey_rsa *key,
@ -341,6 +422,50 @@ sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx,
return 0;
}
int
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];
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_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);
SC_TEST_RET(ctx, r, "ASN.1 parsing of public key failed");
return 0;
}
int
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];
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);
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
SC_TEST_RET(ctx, r, "ASN.1 encoding failed");
return 0;
}
int
sc_pkcs15_encode_pubkey(sc_context_t *ctx,
struct sc_pkcs15_pubkey *key,
@ -350,6 +475,9 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx,
return sc_pkcs15_encode_pubkey_rsa(ctx, &key->u.rsa, buf, len);
if (key->algorithm == SC_ALGORITHM_DSA)
return sc_pkcs15_encode_pubkey_dsa(ctx, &key->u.dsa, buf, len);
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
return sc_pkcs15_encode_pubkey_gostr3410(ctx,
&key->u.gostr3410, buf, len);
sc_error(ctx, "Encoding of public key type %u not supported\n",
key->algorithm);
return SC_ERROR_NOT_SUPPORTED;
@ -364,6 +492,9 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx,
return sc_pkcs15_decode_pubkey_rsa(ctx, &key->u.rsa, buf, len);
if (key->algorithm == SC_ALGORITHM_DSA)
return sc_pkcs15_decode_pubkey_dsa(ctx, &key->u.dsa, buf, len);
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
return sc_pkcs15_decode_pubkey_gostr3410(ctx,
&key->u.gostr3410, buf, len);
sc_error(ctx, "Decoding of public key type %u not supported\n",
key->algorithm);
return SC_ERROR_NOT_SUPPORTED;
@ -393,6 +524,9 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
case SC_PKCS15_TYPE_PUBKEY_DSA:
algorithm = SC_ALGORITHM_DSA;
break;
case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
algorithm = SC_ALGORITHM_GOSTR3410;
break;
default:
sc_error(p15card->card->ctx, "Unsupported public key type.");
return SC_ERROR_NOT_SUPPORTED;
@ -436,6 +570,10 @@ void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
free(key->u.dsa.p.data);
free(key->u.dsa.q.data);
break;
case SC_ALGORITHM_GOSTR3410:
free(key->u.gostr3410.x.data);
free(key->u.gostr3410.y.data);
break;
}
free(key->data.value);
sc_mem_clear(key, sizeof(*key));
@ -451,5 +589,7 @@ void sc_pkcs15_free_pubkey_info(sc_pkcs15_pubkey_info_t *key)
{
if (key->subject)
free(key->subject);
if (key->params)
free(key->params);
free(key);
}

View File

@ -911,9 +911,11 @@ static int compare_obj_id(struct sc_pkcs15_object *obj, const sc_pkcs15_id_t *id
return sc_pkcs15_compare_id(&((struct sc_pkcs15_cert_info *) data)->id, id);
case SC_PKCS15_TYPE_PRKEY_RSA:
case SC_PKCS15_TYPE_PRKEY_DSA:
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_prkey_info *) data)->id, id);
case SC_PKCS15_TYPE_PUBKEY_RSA:
case SC_PKCS15_TYPE_PUBKEY_DSA:
case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_pubkey_info *) data)->id, id);
case SC_PKCS15_TYPE_AUTH_PIN:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_pin_info *) data)->auth_id, id);
@ -938,10 +940,12 @@ static int compare_obj_usage(sc_pkcs15_object_t *obj, unsigned int mask, unsigne
switch (obj->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
case SC_PKCS15_TYPE_PRKEY_DSA:
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
usage = ((struct sc_pkcs15_prkey_info *) data)->usage;
break;
case SC_PKCS15_TYPE_PUBKEY_RSA:
case SC_PKCS15_TYPE_PUBKEY_DSA:
case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
usage = ((struct sc_pkcs15_pubkey_info *) data)->usage;
break;
default:
@ -976,6 +980,7 @@ static int compare_obj_reference(sc_pkcs15_object_t *obj, int value)
break;
case SC_PKCS15_TYPE_PRKEY_RSA:
case SC_PKCS15_TYPE_PRKEY_DSA:
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
reference = ((struct sc_pkcs15_prkey_info *) data)->key_reference;
break;
default:
@ -993,9 +998,11 @@ static int compare_obj_path(sc_pkcs15_object_t *obj, const sc_path_t *path)
return sc_compare_path(&((struct sc_pkcs15_cert_info *) data)->path, path);
case SC_PKCS15_TYPE_PRKEY_RSA:
case SC_PKCS15_TYPE_PRKEY_DSA:
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
return sc_compare_path(&((struct sc_pkcs15_prkey_info *) data)->path, path);
case SC_PKCS15_TYPE_PUBKEY_RSA:
case SC_PKCS15_TYPE_PUBKEY_DSA:
case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
return sc_compare_path(&((struct sc_pkcs15_pubkey_info *) data)->path, path);
case SC_PKCS15_TYPE_AUTH_PIN:
return sc_compare_path(&((struct sc_pkcs15_pin_info *) data)->path, path);

View File

@ -142,6 +142,16 @@ struct sc_pkcs15_prkey_dsa {
sc_pkcs15_bignum_t priv;
};
struct sc_pkcs15_pubkey_gostr3410 {
sc_pkcs15_bignum_t x;
sc_pkcs15_bignum_t y;
};
struct sc_pkcs15_prkey_gostr3410 {
/* private components */
sc_pkcs15_bignum_t d;
};
struct sc_pkcs15_pubkey {
int algorithm;
@ -149,6 +159,7 @@ struct sc_pkcs15_pubkey {
union {
struct sc_pkcs15_pubkey_rsa rsa;
struct sc_pkcs15_pubkey_dsa dsa;
struct sc_pkcs15_pubkey_gostr3410 gostr3410;
} u;
/* DER encoded raw key */
@ -161,6 +172,7 @@ struct sc_pkcs15_prkey {
union {
struct sc_pkcs15_prkey_rsa rsa;
struct sc_pkcs15_prkey_dsa dsa;
struct sc_pkcs15_prkey_gostr3410 gostr3410;
} u;
};
typedef struct sc_pkcs15_prkey sc_pkcs15_prkey_t;
@ -241,6 +253,17 @@ typedef struct sc_pkcs15_data_info sc_pkcs15_data_info_t;
#define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08
#define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10
#define SC_PKCS15_PARAMSET_GOSTR3410_A 1
#define SC_PKCS15_PARAMSET_GOSTR3410_B 2
#define SC_PKCS15_PARAMSET_GOSTR3410_C 3
#define SC_PKCS15_GOSTR3410_KEYSIZE 256
struct sc_pkcs15_keyinfo_gostparams
{
unsigned int gostr3410, gostr3411, gost28147;
};
struct sc_pkcs15_prkey_info {
struct sc_pkcs15_id id; /* correlates to public certificate id */
unsigned int usage, access_flags;
@ -248,6 +271,8 @@ struct sc_pkcs15_prkey_info {
size_t modulus_length;
u8 *subject;
size_t subject_len;
void *params;
size_t params_len;
struct sc_path path;
};
@ -260,6 +285,8 @@ struct sc_pkcs15_pubkey_info {
size_t modulus_length;
u8 *subject;
size_t subject_len;
void *params;
size_t params_len;
struct sc_path path;
};
@ -270,10 +297,12 @@ typedef struct sc_pkcs15_pubkey_info sc_pkcs15_pubkey_info_t;
#define SC_PKCS15_TYPE_PRKEY 0x100
#define SC_PKCS15_TYPE_PRKEY_RSA 0x101
#define SC_PKCS15_TYPE_PRKEY_DSA 0x102
#define SC_PKCS15_TYPE_PRKEY_GOSTR3410 0x103
#define SC_PKCS15_TYPE_PUBKEY 0x200
#define SC_PKCS15_TYPE_PUBKEY_RSA 0x201
#define SC_PKCS15_TYPE_PUBKEY_DSA 0x202
#define SC_PKCS15_TYPE_PUBKEY_GOSTR3410 0x203
#define SC_PKCS15_TYPE_CERT 0x400
#define SC_PKCS15_TYPE_CERT_X509 0x401

View File

@ -105,8 +105,8 @@ struct pkcs15_pubkey_object {
#define pub_cert base.related_cert
#define __p15_type(obj) (((obj) && (obj)->p15_object)? ((obj)->p15_object->type) : (unsigned int)-1)
#define is_privkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PRKEY_RSA)
#define is_pubkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PUBKEY_RSA)
#define is_privkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PRKEY_RSA || __p15_type(obj) == SC_PKCS15_TYPE_PRKEY_GOSTR3410)
#define is_pubkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PUBKEY_RSA || __p15_type(obj) == SC_PKCS15_TYPE_PUBKEY_GOSTR3410)
#define is_cert(obj) (__p15_type(obj) == SC_PKCS15_TYPE_CERT_X509)
struct pkcs15_data_object {
@ -124,6 +124,18 @@ extern struct sc_pkcs11_object_ops pkcs15_prkey_ops;
extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops;
extern struct sc_pkcs11_object_ops pkcs15_dobj_ops;
#define GOST_PARAMS_OID_SIZE 9
static const struct {
const CK_BYTE oid[GOST_PARAMS_OID_SIZE];
unsigned char param;
} gostr3410_param_oid [] = {
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 },
SC_PKCS15_PARAMSET_GOSTR3410_A },
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x02 },
SC_PKCS15_PARAMSET_GOSTR3410_B },
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x03 },
SC_PKCS15_PARAMSET_GOSTR3410_C }
};
static int __pkcs15_release_object(struct pkcs15_any_object *);
static int register_mechanisms(struct sc_pkcs11_card *p11card);
@ -135,6 +147,7 @@ static CK_RV get_modulus_bits(struct sc_pkcs15_pubkey *,
CK_ATTRIBUTE_PTR);
static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);
static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
static CK_RV get_gostr3410_params(const u8 *, size_t, CK_ATTRIBUTE_PTR);
static void cache_pin(void *, int, const sc_path_t *, const void *, size_t);
static int revalidate_pin(struct pkcs15_slot_data *data,
struct sc_pkcs11_session *ses);
@ -275,7 +288,8 @@ static int public_key_created(struct pkcs15_fw_data *fw_data,
}
if ((fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY) &&
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_RSA) &&
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_DSA)) {
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_DSA) &&
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_GOSTR3410)) {
ii++;
continue;
}
@ -637,6 +651,11 @@ pkcs15_add_object(struct sc_pkcs11_slot *slot,
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL);
break;
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
if (obj->related_cert == NULL)
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL);
break;
case SC_PKCS15_TYPE_CERT_X509:
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL);
@ -748,6 +767,20 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
if (rv < 0)
return sc_to_cryptoki_error(rv, reader);
rv = pkcs15_create_pkcs11_objects(fw_data,
SC_PKCS15_TYPE_PRKEY_GOSTR3410,
"private key",
__pkcs15_create_prkey_object);
if (rv < 0)
return sc_to_cryptoki_error(rv, reader);
rv = pkcs15_create_pkcs11_objects(fw_data,
SC_PKCS15_TYPE_PUBKEY_GOSTR3410,
"public key",
__pkcs15_create_pubkey_object);
if (rv < 0)
return sc_to_cryptoki_error(rv, reader);
rv = pkcs15_create_pkcs11_objects(fw_data,
SC_PKCS15_TYPE_CERT_X509,
"certificate",
@ -1480,6 +1513,39 @@ get_X509_usage_pubk(CK_ATTRIBUTE_PTR pTempl, CK_ULONG ulCount, unsigned long *x5
return CKR_OK;
}
static CK_RV
set_gost_params(struct sc_pkcs15init_prkeyargs *prkey_args,
struct sc_pkcs15init_pubkeyargs *pubkey_args,
CK_ATTRIBUTE_PTR pPubTpl, CK_ULONG ulPubCnt,
CK_ATTRIBUTE_PTR pPrivTpl, CK_ULONG ulPrivCnt)
{
CK_BYTE gost_params_oid[GOST_PARAMS_OID_SIZE];
size_t len, i;
CK_RV rv;
len = GOST_PARAMS_OID_SIZE;
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_GOSTR3410_PARAMS,
&gost_params_oid, &len);
if (rv == CKR_OK) {
if (len != GOST_PARAMS_OID_SIZE)
return CKR_ATTRIBUTE_VALUE_INVALID;
for (i = 0; i < sizeof(gostr3410_param_oid)
/sizeof(gostr3410_param_oid[0]); ++i) {
if (!memcmp(gost_params_oid, gostr3410_param_oid[i].oid, len)) {
prkey_args->gost_params.gostr3410 =
gostr3410_param_oid[i].param;
pubkey_args->gost_params.gostr3410 =
gostr3410_param_oid[i].param;
break;
}
}
if (i != sizeof(gostr3410_param_oid)/sizeof(gostr3410_param_oid[0]))
return CKR_OK;
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
/* FIXME: check for the public exponent in public key template and use this value */
static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
struct sc_pkcs11_slot *slot,
@ -1500,7 +1566,7 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
struct pkcs15_any_object *pub_any_obj;
struct sc_pkcs15_id id;
size_t len;
CK_KEY_TYPE keytype = CKK_RSA;
CK_KEY_TYPE keytype;
CK_ULONG keybits;
char pub_label[SC_PKCS15_MAX_LABEL_SIZE];
char priv_label[SC_PKCS15_MAX_LABEL_SIZE];
@ -1508,7 +1574,8 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
sc_debug(context, "Keypair generation, mech = 0x%0x\n", pMechanism->mechanism);
if (pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN)
if (pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN
&& pMechanism->mechanism != CKM_GOSTR3410_KEY_PAIR_GEN)
return CKR_MECHANISM_INVALID;
rc = sc_lock(p11card->card);
@ -1531,18 +1598,37 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_KEY_TYPE,
&keytype, NULL);
if (rv == CKR_OK && keytype != CKK_RSA) {
if (rv != CKR_OK)
keytype = CKK_RSA;
if (keytype == CKK_GOSTR3410)
{
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
pub_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
set_gost_params(&keygen_args.prkey_args, &pub_args,
pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt);
}
else if (keytype == CKK_RSA)
{
/* default value (CKA_KEY_TYPE isn't set) or CKK_RSA is set */
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
pub_args.key.algorithm = SC_ALGORITHM_RSA;
}
else
{
/* CKA_KEY_TYPE is set, but keytype isn't correct */
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto kpgen_done;
}
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
pub_args.key.algorithm = SC_ALGORITHM_RSA;
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_MODULUS_BITS,
&keybits, NULL);
if (rv != CKR_OK)
if (keytype == CKK_GOSTR3410)
keybits = SC_PKCS15_GOSTR3410_KEYSIZE;
else if (keytype == CKK_RSA)
{
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_MODULUS_BITS,
&keybits, NULL);
if (rv != CKR_OK)
keybits = 1024; /* Default key size */
/* To do: check allowed values of keybits */
/* TODO: check allowed values of keybits */
}
id.len = SC_PKCS15_MAX_ID_SIZE;
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_ID,
@ -1981,7 +2067,10 @@ static CK_RV pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session,
break;
case CKA_KEY_TYPE:
check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
if (key && key->algorithm == SC_ALGORITHM_GOSTR3410)
*(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410;
else
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
break;
case CKA_ID:
check_attribute_buffer(attr, prkey->prv_info->id.len);
@ -2082,9 +2171,15 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
case CKM_RSA_X_509:
flags = SC_ALGORITHM_RSA_RAW;
break;
case CKM_OPENSC_GOST:
case CKM_OPENSC_GOST: /* FIXME: */
flags = SC_ALGORITHM_GOST;
break;
case CKM_GOSTR3410:
flags = SC_ALGORITHM_GOSTR3410_HASH_NONE;
break;
case CKM_GOSTR3410_WITH_GOSTR3411:
flags = SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411;
break;
default:
return CKR_MECHANISM_INVALID;
}
@ -2333,7 +2428,10 @@ static CK_RV pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
break;
case CKA_KEY_TYPE:
check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_GOSTR3410)
*(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410;
else
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
break;
case CKA_ID:
if (pubkey->pub_info) {
@ -2383,6 +2481,12 @@ static CK_RV pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len);
}
break;
case CKA_GOSTR3410_PARAMS:
if (pubkey->pub_info && pubkey->pub_info->params_len)
return get_gostr3410_params(pubkey->pub_info->params,
pubkey->pub_info->params_len, attr);
else
return CKR_ATTRIBUTE_TYPE_INVALID;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
@ -2657,6 +2761,26 @@ get_public_exponent(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
return CKR_ATTRIBUTE_TYPE_INVALID;
}
static CK_RV
get_gostr3410_params(const u8 *params, size_t params_len, CK_ATTRIBUTE_PTR attr)
{
size_t i;
if (!params || params_len == sizeof(int))
return CKR_ATTRIBUTE_TYPE_INVALID;
for (i = 0; i < sizeof(gostr3410_param_oid)/
sizeof(gostr3410_param_oid[0]); ++i) {
if (gostr3410_param_oid[i].param == ((int*)params)[0]) {
check_attribute_buffer(attr, sizeof(gostr3410_param_oid[i].oid));
memcpy(attr->pValue, gostr3410_param_oid[i].oid,
sizeof(gostr3410_param_oid[i].oid));
return CKR_OK;
}
}
return CKR_ATTRIBUTE_TYPE_INVALID;
}
/*
* Map pkcs15 usage bits to pkcs11 usage attributes.
*
@ -2790,6 +2914,40 @@ revalidate_pin(struct pkcs15_slot_data *data, struct sc_pkcs11_session *ses)
return rv;
}
static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
{
CK_MECHANISM_INFO mech_info;
sc_pkcs11_mechanism_type_t *mt;
int rc;
mech_info.flags = CKF_HW | CKF_SIGN | CKF_UNWRAP | CKF_DECRYPT;
#ifdef ENABLE_OPENSSL
mech_info.flags |= CKF_VERIFY;
#endif
mech_info.ulMinKeySize = SC_PKCS15_GOSTR3410_KEYSIZE;
mech_info.ulMaxKeySize = SC_PKCS15_GOSTR3410_KEYSIZE;
if (flags & SC_ALGORITHM_GOSTR3410_HASH_NONE) {
mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410,
&mech_info, CKK_GOSTR3410, NULL);
if (!mt)
return CKR_HOST_MEMORY;
rc = sc_pkcs11_register_mechanism(p11card, mt);
if (rc != CKR_OK)
return rc;
}
if (flags & SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411) {
mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410_WITH_GOSTR3411,
&mech_info, CKK_GOSTR3410, NULL);
if (!mt)
return CKR_HOST_MEMORY;
rc = sc_pkcs11_register_mechanism(p11card, mt);
if (rc != CKR_OK)
return rc;
}
return CKR_OK;
}
/*
* Mechanism handling
* FIXME: We should consult the card's algorithm list to
@ -2829,7 +2987,9 @@ static int register_mechanisms(struct sc_pkcs11_card *p11card)
flags |= alg_info->flags;
}
if (alg_info->algorithm == SC_ALGORITHM_GOSTR3410)
flags |= alg_info->flags;
#if 0 /* FIXME: */
if (alg_info->algorithm == SC_ALGORITHM_GOST){
mech_info.flags = CKF_HW | CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT;
#ifdef ENABLE_OPENSSL
@ -2844,10 +3004,20 @@ static int register_mechanisms(struct sc_pkcs11_card *p11card)
if(rc < 0)
return rc;
}
#endif
alg_info++;
}
if (flags & (SC_ALGORITHM_GOSTR3410_RAW
| SC_ALGORITHM_GOSTR3410_HASH_NONE
| SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411)) {
if (flags & SC_ALGORITHM_GOSTR3410_RAW)
flags |= SC_ALGORITHM_GOSTR3410_HASH_NONE;
rc = register_gost_mechanisms(p11card, flags);
if (rc != CKR_OK)
return rc;
}
/* Check if we support raw RSA */
if (flags & SC_ALGORITHM_RSA_RAW) {
mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509,
@ -2892,7 +3062,6 @@ static int register_mechanisms(struct sc_pkcs11_card *p11card)
sc_pkcs11_register_sign_and_hash_mechanism(p11card,
CKM_XXX_RSA_PKCS, CKM_XXX, mt);
#endif
#ifdef ENABLE_OPENSSL
mech_info.flags = CKF_GENERATE_KEY_PAIR;
mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN,
@ -2902,7 +3071,6 @@ static int register_mechanisms(struct sc_pkcs11_card *p11card)
return rc;
#endif
}
return CKR_OK;
}

View File

@ -427,6 +427,8 @@ sc_pkcs11_signature_size(sc_pkcs11_operation_t *operation, CK_ULONG_PTR pLength)
{
struct sc_pkcs11_object *key;
CK_ATTRIBUTE attr = { CKA_MODULUS_BITS, pLength, sizeof(*pLength) };
CK_KEY_TYPE key_type;
CK_ATTRIBUTE attr_key_type = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
CK_RV rv;
key = ((struct signature_data *) operation->priv_data)->key;
@ -436,6 +438,12 @@ sc_pkcs11_signature_size(sc_pkcs11_operation_t *operation, CK_ULONG_PTR pLength)
if (rv == CKR_OK)
*pLength = (*pLength + 7) / 8;
if (rv == CKR_OK) {
rv = key->ops->get_attribute(operation->session, key, &attr_key_type);
if (rv == CKR_OK && key_type == CKK_GOSTR3410)
*pLength *= 2;
}
return rv;
}
@ -609,7 +617,11 @@ sc_pkcs11_verify_final(sc_pkcs11_operation_t *operation,
struct signature_data *data;
struct sc_pkcs11_object *key;
unsigned char *pubkey_value;
CK_KEY_TYPE key_type;
CK_BYTE params[9 /* GOST_PARAMS_OID_SIZE */] = { 0 };
CK_ATTRIBUTE attr = {CKA_VALUE, NULL, 0};
CK_ATTRIBUTE attr_key_type = {CKA_KEY_TYPE, &key_type, sizeof(key_type)};
CK_ATTRIBUTE attr_key_params = {CKA_GOSTR3410_PARAMS, &params, sizeof(params)};
int rv;
data = (struct signature_data *) operation->priv_data;
@ -627,7 +639,15 @@ sc_pkcs11_verify_final(sc_pkcs11_operation_t *operation,
if (rv != CKR_OK)
goto done;
rv = key->ops->get_attribute(operation->session, key, &attr_key_type);
if (rv == CKR_OK && key_type == CKK_GOSTR3410) {
rv = key->ops->get_attribute(operation->session, key, &attr_key_params);
if (rv != CKR_OK)
goto done;
}
rv = sc_pkcs11_verify_data(pubkey_value, attr.ulValueLen,
params, sizeof(params),
operation->mechanism.mechanism, data->md,
data->buffer, data->buffer_len, pSignature, ulSignatureLen);

View File

@ -13,6 +13,10 @@
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#include <openssl/ec.h>
#include <openssl/conf.h>
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *);
static CK_RV sc_pkcs11_openssl_md_update(sc_pkcs11_operation_t *,
@ -63,6 +67,18 @@ static sc_pkcs11_mechanism_type_t openssl_sha512_mech = {
};
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
static sc_pkcs11_mechanism_type_t openssl_gostr3411_mech = {
CKM_GOSTR3411,
{ 0, 0, CKF_DIGEST }, 0,
sizeof(struct sc_pkcs11_operation),
sc_pkcs11_openssl_md_release,
sc_pkcs11_openssl_md_init,
sc_pkcs11_openssl_md_update,
sc_pkcs11_openssl_md_final
};
#endif
static sc_pkcs11_mechanism_type_t openssl_md5_mech = {
CKM_MD5,
{ 0, 0, CKF_DIGEST }, 0,
@ -86,6 +102,10 @@ static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = {
void
sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card)
{
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
/* FIXME: see openssl-1.0.0-beta3/engines/ccgost/README.gost */
OPENSSL_config(NULL);
#endif
openssl_sha1_mech.mech_data = EVP_sha1();
sc_pkcs11_register_mechanism(card, &openssl_sha1_mech);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
@ -100,6 +120,10 @@ sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card)
sc_pkcs11_register_mechanism(card, &openssl_md5_mech);
openssl_ripemd160_mech.mech_data = EVP_ripemd160();
sc_pkcs11_register_mechanism(card, &openssl_ripemd160_mech);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
openssl_gostr3411_mech.mech_data = EVP_get_digestbynid(NID_id_GostR3411_94);
sc_pkcs11_register_mechanism(card, &openssl_gostr3411_mech);
#endif
}
@ -224,11 +248,94 @@ sc_pkcs11_gen_keypair_soft(CK_KEY_TYPE keytype, CK_ULONG keybits,
return CKR_OK;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
static void reverse(unsigned char *buf, size_t len)
{
unsigned char tmp;
size_t i;
for (i = 0; i < len / 2; ++i) {
tmp = buf[i];
buf[i] = buf[len - 1 - i];
buf[len - 1 - i] = tmp;
}
}
static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len,
const unsigned char *params, int params_len,
unsigned char *data, int data_len,
unsigned char *signat, int signat_len)
{
EVP_PKEY *pkey;
EVP_PKEY_CTX *pkey_ctx;
EC_POINT *P;
BIGNUM *X, *Y;
const EC_GROUP *group = NULL;
char paramset[2] = "A";
int r = -1, ret_vrf = 0;
pkey = EVP_PKEY_new();
if (!pkey)
return CKR_HOST_MEMORY;
r = EVP_PKEY_set_type(pkey, NID_id_GostR3410_2001);
if (r == 1) {
pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkey_ctx) {
EVP_PKEY_free(pkey);
return CKR_HOST_MEMORY;
}
/* FIXME: fully check params[] */
if (params_len > 0 && params[params_len - 1] >= 1 &&
params[params_len - 1] <= 3) {
paramset[0] += params[params_len - 1] - 1;
r = EVP_PKEY_CTX_ctrl_str(pkey_ctx, "paramset", paramset);
}
else
r = -1;
if (r == 1)
r = EVP_PKEY_paramgen_init(pkey_ctx);
if (r == 1)
r = EVP_PKEY_paramgen(pkey_ctx, &pkey);
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);
P = EC_POINT_new(group);
if (P && X && Y)
r = EC_POINT_set_affine_coordinates_GFp(group,
P, X, Y, NULL);
BN_free(X);
BN_free(Y);
if (r == 1 && EVP_PKEY_get0(pkey) && P)
r = EC_KEY_set_public_key(EVP_PKEY_get0(pkey), P);
EC_POINT_free(P);
}
if (r == 1) {
r = EVP_PKEY_verify_init(pkey_ctx);
reverse(data, data_len);
if (r == 1)
ret_vrf = EVP_PKEY_verify(pkey_ctx, signat, signat_len,
data, data_len);
}
}
EVP_PKEY_CTX_free(pkey_ctx);
EVP_PKEY_free(pkey);
if (r != 1)
return CKR_GENERAL_ERROR;
return ret_vrf == 1 ? CKR_OK : CKR_SIGNATURE_INVALID;
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
/* If no hash function was used, finish with RSA_public_decrypt().
* If a hash function was used, we can make a big shortcut by
* finishing with EVP_VerifyFinal().
*/
CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
const unsigned char *pubkey_params, int pubkey_params_len,
CK_MECHANISM_TYPE mech, sc_pkcs11_operation_t *md,
unsigned char *data, int data_len,
unsigned char *signat, int signat_len)
@ -237,10 +344,20 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
CK_RV rv = CKR_GENERAL_ERROR;
EVP_PKEY *pkey;
if (mech == CKM_GOSTR3410)
{
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
return gostr3410_verify_data(pubkey, pubkey_len,
pubkey_params, pubkey_params_len,
data, data_len, signat, signat_len);
#else
return CKR_FUNCTION_NOT_SUPPORTED;
#endif
}
pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &pubkey, pubkey_len);
if (pkey == NULL)
return CKR_GENERAL_ERROR;
if (md != NULL) {
EVP_MD_CTX *md_ctx = DIGEST_CTX(md);

View File

@ -356,6 +356,7 @@ typedef unsigned long ck_key_type_t;
#define CKK_AES (0x1fUL)
#define CKK_BLOWFISH (0x20UL)
#define CKK_TWOFISH (0x21UL)
#define CKK_GOSTR3410 (0x30UL)
#define CKK_VENDOR_DEFINED (1UL << 31)
@ -433,6 +434,9 @@ typedef unsigned long ck_attribute_type_t;
#define CKA_AUTH_PIN_FLAGS (0x201UL)
#define CKA_ALWAYS_AUTHENTICATE (0x202UL)
#define CKA_WRAP_WITH_TRUSTED (0x210UL)
#define CKA_GOSTR3410_PARAMS (0x250UL)
#define CKA_GOSTR3411_PARAMS (0x251UL)
#define CKA_GOST28147_PARAMS (0x252UL)
#define CKA_HW_FEATURE_TYPE (0x300UL)
#define CKA_RESET_ON_INIT (0x301UL)
#define CKA_HAS_RESET (0x302UL)
@ -669,6 +673,10 @@ typedef unsigned long ck_mechanism_type_t;
#define CKM_AES_MAC (0x1083UL)
#define CKM_AES_MAC_GENERAL (0x1084UL)
#define CKM_AES_CBC_PAD (0x1085UL)
#define CKM_GOSTR3410_KEY_PAIR_GEN (0x1200UL)
#define CKM_GOSTR3410 (0x1201UL)
#define CKM_GOSTR3410_WITH_GOSTR3411 (0x1202UL)
#define CKM_GOSTR3411 (0x1210UL)
#define CKM_DSA_PARAMETER_GEN (0x2000UL)
#define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL)
#define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL)

View File

@ -440,6 +440,7 @@ CK_RV sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *,
CK_RV sc_pkcs11_gen_keypair_soft(CK_KEY_TYPE keytype, CK_ULONG keybits,
struct sc_pkcs15_prkey *privkey, struct sc_pkcs15_pubkey *pubkey);
CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
const unsigned char *pubkey_params, int pubkey_params_len,
CK_MECHANISM_TYPE mech, sc_pkcs11_operation_t *md,
unsigned char *inp, int inp_len,
unsigned char *signat, int signat_len);

View File

@ -219,6 +219,10 @@ struct sc_pkcs15init_pinargs {
size_t puk_len;
};
struct sc_pkcs15init_keyarg_gost_params {
unsigned char gostr3410, gostr3411, gost28147;
};
struct sc_pkcs15init_prkeyargs {
struct sc_pkcs15_id id;
struct sc_pkcs15_id auth_id;
@ -226,6 +230,7 @@ struct sc_pkcs15init_prkeyargs {
unsigned long usage;
unsigned long x509_usage;
unsigned int flags;
struct sc_pkcs15init_keyarg_gost_params gost_params;
sc_pkcs15_prkey_t key;
@ -248,6 +253,7 @@ struct sc_pkcs15init_pubkeyargs {
const char * label;
unsigned long usage;
unsigned long x509_usage;
struct sc_pkcs15init_keyarg_gost_params gost_params;
sc_pkcs15_pubkey_t key;
};

View File

@ -1188,6 +1188,7 @@ sc_pkcs15init_init_prkdf(sc_pkcs15_card_t *p15card,
)
{
struct sc_pkcs15_prkey_info *key_info;
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
struct sc_pkcs15_object *object;
sc_card_t *card = p15card->card;
const char *label;
@ -1254,6 +1255,19 @@ sc_pkcs15init_init_prkdf(sc_pkcs15_card_t *p15card,
key_info->id = keyargs->id;
if (key->algorithm == SC_ALGORITHM_GOSTR3410) {
key_info->params_len = sizeof(*keyinfo_gostparams);
/* FIXME: malloc() call in pkcs15init, but free() call
* in libopensc (sc_pkcs15_free_prkey_info) */
key_info->params = malloc(key_info->params_len);
if (!key_info->params)
return SC_ERROR_OUT_OF_MEMORY;
keyinfo_gostparams = key_info->params;
keyinfo_gostparams->gostr3410 = keyargs->gost_params.gostr3410;
keyinfo_gostparams->gostr3411 = keyargs->gost_params.gostr3411;
keyinfo_gostparams->gost28147 = keyargs->gost_params.gost28147;
}
r = select_object_path(p15card, profile, object,
&key_info->id, &key_info->path);
if (r < 0)
@ -1311,7 +1325,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
if (r != SC_SUCCESS)
return r;
/* For now, we support just RSA key pair generation */
/* For now, we support just RSA and GOST key pair generation */
if (!check_key_compatibility(p15card, &keygen_args->prkey_args.key,
keygen_args->prkey_args.x509_usage,
keybits, SC_ALGORITHM_ONBOARD_KEY_GEN))
@ -1347,6 +1361,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
pubkey_args.label = keygen_args->pubkey_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;
/* Generate the private key on card */
if (profile->ops->create_key) {
@ -1588,6 +1603,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
{
struct sc_pkcs15_object *object;
struct sc_pkcs15_pubkey_info *key_info;
struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
sc_pkcs15_pubkey_t key;
sc_pkcs15_der_t der_encoded;
sc_path_t *path;
@ -1610,6 +1626,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
keybits = sc_pkcs15init_keybits(&key.u.dsa.q);
type = SC_PKCS15_TYPE_PUBKEY_DSA; break;
#endif
case SC_ALGORITHM_GOSTR3410:
keybits = SC_PKCS15_GOSTR3410_KEYSIZE;
type = SC_PKCS15_TYPE_PUBKEY_GOSTR3410; break;
default:
sc_error(p15card->card->ctx, "Unsupported key algorithm.\n");
return SC_ERROR_NOT_SUPPORTED;
@ -1633,6 +1652,19 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
key_info->usage = usage;
key_info->modulus_length = keybits;
if (key.algorithm == SC_ALGORITHM_GOSTR3410) {
key_info->params_len = sizeof(*keyinfo_gostparams);
/* FIXME: malloc() call in pkcs15init, but free() call
* in libopensc (sc_pkcs15_free_prkey_info) */
key_info->params = malloc(key_info->params_len);
if (!key_info->params)
return SC_ERROR_OUT_OF_MEMORY;
keyinfo_gostparams = key_info->params;
keyinfo_gostparams->gostr3410 = keyargs->gost_params.gostr3410;
keyinfo_gostparams->gostr3411 = keyargs->gost_params.gostr3411;
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;
@ -2178,6 +2210,7 @@ prkey_fixup(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_t *key)
case SC_ALGORITHM_RSA:
return prkey_fixup_rsa(p15card, &key->u.rsa);
case SC_ALGORITHM_DSA:
case SC_ALGORITHM_GOSTR3410:
/* for now */
return 0;
}
@ -2192,6 +2225,14 @@ prkey_bits(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_t *key)
return sc_pkcs15init_keybits(&key->u.rsa.modulus);
case SC_ALGORITHM_DSA:
return sc_pkcs15init_keybits(&key->u.dsa.q);
case SC_ALGORITHM_GOSTR3410:
if (sc_pkcs15init_keybits(&key->u.gostr3410.d)
> SC_PKCS15_GOSTR3410_KEYSIZE) {
sc_error(p15card->card->ctx, "Unsupported key (keybits %u)\n",
sc_pkcs15init_keybits(&key->u.gostr3410.d));
return SC_ERROR_OBJECT_NOT_VALID;
}
return SC_PKCS15_GOSTR3410_KEYSIZE;
}
sc_error(p15card->card->ctx, "Unsupported key algorithm.\n");
return SC_ERROR_NOT_SUPPORTED;
@ -2205,6 +2246,8 @@ prkey_pkcs15_algo(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_t *key)
return SC_PKCS15_TYPE_PRKEY_RSA;
case SC_ALGORITHM_DSA:
return SC_PKCS15_TYPE_PRKEY_DSA;
case SC_ALGORITHM_GOSTR3410:
return SC_PKCS15_TYPE_PRKEY_GOSTR3410;
}
sc_error(p15card->card->ctx, "Unsupported key algorithm.\n");
return SC_ERROR_NOT_SUPPORTED;

View File

@ -245,10 +245,14 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
* RSA_PUBkey Rabin test Attempts Reserve */
const unsigned char prkey_prop[] = { 0x23, 0x1F, 0, 0xFF, 0, 0 };
const unsigned char pbkey_prop[] = { 0x33, 0x1F, 0, 0xFF, 0, 0 };
/* GOSTR3410_PRkey/
* GOSTR3410_PUBkey paramset Attempts Reserve */
unsigned char prgkey_prop[] = { 0x03, '?', 0, 0xFF, 0, 0 };
unsigned char pbgkey_prop[] = { 0x13, '?', 0, 0xFF, 0, 0 };
/* AccessMode - Update Use - - - Delete */
unsigned char prkey_sec[15] = { 0x46, 0, '?', '?', 0, 0, 0, '?' };
unsigned char pbkey_sec[15] = { 0x46, 0, '?', 0, 0, 0, 0, '?' };
unsigned char auth_id;
unsigned char auth_id, paramset;
sc_pkcs15_prkey_info_t *key_info;
sc_file_t *file;
int r;
@ -257,7 +261,8 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(card->ctx, 1);
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA)
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA
&& obj->type != SC_PKCS15_TYPE_PRKEY_GOSTR3410)
return SC_ERROR_NOT_SUPPORTED;
if (obj->auth_id.len != 1)
return SC_ERROR_INVALID_ARGUMENTS;
@ -265,12 +270,29 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
key_info = (sc_pkcs15_prkey_info_t *)obj->data;
assert(key_info);
if (key_info->modulus_length % 128 != 0)
if ((obj->type == SC_PKCS15_TYPE_PRKEY_RSA
&& key_info->modulus_length % 128 != 0)
|| (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410
&& key_info->modulus_length
!= SC_PKCS15_GOSTR3410_KEYSIZE))
{
sc_error(card->ctx, "Unsupported key size %u\n",
key_info->modulus_length);
return SC_ERROR_INVALID_ARGUMENTS;
}
if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410)
{
if (key_info->params_len < sizeof(int))
return SC_ERROR_INVALID_ARGUMENTS;
if (((int*)key_info->params)[0] < 1
|| ((int*)key_info->params)[0] > 3)
return SC_ERROR_INVALID_ARGUMENTS;
paramset = ((unsigned int*)key_info->params)[0] & 0x03;
assert(sizeof(prgkey_prop)/sizeof(prgkey_prop[0]) > 1);
assert(sizeof(pbgkey_prop)/sizeof(pbgkey_prop[0]) > 1);
prgkey_prop[1] = 0x10 + (paramset << 4);
pbgkey_prop[1] = prgkey_prop[1];
}
r = sc_profile_get_file(profile, "PKCS15-AppDF", &file);
SC_TEST_RET(card->ctx, r, "Get PKCS15-AppDF info failed");
@ -287,7 +309,10 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
file->id = key_info->key_reference;
r = sc_file_set_type_attr(file, (const u8*)"\x10\x00", 2);
/* private key file */
file->size = key_info->modulus_length / 8 / 2 * 5 + 8;
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA)
file->size = key_info->modulus_length / 8 / 2 * 5 + 8;
else
file->size = key_info->modulus_length / 8;
if (r == SC_SUCCESS)
{
assert(sizeof(prkey_sec)/sizeof(prkey_sec[0]) > 7);
@ -297,11 +322,19 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
r = sc_file_set_sec_attr(file, prkey_sec, sizeof(prkey_sec));
}
if (r == SC_SUCCESS)
r = sc_file_set_prop_attr(file, prkey_prop, sizeof(prkey_prop));
{
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA)
r = sc_file_set_prop_attr(file, prkey_prop, sizeof(prkey_prop));
else
r = sc_file_set_prop_attr(file, prgkey_prop,sizeof(prgkey_prop));
}
if (r == SC_SUCCESS)
r = sc_create_file(card, file);
/* public key file */
file->size = key_info->modulus_length / 8 / 2 * 3;
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA)
file->size = key_info->modulus_length / 8 / 2 * 3;
else
file->size = key_info->modulus_length / 8 * 2;
if (r == SC_SUCCESS)
{
assert(sizeof(pbkey_sec)/sizeof(pbkey_sec[0]) > 7);
@ -310,7 +343,12 @@ static int rtecp_create_key(sc_profile_t *profile, sc_card_t *card,
r = sc_file_set_sec_attr(file, pbkey_sec, sizeof(pbkey_sec));
}
if (r == SC_SUCCESS)
r = sc_file_set_prop_attr(file, pbkey_prop, sizeof(pbkey_prop));
{
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA)
r = sc_file_set_prop_attr(file, pbkey_prop, sizeof(pbkey_prop));
else
r = sc_file_set_prop_attr(file, pbgkey_prop,sizeof(pbgkey_prop));
}
if (r == SC_SUCCESS)
r = sc_create_file(card, file);
assert(file);
@ -328,72 +366,98 @@ static int rtecp_store_key(sc_profile_t *profile, sc_card_t *card,
sc_file_t *pukey_df;
sc_path_t path;
unsigned char *buf;
size_t len, i;
size_t buf_len, key_len, len, i;
int r;
if (!profile || !card || !card->ctx || !obj || !obj->data || !key)
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(card->ctx, 1);
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA || key->algorithm != SC_ALGORITHM_RSA)
if ((obj->type != SC_PKCS15_TYPE_PRKEY_RSA || key->algorithm != SC_ALGORITHM_RSA)
&& (obj->type != SC_PKCS15_TYPE_PRKEY_GOSTR3410
|| key->algorithm != SC_ALGORITHM_GOSTR3410))
return SC_ERROR_NOT_SUPPORTED;
key_info = (sc_pkcs15_prkey_info_t *)obj->data;
assert(key_info);
assert(key_info->modulus_length % 128 == 0);
len = key_info->modulus_length / 8 / 2;
if (!key->u.rsa.p.data || !key->u.rsa.q.data || !key->u.rsa.iqmp.data
if (key->algorithm == SC_ALGORITHM_RSA)
{
assert(key_info->modulus_length % 128 == 0);
len = key_info->modulus_length / 8 / 2;
key_len = len * 5 + 8;
buf_len = key_len;
}
else
{
assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE);
len = key_info->modulus_length / 8;
key_len = len;
buf_len = len;
}
if (key->algorithm == SC_ALGORITHM_RSA && (!key->u.rsa.p.data
|| !key->u.rsa.q.data || !key->u.rsa.iqmp.data
|| !key->u.rsa.dmp1.data || !key->u.rsa.dmq1.data
|| !key->u.rsa.modulus.data || !key->u.rsa.exponent.data
|| key->u.rsa.p.len != len || key->u.rsa.q.len != len
|| key->u.rsa.iqmp.len != len || key->u.rsa.dmp1.len != len
|| key->u.rsa.dmq1.len != len || key->u.rsa.modulus.len != 2*len
|| key->u.rsa.exponent.len > len || key->u.rsa.exponent.len == 0)
|| key->u.rsa.exponent.len > len || key->u.rsa.exponent.len == 0))
return SC_ERROR_INVALID_ARGUMENTS;
buf = calloc(1, len * 5 + 8);
if (key->algorithm == SC_ALGORITHM_GOSTR3410 && (!key->u.gostr3410.d.data
|| key->u.gostr3410.d.len != len))
return SC_ERROR_INVALID_ARGUMENTS;
buf = calloc(1, buf_len);
if (!buf)
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
assert(key->u.rsa.p.data && key->u.rsa.q.data && key->u.rsa.iqmp.data
&& key->u.rsa.dmp1.data && key->u.rsa.dmq1.data
&& key->u.rsa.p.len == len && key->u.rsa.q.len == len
&& key->u.rsa.iqmp.len == len
&& key->u.rsa.dmp1.len == len
&& key->u.rsa.dmq1.len == len);
/* p */
for (i = 0; i < len; ++i)
buf[i] = key->u.rsa.p.data[len - 1 - i];
/* q */
for (i = 0; i < len; ++i)
buf[len + 4 + i] = key->u.rsa.q.data[len - 1 - i];
/* iqmp */
for (i = 0; i < len; ++i)
buf[len + 4 + len + 4 + i] = key->u.rsa.iqmp.data[len - 1 - i];
/* dmp1 */
for (i = 0; i < len; ++i)
buf[len + 4 + len + 4 + len + i] = key->u.rsa.dmp1.data[len - 1 - i];
/* dmq1 */
for (i = 0; i < len; ++i)
buf[len * 4 + 8 + i] = key->u.rsa.dmq1.data[len - 1 - i];
assert(key_len <= buf_len);
if (key->algorithm == SC_ALGORITHM_RSA)
{
/* p */
for (i = 0; i < len; ++i)
buf[i] = key->u.rsa.p.data[len - 1 - i];
/* q */
for (i = 0; i < len; ++i)
buf[len + 4 + i] = key->u.rsa.q.data[len - 1 - i];
/* iqmp */
for (i = 0; i < len; ++i)
buf[len + 4 + len + 4 + i] = key->u.rsa.iqmp.data[len - 1 - i];
/* dmp1 */
for (i = 0; i < len; ++i)
buf[len + 4 + len + 4 + len + i] =
key->u.rsa.dmp1.data[len - 1 - i];
/* dmq1 */
for (i = 0; i < len; ++i)
buf[len * 4 + 8 + i] = key->u.rsa.dmq1.data[len - 1 - i];
}
else
{
/* d */
for (i = 0; i < len; ++i)
buf[i] = key->u.gostr3410.d.data[len - 1 - i];
}
path = key_info->path;
r = sc_select_file(card, &path, NULL);
if (r == SC_SUCCESS)
r = sc_change_reference_data(card, 0, 0, NULL, 0, buf, len*5 + 8, NULL);
r = sc_change_reference_data(card, 0, 0, NULL, 0, buf, key_len, NULL);
assert(buf);
sc_mem_clear(buf, len * 5 + 8);
sc_mem_clear(buf, key_len);
/* store public key */
assert(key->u.rsa.modulus.data && key->u.rsa.exponent.data
&& key->u.rsa.modulus.len == 2*len
&& key->u.rsa.exponent.len <= len
&& key->u.rsa.exponent.len > 0);
/* modulus */
for (i = 0; i < 2*len; ++i)
buf[i] = key->u.rsa.modulus.data[2*len - 1 - i];
/* exponent */
for (i = 0; i < key->u.rsa.exponent.len && i < len; ++i)
buf[2*len+i] = key->u.rsa.exponent.data[key->u.rsa.exponent.len - 1 - i];
if (key->algorithm == SC_ALGORITHM_RSA)
key_len = len * 3;
else
goto end;
assert(key_len <= buf_len);
if (key->algorithm == SC_ALGORITHM_RSA)
{
/* modulus */
for (i = 0; i < 2*len; ++i)
buf[i] = key->u.rsa.modulus.data[2*len - 1 - i];
/* exponent */
for (i = 0; i < key->u.rsa.exponent.len && i < len; ++i)
buf[2 * len + i] = key->u.rsa.exponent.data[
key->u.rsa.exponent.len - 1 - i];
}
if (r == SC_SUCCESS)
{
r = sc_profile_get_file(profile, "PuKey-DF", &pukey_df);
@ -412,10 +476,11 @@ static int rtecp_store_key(sc_profile_t *profile, sc_card_t *card,
r = sc_select_file(card, &path, NULL);
if (r == SC_SUCCESS)
r = sc_change_reference_data(card, 0, 0, NULL, 0,
buf, len*3, NULL);
buf, key_len, NULL);
if (r && card->ctx->debug >= 2)
sc_debug(card->ctx, "%s\n", "Store public key failed");
}
end:
assert(buf);
free(buf);
SC_FUNC_RETURN(card->ctx, 1, r);
@ -435,33 +500,72 @@ static int rtecp_generate_key(sc_profile_t *profile, sc_card_t *card,
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(card->ctx, 1);
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA)
switch (obj->type)
{
case SC_PKCS15_TYPE_PRKEY_RSA:
data.type = SC_ALGORITHM_RSA;
break;
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
data.type = SC_ALGORITHM_GOSTR3410;
break;
default:
return SC_ERROR_NOT_SUPPORTED;
}
key_info = (sc_pkcs15_prkey_info_t *)obj->data;
assert(key_info);
data.key_id = key_info->key_reference;
assert(data.key_id != 0);
assert(key_info->modulus_length % 128 == 0);
data.modulus_len = key_info->modulus_length / 8;
data.modulus = calloc(1, data.modulus_len);
data.exponent_len = key_info->modulus_length / 8 / 2;
data.exponent = calloc(1, data.exponent_len);
if (!data.modulus || !data.exponent)
switch (data.type)
{
free(data.modulus);
free(data.exponent);
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
case SC_ALGORITHM_RSA:
assert(key_info->modulus_length % 128 == 0);
data.u.rsa.modulus_len = key_info->modulus_length / 8;
data.u.rsa.modulus = calloc(1, data.u.rsa.modulus_len);
data.u.rsa.exponent_len = key_info->modulus_length / 8 / 2;
data.u.rsa.exponent = calloc(1, data.u.rsa.exponent_len);
if (!data.u.rsa.modulus || !data.u.rsa.exponent)
{
free(data.u.rsa.modulus);
free(data.u.rsa.exponent);
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
}
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)
{
free(data.u.gostr3410.x);
free(data.u.gostr3410.y);
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
}
break;
default:
assert(0);
}
r = sc_card_ctl(card, SC_CARDCTL_RTECP_GENERATE_KEY, &data);
if (r == SC_SUCCESS)
{
assert(pubkey);
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.data = data.modulus;
pubkey->u.rsa.modulus.len = data.modulus_len;
pubkey->u.rsa.exponent.data = data.exponent;
pubkey->u.rsa.exponent.len = data.exponent_len;
pubkey->algorithm = data.type;
switch (data.type)
{
case SC_ALGORITHM_RSA:
pubkey->u.rsa.modulus.data = data.u.rsa.modulus;
pubkey->u.rsa.modulus.len = data.u.rsa.modulus_len;
pubkey->u.rsa.exponent.data = data.u.rsa.exponent;
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;
break;
}
}
SC_FUNC_RETURN(card->ctx, 1, r);
}