diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 65c108fc..80c2821a 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -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); diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index d67a83c7..9a58427b 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -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 */ }; diff --git a/src/pkcs15init/myeid.profile b/src/pkcs15init/myeid.profile index 8b84c951..2645261d 100644 --- a/src/pkcs15init/myeid.profile +++ b/src/pkcs15init/myeid.profile @@ -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 { diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 200009a1..3e4bb19e 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -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);