MyEID ECDSA support

This commit is contained in:
sjoblomt 2012-11-28 12:52:43 +02:00 committed by Viktor Tarasov
parent 9e9b3d0bd8
commit 457426543d
10 changed files with 795 additions and 422 deletions

View File

@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
*/
#include "config.h"
@ -35,10 +35,17 @@
#define LOAD_KEY_DP1 0x85
#define LOAD_KEY_DQ1 0x86
#define LOAD_KEY_INVQ 0x87
#define LOAD_KEY_MODE_EC_PRIV 0x87
#define LOAD_KEY_MODE_EC_PUB 0x86
#define LOAD_KEY_EC_PRIVATE 0x97
#define LOAD_KEY_EC_PUBLIC 0x96
#define MYEID_STATE_CREATION 0x01
#define MYEID_STATE_ACTIVATED 0x07
#define MYEID_ECC_SUPPORT
static struct sc_card_operations myeid_ops;
static struct sc_card_driver myeid_drv = {
"MyEID cards with PKCS#15 applet",
@ -52,7 +59,9 @@ static struct sc_card_driver myeid_drv = {
static const char *myeid_atrs[] = {
"3B:F5:18:00:FF:81:31:FE:45:4D:79:45:49:44:65",
"3B:F5:18:00:00:81:31:FE:45:4D:79:45:49:44:9A",
NULL
"3B:85:80:01:4D:79:45:49:44:78",
"3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C",
NULL
};
typedef struct myeid_private_data {
@ -86,7 +95,8 @@ static int myeid_match_card(struct sc_card *card)
static int myeid_init(struct sc_card *card)
{
unsigned long flags =0;
unsigned long flags = 0,
ext_flags = 0;
myeid_private_data_t *priv;
LOG_FUNC_CALLED(card->ctx);
@ -97,11 +107,23 @@ static int myeid_init(struct sc_card *card)
card->drv_data = priv;
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN;
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_ONBOARD_KEY_GEN;
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
_sc_card_add_rsa_alg(card, 512, flags, 0);
_sc_card_add_rsa_alg(card, 768, flags, 0);
_sc_card_add_rsa_alg(card, 1024, flags, 0);
_sc_card_add_rsa_alg(card, 1536, flags, 0);
_sc_card_add_rsa_alg(card, 2048, flags, 0);
#ifdef MYEID_ECC_SUPPORT
flags |= SC_ALGORITHM_ECDSA_RAW;
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
_sc_card_add_ec_alg(card, 192, flags, ext_flags);
_sc_card_add_ec_alg(card, 224, flags, ext_flags);
_sc_card_add_ec_alg(card, 256, flags, ext_flags);
#endif
/* State that we have an RNG */
card->caps |= SC_CARD_CAP_RNG;
@ -282,7 +304,7 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
u8 *out, size_t *outlen)
{
const sc_acl_entry_t *read, *update, *delete, *generate;
const sc_acl_entry_t *read, *update, *delete, *generate;
u8 buf[40];
int i;
@ -290,12 +312,12 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
/* PrivateKey
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
memset(buf,0x0,sizeof(buf));
memset(buf, 0x0, sizeof(buf));
buf[0] = 0x62;
buf[1] = 0x17;
/* File size */
buf[2] = (SC_FILE_TYPE_WORKING_EF == file->type ?0x80:0x81);
buf[2] = (SC_FILE_TYPE_WORKING_EF == file->type ? 0x80 : 0x81);
buf[3] = 0x02;
buf[4] = (file->size >> 8) & 0xFF;
buf[5] = file->size & 0xFF;
@ -365,8 +387,9 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
buf[18] = 0x85;
buf[19] = 0x02;
/* AC right to clear default 0 */
buf[20] = (SC_FILE_TYPE_INTERNAL_EF == file->type ?0x0:0x80);
buf[21] = 0x0;
/* TODO: Implement this */
buf[20] = 0x00; /*(SC_FILE_TYPE_INTERNAL_EF == file->type ? 0x00 : 0x80);*/
buf[21] = 0x00;
/* Life Cycle Status tag */
buf[22] = 0x8A;
@ -379,7 +402,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
break;
case SC_FILE_TYPE_INTERNAL_EF:
buf[8] = 0x11;
buf[8] = file->ef_structure; /* RSA or EC */
break;
case SC_FILE_TYPE_DF:
@ -479,7 +502,7 @@ static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
LOG_FUNC_RETURN(card->ctx, iso_ops->pin_cmd(card, data, tries_left));
}
static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env,
static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *env,
int se_num)
{
sc_apdu_t apdu;
@ -576,6 +599,103 @@ err:
LOG_FUNC_RETURN(card->ctx, r);
}
static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env,
int se_num)
{
sc_apdu_t apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 *p;
int r, locked = 0;
assert(card != NULL && env != NULL);
LOG_FUNC_CALLED(card->ctx);
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
{
sc_log(card->ctx, "asymmetric keyref not supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
if (se_num > 0)
{
sc_log(card->ctx, "restore security environment not supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation)
{
case SC_SEC_OPERATION_DECIPHER:
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n");
return SC_ERROR_NOT_SUPPORTED;
break;
case SC_SEC_OPERATION_SIGN:
apdu.p1 = 0x41;
apdu.p2 = 0xB6;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
apdu.le = 0;
p = sbuf;
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT)
{
*p++ = 0x80; /* algorithm reference */
*p++ = 0x01;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
{
*p++ = 0x81;
*p++ = 0x02;
memcpy(p, env->file_ref.value, 2);
p += 2;
}
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
{
*p++ = 0x84;
*p++ = 1;
*p++ = 0;
}
r = p - sbuf;
apdu.lc = r;
apdu.datalen = r;
apdu.data = sbuf;
apdu.resplen = 0;
if (se_num > 0) {
r = sc_lock(card);
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
locked = 1;
}
if (apdu.datalen != 0)
{
r = sc_transmit_apdu(card, &apdu);
if (r)
{
sc_log(card->ctx,
"%s: APDU transmit failed", sc_strerror(r));
goto err;
}
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r)
{
sc_log(card->ctx,
"%s: Card returned error", sc_strerror(r));
goto err;
}
}
if (se_num <= 0)
return 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
r = sc_transmit_apdu(card, &apdu);
sc_unlock(card);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_check_sw(card, apdu.sw1, apdu.sw2);
err:
if (locked)
sc_unlock(card);
LOG_FUNC_RETURN(card->ctx, r);
}
static int myeid_set_security_env(struct sc_card *card,
const struct sc_security_env *env, int se_num)
{
@ -588,22 +708,39 @@ static int myeid_set_security_env(struct sc_card *card,
tmp = *env;
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
if (tmp.algorithm != SC_ALGORITHM_RSA)
if (tmp.algorithm == SC_ALGORITHM_RSA)
{
sc_log(card->ctx, "Only RSA algorithm supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
/* potential FIXME: return an error, if an unsupported
* pad or hash was requested, although this shouldn't happen */
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
tmp.algorithm_ref = 0x02;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
tmp.algorithm_ref |= 0x10;
tmp.algorithm_ref = 0x00;
/* potential FIXME: return an error, if an unsupported
* pad or hash was requested, although this shouldn't happen */
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
tmp.algorithm_ref = 0x02;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
tmp.algorithm_ref |= 0x10;
return myeid_set_security_env2(card, &tmp, se_num);
return myeid_set_security_env_rsa(card, &tmp, se_num);
}
else if (tmp.algorithm == SC_ALGORITHM_EC)
{
#ifdef MYEID_ECC_SUPPORT
/* TODO: Update the algorithm_ref */
tmp.algorithm_ref = 0xAA;
tmp.algorithm_flags = 0;
return myeid_set_security_env_ec(card, &tmp, se_num);
#else
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Elliptic curves are not supported in this version.\n");
return SC_ERROR_NOT_SUPPORTED;
#endif
}
else
{
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported algorithm.\n");
return SC_ERROR_NOT_SUPPORTED;
}
}
return myeid_set_security_env2(card, env, se_num);
return myeid_set_security_env_rsa(card, env, se_num);
}
static int myeid_compute_signature(struct sc_card *card, const u8 * data,
@ -618,42 +755,42 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
assert(card != NULL && data != NULL && out != NULL);
if (datalen > 256)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
/* INS: 0x2A PERFORM SECURITY OPERATION
* P1: 0x9E Resp: Digital Signature
* P2: 0x9A Cmd: Input for Digital Signature */
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
/* INS: 0x2A PERFORM SECURITY OPERATION
* P1: 0x9E Resp: Digital Signature
* P2: 0x9A Cmd: Input for Digital Signature */
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
if (datalen == 256)
{
apdu.p2 = data[0];
memcpy(sbuf, data+1, datalen-1);
apdu.lc = datalen - 1;
apdu.datalen = datalen - 1;
apdu.p2 = data[0];
memcpy(sbuf, data+1, datalen-1);
apdu.lc = datalen - 1;
apdu.datalen = datalen - 1;
}
else
{
memcpy(sbuf, data, datalen);
apdu.lc = datalen;
apdu.datalen = datalen;
memcpy(sbuf, data, datalen);
apdu.lc = datalen;
apdu.datalen = datalen;
}
apdu.data = sbuf;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
apdu.data = sbuf;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
{
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len);
LOG_FUNC_RETURN(card->ctx, len);
}
}
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
static int myeid_decipher(struct sc_card *card, const u8 * crgram,
@ -683,7 +820,8 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
apdu.le = crgram_len;
if (crgram_len == 256)
{ apdu.le = 0;
{
apdu.le = 0;
/* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */
sbuf[0] = 0x81;
memcpy(sbuf + 1, crgram, crgram_len / 2);
@ -696,7 +834,8 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
apdu.lc = crgram_len + 1;
}
apdu.datalen = apdu.lc; apdu.data = sbuf;
apdu.datalen = apdu.lc;
apdu.data = sbuf;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -818,8 +957,6 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
mode != LOAD_KEY_PUBLIC_EXPONENT)
sbuf[len++] = 0x0;
LOG_FUNC_CALLED(card->ctx);
if(mode == LOAD_KEY_MODULUS && value_len >= 256)
{
r=0;
@ -852,6 +989,16 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
memset(&sbuf, 0, SC_MAX_APDU_BUFFER_SIZE);
memcpy(sbuf,value + 128, value_len - 128);
}
else if(mode == LOAD_KEY_EC_PRIVATE) {
memcpy(sbuf, value, value_len);
len = value_len;
mode = LOAD_KEY_MODE_EC_PRIV;
}
else if(mode == LOAD_KEY_EC_PUBLIC) {
memcpy(sbuf, value, value_len);
len = value_len;
mode = LOAD_KEY_MODE_EC_PUB;
}
else
{
memcpy(sbuf + len, value, value_len);
@ -865,7 +1012,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
apdu.data = sbuf;
apdu.datalen = len;
apdu.lc = len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -886,22 +1033,34 @@ static int myeid_generate_store_key(struct sc_card *card,
if (data->op_type == OP_TYPE_GENERATE)
{
len = 0;
sbuf[len++] = 0x30;
sbuf[len++] = 0x05;
sbuf[len++] = 0x81;
sbuf[len++] = data->pubexp_len;
memcpy(sbuf + len, data->pubexp, data->pubexp_len);
len += data->pubexp_len;
memset(&apdu, 0, sizeof(apdu));
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA)
{
sbuf[len++] = 0x30;
sbuf[len++] = 0x05;
sbuf[len++] = 0x81;
sbuf[len++] = data->pubexp_len;
memcpy(sbuf + len, data->pubexp, data->pubexp_len);
len += data->pubexp_len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
apdu.data = sbuf;
}
else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) {
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x46, 0x00, 0x00);
apdu.data = NULL;
apdu.resp = sbuf;
apdu.resplen = 0x00;
apdu.le = 0x00;
}
apdu.cla = 0x00;
apdu.data = sbuf;
apdu.datalen = len;
apdu.lc = len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -910,21 +1069,31 @@ static int myeid_generate_store_key(struct sc_card *card,
}
else
{
if((r=myeid_loadkey(card, LOAD_KEY_PRIME_P,
data->primep, data->primep_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_PRIME_Q,
data->primeq, data->primeq_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_DP1,
data->dp1, data->dp1_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_DQ1,
data->dq1, data->dq1_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_INVQ,
data->invq, data->invq_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_MODULUS,
data->mod, data->mod_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT,
data->pubexp, data->pubexp_len)) >= 0)
if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA)
{
if((r=myeid_loadkey(card, LOAD_KEY_PRIME_P,
data->primep, data->primep_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_PRIME_Q,
data->primeq, data->primeq_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_DP1,
data->dp1, data->dp1_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_DQ1,
data->dq1, data->dq1_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_INVQ,
data->invq, data->invq_len)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_MODULUS,
data->mod, data->key_len_bits)) >= 0 &&
(r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT,
data->pubexp, data->pubexp_len)) >= 0)
LOG_FUNC_RETURN(card->ctx, r);
}
else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) {
if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d,
data->d_len)) >= 0 &&
(r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point,
data->ecpublic_point_len)) >= 0)
LOG_FUNC_RETURN(card->ctx, r);
}
}
LOG_FUNC_RETURN(card->ctx, r);
@ -952,17 +1121,17 @@ static int myeid_activate_card(struct sc_card *card)
LOG_FUNC_RETURN(card->ctx, r);
}
static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen)
{
int r;
sc_apdu_t apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
LOG_FUNC_CALLED(card->ctx);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
apdu.resplen = buflen;
apdu.le = buflen;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -972,13 +1141,41 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
if (apdu.resplen != 20)
{
sc_log(card->ctx, "unexpected response to GET DATA serial number\n");
sc_log(card->ctx, "Unexpected response to GET DATA (applet info)\n");
return SC_ERROR_INTERNAL;
}
}
/* store the applet version */
card->version.fw_major = rbuf[5] * 10 + rbuf[6];
card->version.fw_minor = rbuf[7];
/* add version to name */
u8 nameBuf[100];
sprintf(nameBuf, "%s %d.%d.%d", card->name, rbuf[5], rbuf[6], rbuf[7]);
card->name = nameBuf;
//card->driver->name
LOG_FUNC_RETURN(card->ctx, r);
}
static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
{
int r;
u8 rbuf[256];
LOG_FUNC_CALLED(card->ctx);
/* if number cached, get it
if(card->serialnr.value) {
memcpy(serial, &card->serialnr, sizeof(*serial));
LOG_FUNC_RETURN(card->ctx, r);
}*/
/* get number from card */
r = myeid_get_info(card, rbuf, sizeof(rbuf));
LOG_TEST_RET(card->ctx, r, "Get applet info failed");
/* cache serial number */
memcpy(card->serialnr.value, &rbuf[10], 8);
card->serialnr.len = 8;
memcpy(card->serialnr.value, &rbuf[8], 10);
card->serialnr.len = 10;
/* copy and return serial number */
memcpy(serial, &card->serialnr, sizeof(*serial));

View File

@ -821,8 +821,16 @@ typedef struct sc_rtecp_genkey_data {
} sc_rtecp_genkey_data_t;
/*
* MyEID stuff
*/
* MyEID stuff
*/
enum SC_CARDCTL_MYEID_KEY_TYPE {
SC_CARDCTL_MYEID_KEY_RSA = 0x11,
SC_CARDCTL_MYEID_KEY_EC = 0x21,
/* SC_CARDCTL_MYEID_KEY_AES = 0x?, // for future use
SC_CARDCTL_MYEID_KEY_DES = 0x?,
SC_CARDCTL_MYEID_KEY_3DES = 0x?, */
};
struct sc_cardctl_myeid_data_obj {
int P1;
int P2;
@ -832,22 +840,28 @@ typedef struct sc_rtecp_genkey_data {
};
struct sc_cardctl_myeid_gen_store_key_info {
int op_type;
unsigned int mod_len;
unsigned char *mod;
unsigned int pubexp_len;
unsigned char *pubexp;
unsigned int primep_len;
unsigned char *primep;
unsigned int primeq_len;
unsigned char *primeq;
unsigned int dp1_len;
unsigned char *dp1;
unsigned int dq1_len;
unsigned char *dq1;
unsigned int invq_len;
unsigned char *invq;
};
int op_type;
unsigned int key_type; /* value of SC_CARDCTL_MYEID_KEY_TYPE */
unsigned int key_len_bits;
unsigned char *mod;
unsigned int pubexp_len;
unsigned char *pubexp;
unsigned int primep_len;
unsigned char *primep;
unsigned int primeq_len;
unsigned char *primeq;
unsigned int dp1_len;
unsigned char *dp1;
unsigned int dq1_len;
unsigned char *dq1;
unsigned int invq_len;
unsigned char *invq;
/* new for MyEID > 3.6.0 */
unsigned char *d; /* EC private key */
unsigned int d_len; /* EC */
unsigned char *ecpublic_point; /* EC public key */
unsigned int ecpublic_point_len; /* EC */
};
/*
* PIV info

View File

@ -576,6 +576,14 @@ sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key)
break;
case SC_ALGORITHM_EC:
/* TODO: -DEE may not need much */
if (key->u.ec.params.der.value)
free(key->u.ec.params.der.value);
if (key->u.ec.params.named_curve)
free(key->u.ec.params.named_curve);
if (key->u.ec.privateD.data)
free(key->u.ec.privateD.data);
if (key->u.ec.ecpointQ.value)
free(key->u.ec.ecpointQ.value);
break;
}
}
@ -658,6 +666,53 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key)
sc_pkcs15_convert_bignum(&dst->d, EC_KEY_get0_private_key(src));
break;
}
case EVP_PKEY_EC: {
struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec;
EC_KEY *src = EVP_PKEY_get0(pk);
assert(src);
pkcs15_key->algorithm = SC_ALGORITHM_EC;
assert(EC_KEY_get0_private_key(src));
if (!sc_pkcs15_convert_bignum(&dst->privateD, EC_KEY_get0_private_key(src)))
return SC_ERROR_INCOMPATIBLE_KEY;
assert(EC_KEY_get0_public_key(src));
unsigned char buf[255];
size_t buflen = 255;
const EC_GROUP *grp = EC_KEY_get0_group(src);
if(grp == 0) {
//EC_KEY_free(src);
return SC_ERROR_INCOMPATIBLE_KEY;
}
/* get curve name */
int nid;
nid = EC_GROUP_get_curve_name(grp);
if(nid != 0)
dst->params.named_curve = strdup(OBJ_nid2sn(nid));
/* Decode EC_POINT from a octet string */
buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src),
POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL);
/* clean up */
//EC_KEY_free(src);
/* copy the public key */
if (buflen > 0) {
dst->ecpointQ.value = malloc(buflen);
memcpy(dst->ecpointQ.value, buf, buflen);
dst->ecpointQ.len = buflen;
/* calculate the field length */
dst->params.field_length = (buflen - 1) / 2 * 8;
}
else
return SC_ERROR_INCOMPATIBLE_KEY;
break;
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */
default:
return SC_ERROR_NOT_SUPPORTED;

View File

@ -81,12 +81,33 @@ static const struct sc_asn1_entry c_asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE] =
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_ECKEY_VALUE_CHOICE_SIZE 3
static const struct sc_asn1_entry c_asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE] = {
{ "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_EMPTY_ALLOWED, NULL, NULL },
{ "direct", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_ECKEY_ATTR_SIZE 4
static const struct sc_asn1_entry c_asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE] = {
{ "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL },
{ "fieldSize", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_RSA_TYPE_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE] = {
{ "publicRSAKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_EC_TYPE_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE] = {
{ "publicECKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_DSAKEY_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE] = {
{ "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
@ -114,11 +135,12 @@ static const struct sc_asn1_entry c_asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYP
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_PUBKEY_CHOICE_SIZE 4
#define C_ASN1_PUBKEY_CHOICE_SIZE 5
static const struct sc_asn1_entry c_asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE] = {
{ "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, 4 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL },
{ "publicECKey", SC_ASN1_PKCS15_OBJECT, 0 | SC_ASN1_CTX | SC_ASN1_CONS, 0, NULL, NULL },
/*TODO: -DEE not clear EC is needed here as look like it is for pukdf */
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -145,6 +167,9 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE];
struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE];
struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE];
@ -153,6 +178,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE];
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 eckey_obj = { obj, asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_ec_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,
@ -163,6 +190,9 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr);
sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice);
sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_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);
@ -175,6 +205,7 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
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_pubkey_choice + 3, &eckey_obj, NULL, 0);
sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 0);
@ -184,6 +215,14 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 0);
sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0);
sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 0);
sc_format_asn1_entry(asn1_eckey_value_choice + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_eckey_value_choice + 1, &der->value, &der->len, 0);
sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 0);
sc_format_asn1_entry(asn1_eckey_attr + 1, &info.field_length, NULL, 0);
sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 0);
sc_format_asn1_entry(asn1_dsakey_attr + 0, &info.path, NULL, 0);
@ -229,7 +268,11 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
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 {
}
else if (asn1_pubkey_choice[3].flags & SC_ASN1_PRESENT) {
obj->type = SC_PKCS15_TYPE_PUBKEY_EC;
}
else {
obj->type = SC_PKCS15_TYPE_PUBKEY_DSA;
}
if (!p15card->app || !p15card->app->ddo.aid.len) {
@ -269,17 +312,24 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE];
struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE];
struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE];
struct sc_asn1_entry asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYPE_ATTR_SIZE];
struct sc_asn1_entry asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE];
struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE];
struct sc_pkcs15_pubkey_info *pubkey =
(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 eckey_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_key_attr,
asn1_com_pubkey_attr, asn1_ec_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 };
@ -295,6 +345,9 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr);
sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice);
sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr);
sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice);
sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_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);
@ -338,9 +391,21 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
sc_format_asn1_entry(asn1_gostr3410key_attr + 3,
&keyinfo_gostparams->gost28147, NULL, 1);
}
break;
case SC_PKCS15_TYPE_PUBKEY_EC:
/* MyEID is a PKCS15 card with ECC */
sc_format_asn1_entry(asn1_pubkey_choice + 3, &eckey_obj, NULL, 1);
sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 1);
if (pubkey->path.len || !obj->content.value)
sc_format_asn1_entry(asn1_eckey_value_choice + 0, &pubkey->path, NULL, 1);
else
sc_format_asn1_entry(asn1_eckey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1);
sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 1);
sc_format_asn1_entry(asn1_eckey_attr + 1, &pubkey->field_length, NULL, 1);
break;
default:
/* TODO: -DEE Should add ECC but don't have PKCS15 card with ECC */
sc_log(ctx, "Unsupported public key type: %X", obj->type);
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
break;
@ -581,12 +646,22 @@ int
sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key,
u8 **buf, size_t *buflen)
{
*buf = malloc(key->ecpointQ.len);
int r;
/*u8 * ecpoint_data;
size_t ecpoint_len;*/
struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE];
/*buf = malloc(key->ecpointQ.len);
if (*buf == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(*buf, key->ecpointQ.value, key->ecpointQ.len);
return SC_ERROR_OUT_OF_MEMORY;*/
sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ);
sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key->ecpointQ.len, 1);
/* memcpy(*buf, key->ecpointQ.value, key->ecpointQ.len);
*buflen = key->ecpointQ.len;
*/
r = sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen);
sc_log(ctx, "DEE-EC key->ecpointQ=%p:%d *buf=%p:%d", key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen);
return 0;
@ -754,6 +829,12 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv
break;
case SC_ALGORITHM_GOSTR3410:
break;
case SC_ALGORITHM_EC:
pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len);
memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len);
pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len;
rv = SC_SUCCESS;
break;
default:
sc_log(ctx, "Unsupported private key algorithm");
return SC_ERROR_NOT_SUPPORTED;
@ -1175,6 +1256,52 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
return SC_ERROR_INTERNAL;
break;
}
case EVP_PKEY_EC: {
struct sc_pkcs15_pubkey_ec *dst = &pkcs15_key->u.ec;
EC_KEY *src = EVP_PKEY_get0(pk);
assert(src);
pkcs15_key->algorithm = SC_ALGORITHM_EC;
assert(EC_KEY_get0_public_key(src));
unsigned char buf[255];
size_t buflen = 255;
const EC_GROUP *grp = EC_KEY_get0_group(src);
if(grp == 0) {
//EC_KEY_free(src);
return SC_ERROR_INCOMPATIBLE_KEY;
}
/* Decode EC_POINT from a octet string */
buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src),
POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL);
/* get curve name */
int nid;
nid = EC_GROUP_get_curve_name(grp);
if(nid != 0) {
const char *name = OBJ_nid2sn(nid);
if(sizeof(name) > 0)
dst->params.named_curve = strdup(name);
}
/* clean up */
//EC_KEY_free(src);
/* copy the public key */
if (buflen > 0) {
dst->ecpointQ.value = malloc(buflen);
memcpy(dst->ecpointQ.value, buf, buflen);
dst->ecpointQ.len = buflen;
/* calculate the field length */
dst->params.field_length = (buflen - 1) / 2 * 8;
}
else
return SC_ERROR_INCOMPATIBLE_KEY;
break;
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */
default:
return SC_ERROR_NOT_SUPPORTED;

View File

@ -303,7 +303,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
sc_security_env_t senv;
sc_algorithm_info_t *alg_info;
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
u8 buf[512], *tmp;
u8 buf[1024], *tmp;
size_t modlen;
unsigned long pad_flags = 0, sec_flags = 0;

View File

@ -220,6 +220,7 @@ struct sc_pkcs15_pubkey_ec {
struct sc_pkcs15_prkey_ec {
struct sc_pkcs15_ec_parameters params;
sc_pkcs15_bignum_t privateD; /* note this is bignum */
sc_pkcs15_der_t ecpointQ; /* note this is der */
};
struct sc_pkcs15_pubkey_gostr3410 {

View File

@ -17,17 +17,17 @@ cardinfo {
#
pkcs15 {
# Put certificates into the CDF itself?
direct-certificates = no;
direct-certificates = no;
# Put the DF length into the ODF file?
encode-df-length = no;
encode-df-length = no;
# Have a lastUpdate field in the EF(TokenInfo)?
do-last-update = no;
do-last-update = no;
}
option default {
macros {
#protected = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
#unprotected = READ=NONE, UPDATE=CHV1, DELETE=CHV1;
#protected = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
#unprotected = READ=NONE, UPDATE=CHV1, DELETE=CHV1;
unusedspace-size = 510;
odf-size = 255;
@ -36,7 +36,7 @@ option default {
cdf-trusted-size = 510;
prkdf-size = 1530;
pukdf-size = 1530;
dodf-size = 255;
dodf-size = 1530;
}
}
@ -195,6 +195,16 @@ filesystem {
structure = transparent;
acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN;
}
EF privdata {
file-id = 4501;
structure = transparent;
acl = READ=$PIN, UPDATE=$PIN, DELETE=$PIN;
}
EF data {
file-id = 4501;
structure = transparent;
acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN;
}
}
}
}

View File

@ -1528,7 +1528,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
keyinfo_gostparams->gostr3411 = keyargs->params.gost.gostr3411;
keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147;
}
else if(key.algorithm == SC_ALGORITHM_EC)
key_info->field_length = keybits;
/* Select a intrinsic Key ID if the user didn't specify one */
r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, &key);
LOG_TEST_RET(ctx, r, "Get intrinsic ID error");
@ -1974,7 +1976,8 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *
count = p15card->card->algorithm_count;
for (info = p15card->card->algorithms; count--; info++) {
if (info->algorithm != key->algorithm || info->key_length != key_length || (info->flags & flags) != flags)
/* don't check flags if none was specified */
if (info->algorithm != key->algorithm || info->key_length != key_length || (flags != 0 && (info->flags & flags) != flags))
continue;
if (key->algorithm == SC_ALGORITHM_RSA) {
@ -2106,7 +2109,11 @@ prkey_bits(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key)
sc_log(ctx, "Unsupported key (keybits %u)", sc_pkcs15init_keybits(&key->u.gostr3410.d));
return SC_ERROR_OBJECT_NOT_VALID;
}
return SC_PKCS15_GOSTR3410_KEYSIZE;
return SC_PKCS15_GOSTR3410_KEYSIZE;
case SC_ALGORITHM_EC:
/* calculation returns one bit too small, add one bu default */
sc_log(ctx, "Private EC key length %u", sc_pkcs15init_keybits(&key->u.ec.privateD) + 1);
return sc_pkcs15init_keybits(&key->u.ec.privateD) + 1;
}
sc_log(ctx, "Unsupported key algorithm.");
return SC_ERROR_NOT_SUPPORTED;
@ -2197,6 +2204,8 @@ select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 &&
!pubkey->u.gostr3410.xy.data)
goto done;
else if (pubkey->algorithm == SC_ALGORITHM_EC && !pubkey->u.ec.ecpointQ.value)
goto done;
/* In Mozilla 'GOST R 34.10' is not yet supported.
* So, switch to the ID recommended by RFC2459 */
@ -2208,8 +2217,11 @@ select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
SHA1(pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len, id->value);
else if (pubkey->algorithm == SC_ALGORITHM_DSA)
SHA1(pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len, id->value);
else if (pubkey->algorithm == SC_ALGORITHM_EC)
SHA1(pubkey->u.ec.ecpointQ.value, pubkey->u.ec.ecpointQ.len, id->value);
else if (pubkey->algorithm == SC_ALGORITHM_EC) {
/* ID should be SHA1 of the X coordinate according to PKCS#15 v1.1 */
/* skip the 04 tag and get the X component */
SHA1(pubkey->u.ec.ecpointQ.value+1, (pubkey->u.ec.ecpointQ.len - 1) / 2, id->value);
}
else
goto done;

View File

@ -41,21 +41,18 @@ unsigned char MYEID_DEFAULT_PUBKEY[] = {0x01, 0x00, 0x01};
/* For Myeid, all objects are files that can be deleted in any order */
static int
myeid_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object, const struct sc_path *path)
{
struct sc_pkcs15_object *object, const struct sc_path *path) {
LOG_FUNC_CALLED(p15card->card->ctx);
return sc_pkcs15init_delete_by_path(profile, p15card, path);
}
/*
* Get 'Initialize Applet' data
* using the ACLs defined in card profile.
*/
static int
myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
unsigned char *data, size_t data_len)
{
unsigned char *data, size_t data_len) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *tmp_file = NULL;
const struct sc_acl_entry *entry = NULL;
@ -77,17 +74,17 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1
LOG_TEST_RET(ctx, r, "MF fixup failed");
/* AC 'Create DF' and 'Create EF' */
*(data + 2) = 0x00; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
*(data + 2) = 0x00; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
if (entry->method == SC_AC_CHV)
*(data + 2) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx'. */
*(data + 2) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx'. */
else if (entry->method == SC_AC_NEVER)
*(data + 2) = 0xFF; /* 'NEVER'. */
*(data + 2) = 0xFF; /* 'NEVER'. */
/* AC 'INITIALISE APPLET'. */
*(data + 3) = 0x0F; /* 'NONE' */
*(data + 3) = 0x0F; /* 'NONE' */
#ifndef KEEP_AC_NONE_FOR_INIT_APPLET
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
if (entry->method == SC_AC_CHV)
*(data + 3) = (entry->key_ref << 4) | 0xF;
else if (entry->method == SC_AC_NEVER)
@ -106,33 +103,31 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1
LOG_TEST_RET(ctx, r, "Application DF fixup failed");
/* AC 'Create DF' and 'Create EF' */
*(data + 5) = 0x00; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
*(data + 5) = 0x00; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
if (entry->method == SC_AC_CHV)
*(data + 5) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx' */
*(data + 5) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx' */
else if (entry->method == SC_AC_NEVER)
*(data + 5) = 0xFF; /* 'NEVER'. */
*(data + 5) = 0xFF; /* 'NEVER'. */
/* AC 'Self delete' */
*(data + 6) = 0x0F; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
*(data + 6) = 0x0F; /* 'NONE' */
entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
if (entry->method == SC_AC_CHV)
*(data + 6) = (entry->key_ref << 4) | 0xF; /* 'CHVx' */
*(data + 6) = (entry->key_ref << 4) | 0xF; /* 'CHVx' */
else if (entry->method == SC_AC_NEVER)
*(data + 6) = 0xFF; /* 'NEVER'. */
*(data + 7)= 0xFF;
*(data + 6) = 0xFF; /* 'NEVER'. */
*(data + 7) = 0xFF;
sc_file_free(tmp_file);
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
/*
* Erase the card.
*/
static int
myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
{
myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_cardctl_myeid_data_obj data_obj;
struct sc_file *mf = NULL;
@ -141,7 +136,7 @@ myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
LOG_FUNC_CALLED(ctx);
r = myeid_get_init_applet_data(profile, p15card, data, sizeof(data));
r = myeid_get_init_applet_data(profile, p15card, data, sizeof (data));
LOG_TEST_RET(ctx, r, "Get init applet date error");
/* Select parent DF and verify PINs/key as necessary */
@ -153,48 +148,51 @@ myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
r = sc_pkcs15init_authenticate(profile, p15card, mf, SC_AC_OP_DELETE);
LOG_TEST_RET(ctx, r, "'DELETE' authentication failed on MF");
data_obj.P1 = 0x01;
data_obj.P2 = 0xE0;
data_obj.Data = data;
data_obj.DataLen = sizeof(data);
data_obj.P1 = 0x01;
data_obj.P2 = 0xE0;
data_obj.Data = data;
data_obj.DataLen = sizeof (data);
r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj);
LOG_FUNC_RETURN(p15card->card->ctx, r);
}
static int
myeid_init_card(sc_profile_t *profile,
sc_pkcs15_card_t *p15card)
{
sc_pkcs15_card_t *p15card) {
struct sc_path path;
struct sc_file *file = NULL;
u8 rbuf[256];
int r;
LOG_FUNC_CALLED(p15card->card->ctx);
sc_format_path("3F00", &path);
r = sc_select_file(p15card->card, &path, &file);
p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT;
r = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &rbuf);
LOG_TEST_RET(p15card->card->ctx, r, "Get applet info failed");
sc_format_path("3F00", &path);
r = sc_select_file(p15card->card, &path, &file);
if (file)
sc_file_free(file);
LOG_FUNC_RETURN(p15card->card->ctx, r);
}
/*
* Create a DF
*/
static int
myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df)
{
myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *file = NULL;
int r=0, ii;
static const char *create_dfs[] = {
int r = 0, ii;
static const char *create_dfs[] = {
"PKCS15-PrKDF",
"PKCS15-PuKDF",
"PKCS15-CDF",
@ -204,28 +202,27 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df
};
static const int create_dfs_val[] = {
SC_PKCS15_PRKDF,
SC_PKCS15_PUKDF,
SC_PKCS15_CDF,
SC_PKCS15_CDF_TRUSTED,
SC_PKCS15_DODF
SC_PKCS15_PRKDF,
SC_PKCS15_PUKDF,
SC_PKCS15_CDF,
SC_PKCS15_CDF_TRUSTED,
SC_PKCS15_DODF
};
if (!profile || !p15card || !df)
return SC_ERROR_INVALID_ARGUMENTS;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "id (%x)",df->id);
sc_log(ctx, "id (%x)", df->id);
if(df->id == 0x5015)
{
sc_log(ctx, "Select (%x)",df->id);
if (df->id == 0x5015) {
sc_log(ctx, "Select (%x)", df->id);
r = sc_select_file(p15card->card, &df->path, NULL);
for (ii = 0; create_dfs[ii]; ii++) {
for (ii = 0; create_dfs[ii]; ii++) {
sc_log(ctx, "Create '%s'", create_dfs[ii]);
if (sc_profile_get_file(profile, create_dfs[ii], &file)) {
if (sc_profile_get_file(profile, create_dfs[ii], &file)) {
sc_log(ctx, "Inconsistent profile: cannot find %s", create_dfs[ii]);
LOG_FUNC_RETURN(ctx, SC_ERROR_INCONSISTENT_PROFILE);
}
@ -240,30 +237,25 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df
LOG_FUNC_RETURN(p15card->card->ctx, r);
}
/*
* Select the PIN reference
*/
static int
myeid_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_auth_info_t *auth_info)
{
sc_pkcs15_auth_info_t *auth_info) {
SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE);
if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
return SC_ERROR_OBJECT_NOT_VALID;
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
{
sc_log(p15card->card->ctx,
"PIN_FLAG_SO_PIN, ref (%d), tries_left (%d)",
auth_info->attrs.pin.reference, auth_info->tries_left);
}
else
{
sc_log(p15card->card->ctx,
"PIN_FLAG_PIN, ref (%d), tries_left (%d)",
auth_info->attrs.pin.reference, auth_info->tries_left);
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
sc_log(p15card->card->ctx,
"PIN_FLAG_SO_PIN, ref (%d), tries_left (%d)",
auth_info->attrs.pin.reference, auth_info->tries_left);
} else {
sc_log(p15card->card->ctx,
"PIN_FLAG_PIN, ref (%d), tries_left (%d)",
auth_info->attrs.pin.reference, auth_info->tries_left);
}
@ -280,18 +272,17 @@ static int
myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_file *df, struct sc_pkcs15_object *pin_obj,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
{
const unsigned char *puk, size_t puk_len) {
struct sc_context *ctx = p15card->card->ctx;
unsigned char data[20];
unsigned char data[20];
struct sc_cardctl_myeid_data_obj data_obj;
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
struct sc_pkcs15_auth_info puk_ainfo;
int r;
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data;
struct sc_pkcs15_auth_info puk_ainfo;
int r;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "PIN('%s',ref:%i,flags:0x%X,pin_len:%d,puk_len:%d)\n",
pin_obj->label, auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, pin_len, puk_len);
pin_obj->label, auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, pin_len, puk_len);
if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
return SC_ERROR_OBJECT_NOT_VALID;
@ -304,30 +295,30 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
? SC_PKCS15INIT_SO_PUK : SC_PKCS15INIT_USER_PUK,
&puk_ainfo);
memset(data, 0, sizeof(data));
memset(data, 0, sizeof (data));
/* Make command to add a pin-record */
data_obj.P1 = 0x01;
data_obj.P2 = auth_info->attrs.pin.reference; /* myeid pin number */
data_obj.P2 = auth_info->attrs.pin.reference; /* myeid pin number */
memset(data, auth_info->attrs.pin.pad_char, 8);
memcpy(&data[0], (u8 *)pin, pin_len); /* copy pin */
memcpy(&data[0], (u8 *) pin, pin_len); /* copy pin */
memset(&data[8], puk_ainfo.attrs.pin.pad_char, 8);
memcpy(&data[8], (u8 *)puk, puk_len); /* copy puk */
memcpy(&data[8], (u8 *) puk, puk_len); /* copy puk */
if(auth_info->tries_left > 0 && auth_info->tries_left < 15)
if (auth_info->tries_left > 0 && auth_info->tries_left < 15)
data[16] = auth_info->tries_left;
else
data[16] = 5; /* default value */
data[16] = 5; /* default value */
if(puk_ainfo.tries_left > 0 && puk_ainfo.tries_left < 15)
if (puk_ainfo.tries_left > 0 && puk_ainfo.tries_left < 15)
data[17] = puk_ainfo.tries_left;
else
data[17] = 5; /* default value */
data[17] = 5; /* default value */
data[18] = 0x00;
data_obj.Data = data;
data_obj.Data = data;
data_obj.DataLen = 19;
r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj);
@ -336,7 +327,6 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
LOG_FUNC_RETURN(ctx, r);
}
/*
* Setup file struct & path: get correct template from the profile, construct full path
* num = number of objects of this type already on the card
@ -344,8 +334,7 @@ myeid_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
static int
myeid_new_file(sc_profile_t *profile, sc_card_t *card,
unsigned int type, unsigned int num,
sc_file_t **out)
{
sc_file_t **out) {
sc_file_t *file;
sc_path_t *p;
char name[64];
@ -353,24 +342,22 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card,
int r;
LOG_FUNC_CALLED(card->ctx);
if (type == SC_PKCS15_TYPE_PRKEY_RSA)
if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC)
tag = "private-key";
else if (type == SC_PKCS15_TYPE_PUBKEY_RSA)
else if (type == SC_PKCS15_TYPE_PUBKEY_RSA || type == SC_PKCS15_TYPE_PUBKEY_EC)
tag = "public-key";
else if ((type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_CERT)
tag = "certificate";
else if ((type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_DATA_OBJECT)
tag = "data";
else
{
else {
sc_log(card->ctx, "Unsupported file type");
return SC_ERROR_INVALID_ARGUMENTS;
}
/* Get template from profile */
snprintf(name, sizeof(name), "template-%s", tag);
if (sc_profile_get_file(profile, name, &file) < 0)
{
snprintf(name, sizeof (name), "template-%s", tag);
if (sc_profile_get_file(profile, name, &file) < 0) {
sc_log(card->ctx, "Profile doesn't define %s", name);
return SC_ERROR_NOT_SUPPORTED;
}
@ -384,8 +371,7 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card,
/* Increment FID until there's no file with such path */
r = sc_select_file(card, p, NULL);
while(r == 0)
{
while (r == 0) {
file->id++;
p->value[p->len - 2] = (u8) (file->id / 256);
p->value[p->len - 1] = (u8) (file->id % 256);
@ -396,12 +382,10 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card,
LOG_FUNC_RETURN(card->ctx, 0);
}
static int
myeid_encode_private_key(sc_profile_t *profile, sc_card_t *card,
struct sc_pkcs15_prkey_rsa *rsa, u8 *key,
size_t *keysize, int key_ref)
{
size_t *keysize, int key_ref) {
LOG_FUNC_CALLED(card->ctx);
LOG_FUNC_RETURN(card->ctx, 0);
}
@ -409,159 +393,62 @@ myeid_encode_private_key(sc_profile_t *profile, sc_card_t *card,
static int
myeid_encode_public_key(sc_profile_t *profile, sc_card_t *card,
struct sc_pkcs15_prkey_rsa *rsa, u8 *key,
size_t *keysize, int key_ref)
{
size_t *keysize, int key_ref) {
LOG_FUNC_CALLED(card->ctx);
LOG_FUNC_RETURN(card->ctx, 0);
}
#if 0
/*
* Generate RSA key
*/
static int myeid_generate_key(sc_profile_t *profile, sc_card_t *card,
unsigned int index, /* keyref: 0 for 1st key, ... */
unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey,
struct sc_pkcs15_prkey_info *info)
{
return myeid_generate_store_key(profile, card, index, keybits,
pubkey, NULL, info);
}
/*
* Store RSA key
*/
static int myeid_new_key(sc_profile_t *profile, sc_card_t *card,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
{
return myeid_generate_store_key(profile, card, index,
key->u.rsa.modulus.len * 8, NULL, key, info);
}
/*
* Common code for generating or storing a private key.
* If pubkey == NULL and prkey != NULL, we have to store a private key
* In the oposite case, we have to generate a private key
*/
static int myeid_generate_store_key(sc_profile_t *profile, sc_card_t *card,
unsigned int index, /* keynumber: 0 for 1st priv key, ... */
unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey,
sc_pkcs15_prkey_t *prkey,
sc_pkcs15_prkey_info_t *info)
{
struct sc_cardctl_myeid_gen_store_key_info args;
int r;
sc_file_t *prkf = NULL;
LOG_FUNC_CALLED(card->ctx);
/* Parameter check */
if ( (keybits < 1024) || (keybits > 2048) || (keybits & 0X7)) {
sc_log(card->ctx,
"Unsupported key size [%u]: 1024-2048 bit + 8-multiple\n", keybits);
return SC_ERROR_INVALID_ARGUMENTS;
}
/* Get the private key file */
r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &prkf);
if (r < 0)
goto done;
/* Take enough room for a 1024 bit key */
if (prkf->size < 1024)
prkf->size = 1024;
/* Now create the key file */
r = sc_pkcs15init_create_file(profile, card, prkf);
if (r < 0)
goto done;
/* Fill in data structure */
memset(&args, 0, sizeof(args));
args.mod_len = keybits;
if (prkey == NULL)
{
args.op_type = OP_TYPE_GENERATE;
args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN;
args.pubexp = MYEID_DEFAULT_PUBKEY;
}
else
{
args.op_type = OP_TYPE_STORE;
args.pubexp_len = prkey->u.rsa.exponent.len;
args.pubexp = prkey->u.rsa.exponent.data;
args.primep_len = prkey->u.rsa.p.len;
args.primep = prkey->u.rsa.p.data;
args.primeq_len = prkey->u.rsa.q.len;
args.primeq = prkey->u.rsa.q.data;
args.dp1_len = prkey->u.rsa.dmp1.len;
args.dp1 = prkey->u.rsa.dmp1.data;
args.dq1_len = prkey->u.rsa.dmq1.len;
args.dq1 = prkey->u.rsa.dmq1.data;
args.invq_len = prkey->u.rsa.iqmp.len;
args.invq = prkey->u.rsa.iqmp.data;
args.mod_len = prkey->u.rsa.modulus.len;
args.mod = prkey->u.rsa.modulus.data;
}
/* Authenticate */
r = sc_pkcs15init_authenticate(profile, card, prkf, SC_AC_OP_UPDATE);
if (r < 0)
goto done;
/* Generate/store rsa key */
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_KEY, &args);
if (r < 0)
goto done;
info->key_reference = 0;
info->path = prkf->path;
done:
if (prkf)
sc_file_free(prkf);
LOG_FUNC_RETURN(card->ctx, r);
}
#endif
/*
* Store a private key
*/
static int
myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object)
{
struct sc_pkcs15_object *object) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_card *card = p15card->card;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
struct sc_file *file = NULL;
int keybits = key_info->modulus_length, r;
LOG_FUNC_CALLED(card->ctx);
/* Check that the card supports the requested modulus length */
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size");
sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id));
/* Check that the card supports the requested modulus length */
switch (object->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
"Unsupported RSA key size");
break;
case SC_PKCS15_TYPE_PRKEY_EC:
if (sc_card_find_ec_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
"Unsupported EC key size");
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
"Unsupported key type");
break;
}
sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id));
/* Get the private key file */
r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file);
LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file");
sc_log(ctx, "Key file size %d", keybits);
file->size = keybits;
if (object->type == SC_PKCS15_TYPE_PRKEY_RSA)
file->ef_structure = SC_CARDCTL_MYEID_KEY_RSA;
else if (object->type == SC_PKCS15_TYPE_PRKEY_EC)
file->ef_structure = SC_CARDCTL_MYEID_KEY_EC;
memcpy(&key_info->path.value, &file->path.value, file->path.len);
key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF;
sc_log(ctx, "Path of MyEID private key file to create %s",
sc_log(ctx, "Path of MyEID private key file to create %s",
sc_print_path(&file->path));
/* Now create the key file */
@ -572,30 +459,41 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
LOG_FUNC_RETURN(ctx, r);
}
/*
* Store a private key
*/
static int
myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object,
struct sc_pkcs15_prkey *prkey)
{
struct sc_pkcs15_prkey *prkey) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_card *card = p15card->card;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
struct sc_cardctl_myeid_gen_store_key_info args;
struct sc_file *file = NULL;
int r, keybits = key_info->modulus_length;
LOG_FUNC_CALLED(ctx);
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported");
/* Check that the card supports the requested modulus length */
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size");
switch (object->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size");
break;
case SC_PKCS15_TYPE_PRKEY_EC:
if (sc_card_find_ec_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size");
if(key_info->field_length != 0)
keybits = key_info->field_length;
else
key_info->field_length = keybits;
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type");
break;
}
sc_log(ctx, "store MyEID key with ID:%s and path:%s",
sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path));
@ -609,26 +507,37 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
sc_file_free(file);
/* Fill in data structure */
memset(&args, 0, sizeof(args));
args.mod_len = keybits;
args.op_type = OP_TYPE_STORE;
args.pubexp_len = prkey->u.rsa.exponent.len;
args.pubexp = prkey->u.rsa.exponent.data;
args.primep_len = prkey->u.rsa.p.len;
args.primep = prkey->u.rsa.p.data;
args.primeq_len = prkey->u.rsa.q.len;
args.primeq = prkey->u.rsa.q.data;
memset(&args, 0, sizeof (args));
args.dp1_len = prkey->u.rsa.dmp1.len;
args.dp1 = prkey->u.rsa.dmp1.data;
args.dq1_len = prkey->u.rsa.dmq1.len;
args.dq1 = prkey->u.rsa.dmq1.data;
args.invq_len = prkey->u.rsa.iqmp.len;
args.invq = prkey->u.rsa.iqmp.data;
args.op_type = OP_TYPE_STORE;
if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
//args.key_len_bits = keybits;
args.key_type = SC_CARDCTL_MYEID_KEY_RSA;
args.pubexp_len = prkey->u.rsa.exponent.len;
args.pubexp = prkey->u.rsa.exponent.data;
args.primep_len = prkey->u.rsa.p.len;
args.primep = prkey->u.rsa.p.data;
args.primeq_len = prkey->u.rsa.q.len;
args.primeq = prkey->u.rsa.q.data;
args.mod_len = prkey->u.rsa.modulus.len;
args.mod = prkey->u.rsa.modulus.data;
args.dp1_len = prkey->u.rsa.dmp1.len;
args.dp1 = prkey->u.rsa.dmp1.data;
args.dq1_len = prkey->u.rsa.dmq1.len;
args.dq1 = prkey->u.rsa.dmq1.data;
args.invq_len = prkey->u.rsa.iqmp.len;
args.invq = prkey->u.rsa.iqmp.data;
args.key_len_bits = prkey->u.rsa.modulus.len;
args.mod = prkey->u.rsa.modulus.data;
}
else {
args.key_type = SC_CARDCTL_MYEID_KEY_EC;
args.d = prkey->u.ec.privateD.data;
args.d_len = prkey->u.ec.privateD.len;
args.ecpublic_point = prkey->u.ec.ecpointQ.value;
args.ecpublic_point_len = prkey->u.ec.ecpointQ.len;
args.key_len_bits = prkey->u.ec.params.field_length;
}
/* Store RSA key */
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args);
LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed");
@ -636,15 +545,13 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
LOG_FUNC_RETURN(ctx, r);
}
static int
myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object,
struct sc_pkcs15_pubkey *pubkey)
{
struct sc_pkcs15_pubkey *pubkey) {
struct sc_context *ctx = p15card->card->ctx;
struct sc_card *card = p15card->card;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
struct sc_cardctl_myeid_gen_store_key_info args;
struct sc_file *file = NULL;
int r;
@ -652,61 +559,107 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
unsigned char raw_pubkey[256];
LOG_FUNC_CALLED(ctx);
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported");
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA && object->type != SC_PKCS15_TYPE_PRKEY_EC)
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: only RSA and EC supported");
/* Check that the card supports the requested modulus length */
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size");
switch (object->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size");
break;
case SC_PKCS15_TYPE_PRKEY_EC:
if (sc_card_find_ec_alg(p15card->card, keybits) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size");
if(key_info->field_length != 0)
keybits = key_info->field_length;
else
key_info->field_length = keybits;
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type");
break;
}
sc_log(ctx, "store MyEID key with ID:%s and path:%s",
sc_log(ctx, "Generate key with ID:%s and path:%s",
sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path));
r = sc_select_file(card, &key_info->path, &file);
LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed");
LOG_TEST_RET(ctx, r, "Cannot generate key: failed to select key file");
r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE);
LOG_TEST_RET(ctx, r, "No authorisation to generate MyEID private key");
LOG_TEST_RET(ctx, r, "No authorisation to generate private key");
/* Fill in data structure */
memset(&args, 0, sizeof(args));
args.mod_len = keybits;
args.op_type = OP_TYPE_GENERATE;
args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN;
args.pubexp = MYEID_DEFAULT_PUBKEY;
memset(&args, 0, sizeof (args));
args.key_len_bits = keybits;
args.op_type = OP_TYPE_GENERATE;
if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
args.key_type = SC_CARDCTL_MYEID_KEY_RSA;
args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN;
args.pubexp = MYEID_DEFAULT_PUBKEY;
} else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) {
args.key_type = SC_CARDCTL_MYEID_KEY_EC;
}
/* Generate RSA key */
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args);
LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed");
/* Keypair generation -> collect public key info */
/* FIXME: was not preset in original Aventra version. Need to be tested. (VT) */
if (pubkey != NULL) {
if (pubkey != NULL) {
struct sc_cardctl_myeid_data_obj data_obj;
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = (keybits + 7) / 8;
pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN;
pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN);
memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN);
if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = (keybits + 7) / 8;
pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN;
pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN);
memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN);
/* Get public key modulus */
r = sc_select_file(card, &file->path, NULL);
LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed");
/* Get public key modulus */
r = sc_select_file(card, &file->path, NULL);
LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed");
data_obj.P1 = 0x01;
data_obj.P2 = 0x01;
data_obj.Data = raw_pubkey;
data_obj.DataLen = sizeof(raw_pubkey);
data_obj.P1 = 0x01;
data_obj.P2 = 0x01;
data_obj.Data = raw_pubkey;
data_obj.DataLen = sizeof (raw_pubkey);
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
LOG_TEST_RET(ctx, r, "Cannot get key modulus: 'MYEID_GETDATA' failed");
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
LOG_TEST_RET(ctx, r, "Cannot get RSA key modulus: 'MYEID_GETDATA' failed");
if ((data_obj.DataLen * 8) != key_info->modulus_length)
LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get key modulus: invalid key-size");
if ((data_obj.DataLen * 8) != key_info->modulus_length)
LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get RSA key modulus: invalid key-size");
memcpy (pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len);
memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len);
}
else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) {
pubkey->algorithm = SC_ALGORITHM_EC;
r = sc_select_file(card, &file->path, NULL);
LOG_TEST_RET(ctx, r, "Cannot get public key: select key file failed");
data_obj.P1 = 0x01;
data_obj.P2 = 0x86; /* Get public EC key (Q) */
data_obj.Data = raw_pubkey;
data_obj.DataLen = sizeof (raw_pubkey);
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed");
pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2);
pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2;
pubkey->data.value = malloc(data_obj.DataLen);
pubkey->data.len = data_obj.DataLen;
pubkey->u.ec.params.field_length = keybits;
/* Omit the first 2 bytes (0x86??) */
memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2);
memcpy(pubkey->data.value, data_obj.Data, data_obj.DataLen);
}
}
if (file)
@ -716,8 +669,7 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
}
/* Finish initialization. After this ACL is in affect */
static int myeid_finalize_card(sc_card_t *card)
{
static int myeid_finalize_card(sc_card_t *card) {
LOG_FUNC_CALLED(card->ctx);
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_MYEID_ACTIVATE_CARD, NULL));
}
@ -728,24 +680,23 @@ static int myeid_finalize_card(sc_card_t *card)
*/
static struct sc_pkcs15init_operations sc_pkcs15init_myeid_operations = {
myeid_erase_card,
myeid_init_card, /* init_card */
myeid_create_dir, /* create_dir */
NULL, /* create_domain */
myeid_init_card, /* init_card */
myeid_create_dir, /* create_dir */
NULL, /* create_domain */
myeid_select_pin_reference,
myeid_create_pin,
NULL, /* select_key_reference */
NULL, /* select_key_reference */
myeid_create_key,
myeid_store_key,
myeid_generate_key,
myeid_encode_private_key,
myeid_encode_public_key,
myeid_finalize_card,
myeid_delete_object, /* delete_object */
NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */
NULL /* sanity_check */
myeid_delete_object, /* delete_object */
NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */
NULL /* sanity_check */
};
struct sc_pkcs15init_operations *sc_pkcs15init_get_myeid_ops(void)
{
struct sc_pkcs15init_operations *sc_pkcs15init_get_myeid_ops(void) {
return &sc_pkcs15init_myeid_operations;
}

View File

@ -61,9 +61,15 @@ static struct ec_curve_info {
const char *oid_encoded;
size_t size;
} ec_curve_infos[] = {
{"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192},
{"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
{"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
{"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192},
{"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192},
{"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192},
{"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
{"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
{"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
{"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
{"prime384v1", "1.3.132.0.34", "06052B81040022", 384},
{"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384},
{"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192},
{"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224},
{"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256},
@ -4231,9 +4237,9 @@ static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
data = md5_and_digestinfo;
data_len = 20;
rv = p11->C_SignInit(session, &mech, priv_key);
rv = p11->C_Sign(session, data, data_len, sig, &sig_len);
if (rv != CKR_OK)
p11_fatal("C_SignInit", rv);
rv = p11->C_Sign(session, data, data_len, sig, &sig_len);
if (rv != CKR_OK)
p11_fatal("C_Sign", rv);