Support SKDF and secret key upload for MyEID cards

This commit is contained in:
Timo Teräs 2017-04-14 10:42:30 +03:00 committed by Frank Morgner
parent 3d8cf274ff
commit 94973809c2
4 changed files with 160 additions and 88 deletions

View File

@ -43,6 +43,8 @@
#define LOAD_KEY_EC_PRIVATE 0x97
#define LOAD_KEY_EC_PUBLIC 0x96
#define LOAD_KEY_SYMMETRIC 0xa0
#define MYEID_STATE_CREATION 0x01
#define MYEID_STATE_ACTIVATED 0x07
@ -148,7 +150,6 @@ static int myeid_init(struct sc_card *card)
u8 appletInfo[20];
size_t appletInfoLen;
int r;
unsigned short max_ecc_key_length = 256;
myeid_card_caps_t card_caps;
LOG_FUNC_CALLED(card->ctx);
@ -183,16 +184,15 @@ static int myeid_init(struct sc_card *card)
_sc_card_add_rsa_alg(card, 2048, flags, 0);
memset(&card_caps, 0, sizeof(myeid_card_caps_t));
card_caps.max_ecc_key_length = 256;
card_caps.max_rsa_key_length = 2048;
if (card->version.fw_major >= 40) {
/* Since 4.0, we can query available algorithms and key sizes.
* Since 3.5.0 RSA up to 2048 and ECC up to 256 are always supported, so we check only max ECC key length. */
r = myeid_get_card_caps(card, &card_caps);
if (r == SC_SUCCESS) {
max_ecc_key_length = card_caps.max_ecc_key_length;
}
else {
if (r != SC_SUCCESS) {
sc_log(card->ctx, "Failed to get card capabilities. Using default max ECC key length 256.");
}
}
@ -206,15 +206,28 @@ static int myeid_init(struct sc_card *card)
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
for (i=0; ec_curves[i].curve_name != NULL; i++) {
if (i == 2 && max_ecc_key_length < 384)
continue;
else if (i == 3 && max_ecc_key_length < 521)
continue;
else
_sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].curve_oid);
if (card_caps.max_ecc_key_length >= ec_curves[i].size)
_sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].curve_oid);
}
}
/* show supported symmetric algorithms */
flags = 0;
if (card_caps.card_supported_features & MYEID_CARD_CAP_3DES) {
if (card_caps.max_des_key_length >= 56)
_sc_card_add_symmetric_alg(card, SC_ALGORITHM_DES, 56, flags);
if (card_caps.max_des_key_length >= 128)
_sc_card_add_symmetric_alg(card, SC_ALGORITHM_3DES, 128, flags);
if (card_caps.max_des_key_length >= 192)
_sc_card_add_symmetric_alg(card, SC_ALGORITHM_3DES, 192, flags);
}
if (card_caps.card_supported_features & MYEID_CARD_CAP_AES) {
if (card_caps.max_aes_key_length >= 128)
_sc_card_add_symmetric_alg(card, SC_ALGORITHM_AES, 128, flags);
if (card_caps.max_aes_key_length >= 256)
_sc_card_add_symmetric_alg(card, SC_ALGORITHM_AES, 256, flags);
}
/* State that we have an RNG */
card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;
@ -439,6 +452,8 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
else {
delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE);
sc_log(card->ctx, "id (%X), type (%X)", file->id, file->type);
switch (file->type) {
case SC_FILE_TYPE_WORKING_EF:
@ -1188,7 +1203,8 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
if(value != NULL &&
value[0] != 0x0 &&
mode != LOAD_KEY_PUBLIC_EXPONENT)
mode != LOAD_KEY_PUBLIC_EXPONENT &&
mode != LOAD_KEY_SYMMETRIC)
sbuf[len++] = 0x0;
if(mode == LOAD_KEY_MODULUS && value_len >= 256)
@ -1328,6 +1344,12 @@ static int myeid_generate_store_key(struct sc_card *card,
data->ecpublic_point_len)) >= 0)
LOG_FUNC_RETURN(card->ctx, r);
}
else if(data->key_type == SC_CARDCTL_MYEID_KEY_AES ||
data->key_type == SC_CARDCTL_MYEID_KEY_DES) {
if((r = myeid_loadkey(card, LOAD_KEY_SYMMETRIC, data->d,
data->d_len)) >= 0)
LOG_FUNC_RETURN(card->ctx, r);
}
}
LOG_FUNC_RETURN(card->ctx, r);

View File

@ -878,7 +878,9 @@ typedef struct sc_rtecp_genkey_data {
*/
enum SC_CARDCTL_MYEID_KEY_TYPE {
SC_CARDCTL_MYEID_KEY_RSA = 0x11,
SC_CARDCTL_MYEID_KEY_EC = 0x22
SC_CARDCTL_MYEID_KEY_DES = 0x19,
SC_CARDCTL_MYEID_KEY_EC = 0x22,
SC_CARDCTL_MYEID_KEY_AES = 0x29
};
struct sc_cardctl_myeid_data_obj {
@ -907,8 +909,8 @@ typedef struct sc_rtecp_genkey_data {
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 *d; /* EC private key / Symmetric key */
unsigned int d_len; /* EC / Symmetric */
unsigned char *ecpublic_point; /* EC public key */
unsigned int ecpublic_point_len; /* EC */
};

View File

@ -36,6 +36,7 @@ option default {
cdf-trusted-size = 510;
prkdf-size = 1530;
pukdf-size = 1530;
skdf-size = 1530;
dodf-size = 1530;
}
}
@ -136,6 +137,13 @@ filesystem {
acl = *=NEVER, READ=NONE, UPDATE=$PIN, DELETE=$SOPIN;
}
EF PKCS15-SKDF {
file-id = 4407;
structure = transparent;
size = $skdf-size;
acl = *=NEVER, READ=NONE, UPDATE=$PIN, DELETE=$SOPIN;
}
EF PKCS15-CDF {
file-id = 4403;
structure = transparent;
@ -159,8 +167,14 @@ filesystem {
EF template-private-key {
type = internal-ef;
file-id = 4B01;
acl = CRYPTO=$PIN, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
file-id = 4B01;
acl = CRYPTO=$PIN, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
}
EF template-secret-key {
type = internal-ef;
file-id = 4D01;
acl = CRYPTO=$PIN, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
}
EF template-public-key {
@ -181,13 +195,18 @@ filesystem {
EF private-key {
file-id = 4B01;
type = internal-ef;
acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
acl = CRYPTO=$PIN, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
}
EF public-key {
file-id = 5501;
file-id = 5501;
structure = transparent;
acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
}
EF secret-key {
file-id = 4D01;
type = internal-ef;
acl = CRYPTO=$PIN, UPDATE=$PIN, DELETE=$PIN, GENERATE=$PIN;
}
# Certificate template
EF certificate {

View File

@ -201,6 +201,7 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df
static const char *create_dfs[] = {
"PKCS15-PrKDF",
"PKCS15-PuKDF",
"PKCS15-SKDF",
"PKCS15-CDF",
"PKCS15-CDF-TRUSTED",
"PKCS15-DODF",
@ -210,6 +211,7 @@ 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_SKDF,
SC_PKCS15_CDF,
SC_PKCS15_CDF_TRUSTED,
SC_PKCS15_DODF
@ -349,19 +351,33 @@ myeid_new_file(sc_profile_t *profile, sc_card_t *card,
sc_file_t *file;
sc_path_t *p;
char name[64];
const char *tag;
const char *tag = NULL;
int r;
LOG_FUNC_CALLED(card->ctx);
if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC)
switch (type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
case SC_PKCS15_TYPE_PRKEY_EC:
tag = "private-key";
else if (type == SC_PKCS15_TYPE_PUBKEY_RSA || type == SC_PKCS15_TYPE_PUBKEY_EC)
break;
case SC_PKCS15_TYPE_PUBKEY_RSA:
case 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 {
break;
case SC_PKCS15_TYPE_SKEY_GENERIC:
case SC_PKCS15_TYPE_SKEY_DES:
case SC_PKCS15_TYPE_SKEY_3DES:
tag = "secret-key";
break;
default:
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";
break;
}
if (!tag) {
sc_log(card->ctx, "Unsupported file type");
return SC_ERROR_INVALID_ARGUMENTS;
}
@ -418,36 +434,37 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
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 *prkey_info = (struct sc_pkcs15_prkey_info *) object->data;
struct sc_pkcs15_skey_info *skey_info = (struct sc_pkcs15_skey_info *) object->data;
struct sc_pkcs15_id *id;
struct sc_path *path;
int *key_reference;
struct sc_file *file = NULL;
struct sc_pkcs15_object *pin_object = NULL;
struct sc_pkcs15_auth_info *pkcs15_auth_info = NULL;
int keybits = key_info->modulus_length, r;
int pin_reference = -1;
unsigned char sec_attrs[] = {0xFF, 0xFF, 0xFF};
int r, ef_structure, keybits = 0, pin_reference = -1;
LOG_FUNC_CALLED(card->ctx);
/* 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");
ef_structure = SC_CARDCTL_MYEID_KEY_RSA;
keybits = prkey_info->modulus_length;
break;
case SC_PKCS15_TYPE_PRKEY_EC:
/*
Here the information about curve is not available, that's why algorithm is checked
without curve OID.
*/
if (key_info->field_length != 0)
keybits = key_info->field_length;
else
key_info->field_length = keybits;
if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size");
ef_structure = SC_CARDCTL_MYEID_KEY_EC;
keybits = prkey_info->field_length;
break;
case SC_PKCS15_TYPE_SKEY_DES:
case SC_PKCS15_TYPE_SKEY_3DES:
ef_structure = SC_CARDCTL_MYEID_KEY_DES;
keybits = skey_info->value_len;
break;
case SC_PKCS15_TYPE_SKEY_GENERIC:
keybits = skey_info->value_len;
/* FIXME */
ef_structure = SC_CARDCTL_MYEID_KEY_AES;
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
@ -455,27 +472,33 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
break;
}
sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id));
if ((object->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) {
id = &prkey_info->id;
path = &prkey_info->path;
key_reference = &prkey_info->key_reference;
} else {
id = &skey_info->id;
path = &skey_info->path;
key_reference = &skey_info->key_reference;
}
sc_log(ctx, "create MyEID key ID:%s", sc_pkcs15_print_id(id));
/* Get the private key 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");
r = myeid_new_file(profile, card, object->type, *key_reference, &file);
LOG_TEST_RET(ctx, r, "Cannot get new MyEID key file");
if (!file || !file->path.len)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine private key file");
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine key file");
sc_log(ctx, "Key file size %d", keybits);
file->size = keybits;
file->ef_structure = ef_structure;
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(path->value, &file->path.value, file->path.len);
*key_reference = file->path.value[file->path.len - 1] & 0xFF;
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 key file to create %s",
sc_print_path(&file->path));
if (object->auth_id.len >= 1) {
@ -513,7 +536,7 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
/* Now create the key file */
r = sc_pkcs15init_create_file(profile, p15card, file);
sc_file_free(file);
LOG_TEST_RET(ctx, r, "Cannot create MyEID private key file");
LOG_TEST_RET(ctx, r, "Cannot create MyEID key file");
LOG_FUNC_RETURN(ctx, r);
}
@ -527,40 +550,28 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
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_cardctl_myeid_gen_store_key_info args;
struct sc_file *file = NULL;
int r, keybits = key_info->modulus_length;
struct sc_pkcs15_id *id;
struct sc_path *path;
int r;
LOG_FUNC_CALLED(ctx);
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_valid_oid(&prkey->u.ec.params.id))
if (sc_pkcs15_fix_ec_parameters(ctx, &prkey->u.ec.params))
LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID);
if(key_info->field_length != 0)
keybits = key_info->field_length;
else
key_info->field_length = keybits;
if (sc_card_find_ec_alg(p15card->card, keybits, &prkey->u.ec.params.id) == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported algorithm or key size");
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type");
break;
if ((object->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) {
struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *) object->data;
id = &prkey_info->id;
path = &prkey_info->path;
} else {
struct sc_pkcs15_skey_info *skey_info = (struct sc_pkcs15_skey_info *) object->data;
id = &skey_info->id;
path = &skey_info->path;
}
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));
sc_pkcs15_print_id(id), sc_print_path(path));
r = sc_select_file(card, &key_info->path, &file);
r = sc_select_file(card, path, &file);
LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed");
r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
@ -572,8 +583,9 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
memset(&args, 0, sizeof (args));
args.op_type = OP_TYPE_STORE;
if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
//args.key_len_bits = keybits;
switch (object->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
args.key_type = SC_CARDCTL_MYEID_KEY_RSA;
args.pubexp_len = prkey->u.rsa.exponent.len;
args.pubexp = prkey->u.rsa.exponent.data;
@ -589,16 +601,33 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
args.invq_len = prkey->u.rsa.iqmp.len;
args.invq = prkey->u.rsa.iqmp.data;
//args.key_len_bits = keybits;
args.key_len_bits = prkey->u.rsa.modulus.len;
args.mod = prkey->u.rsa.modulus.data;
}
else {
break;
case SC_PKCS15_TYPE_PRKEY_EC:
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;
break;
case SC_PKCS15_TYPE_SKEY_GENERIC:
case SC_PKCS15_TYPE_SKEY_DES:
case SC_PKCS15_TYPE_SKEY_2DES:
case SC_PKCS15_TYPE_SKEY_3DES:
switch (prkey->algorithm) {
case SC_ALGORITHM_AES:
args.key_type = SC_CARDCTL_MYEID_KEY_AES;
break;
case SC_ALGORITHM_DES:
args.key_type = SC_CARDCTL_MYEID_KEY_DES;
break;
}
args.d = prkey->u.secret.data;
args.d_len = prkey->u.secret.data_len;
break;
}
/* Store RSA key */
r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args);