static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) { struct sc_ec_parameters *ecp; const struct sc_lv_data *oid; int r; pubkey->algorithm = SC_ALGORITHM_EC; r = sc_pkcs15emu_sc_hsm_get_curve_oid(cvc, &oid); if (r != SC_SUCCESS) return r; ecp = calloc(1, sizeof(struct sc_ec_parameters)); if (!ecp) return SC_ERROR_OUT_OF_MEMORY; ecp->der.len = oid->len + 2; ecp->der.value = calloc(ecp->der.len, 1); if (!ecp->der.value) { free(ecp); return SC_ERROR_OUT_OF_MEMORY; } *(ecp->der.value + 0) = 0x06; *(ecp->der.value + 1) = (u8)oid->len; memcpy(ecp->der.value + 2, oid->value, oid->len); ecp->type = 1; // Named curve pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); if (!pubkey->alg_id) { free(ecp->der.value); free(ecp); return SC_ERROR_OUT_OF_MEMORY; } pubkey->alg_id->algorithm = SC_ALGORITHM_EC; pubkey->alg_id->params = ecp; pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen); if (!pubkey->u.ec.ecpointQ.value) return SC_ERROR_OUT_OF_MEMORY; memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen); pubkey->u.ec.ecpointQ.len = cvc->publicPointlen; pubkey->u.ec.params.der.value = malloc(ecp->der.len); if (!pubkey->u.ec.params.der.value) return SC_ERROR_OUT_OF_MEMORY; memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len); pubkey->u.ec.params.der.len = ecp->der.len; sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); return SC_SUCCESS; }
static int sc_hsm_decode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info, struct sc_pkcs15_pubkey *pubkey) { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; struct sc_pkcs15_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)(key_info->params.data); struct sc_ec_params *ecp; u8 *buf; size_t buflen; int r; LOG_FUNC_CALLED(p15card->card->ctx); pubkey->algorithm = SC_ALGORITHM_EC; pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve); sc_pkcs15_fix_ec_parameters(p15card->card->ctx, &pubkey->u.ec.params); ecp = calloc(1, sizeof(struct sc_ec_params)); if (!ecp) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } ecp->der = malloc(ecparams->der.len); if (!ecp->der) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } ecp->der_len = ecparams->der.len; memcpy(ecp->der, ecparams->der.value, ecp->der_len); pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); if (!pubkey->alg_id) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } pubkey->alg_id->algorithm = SC_ALGORITHM_EC; pubkey->alg_id->params = ecp; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, cvc->publicPoint, &cvc->publicPointlen, 1); r = sc_asn1_encode(p15card->card->ctx, asn1_ec_pointQ, &pubkey->u.ec.ecpointQ.value, &pubkey->u.ec.ecpointQ.len); LOG_TEST_RET(p15card->card->ctx, r, "ASN.1 encoding failed"); LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); }
/* * can be used as an SC_ASN1_CALLBACK while parsing a certificate, * or can be called from the sc_pkcs15_pubkey_from_spki_filename */ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubkey, u8 *buf, size_t buflen, int depth) { int r; sc_pkcs15_pubkey_t * pubkey = NULL; sc_pkcs15_der_t pk = { NULL, 0 }; struct sc_algorithm_id pk_alg; struct sc_asn1_entry asn1_pkinfo[C_ASN1_PKINFO_ATTR_SIZE]; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_log(ctx, "sc_pkcs15_pubkey_from_spki %p:%d", buf, buflen); memset(&pk_alg, 0, sizeof(pk_alg)); pubkey = calloc(1, sizeof(sc_pkcs15_pubkey_t)); if (pubkey == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } sc_copy_asn1_entry(c_asn1_pkinfo, asn1_pkinfo); sc_format_asn1_entry(asn1_pkinfo + 0, &pk_alg, NULL, 0); sc_format_asn1_entry(asn1_pkinfo + 1, &pk.value, &pk.len, 0); r = sc_asn1_decode(ctx, asn1_pkinfo, buf, buflen, NULL, NULL); if (r < 0) goto err; pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); if (pubkey->alg_id == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id)); pubkey->algorithm = pk_alg.algorithm; pk_alg.params = NULL; sc_log(ctx, "DEE pk_alg.algorithm=%d", pk_alg.algorithm); /* pk.len is in bits at this point */ switch (pk_alg.algorithm) { case SC_ALGORITHM_EC: /* * TODO we really should only have params in one place! * The alg_id may have the sc_ec_params, * we want to get the curve OID into the * u.ec.params and get the field length too. */ if (pubkey->alg_id->params) { struct sc_ec_params * ecp = (struct sc_ec_params *)pubkey->alg_id->params; pubkey->u.ec.params.der.value = malloc(ecp->der_len); if (pubkey->u.ec.params.der.value) { memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); pubkey->u.ec.params.der.len = ecp->der_len; sc_pkcs15_fix_ec_parameters(ctx,&pubkey->u.ec.params); } } /* * For most keys, the above ASN.1 parsing of a key works, but for EC keys, * the ec_pointQ in a certificate is stored in the bitstring, in its raw format. * RSA for example is stored in the bitstring, as a ASN1 DER * So we encoded the raw ecpointQ into ASN1 DER as the pubkey->data * and let the sc_pkcs15_decode_pubkey below get the ecpointQ out later. */ pk.len >>= 3; /* Assume it is multiple of 8 */ if (pubkey->u.ec.params.field_length == 0) pubkey->u.ec.params.field_length = (pk.len - 1)/2 * 8; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(&asn1_ec_pointQ[0], pk.value, &pk.len, 1); r = sc_asn1_encode(ctx, asn1_ec_pointQ, &pubkey->data.value, &pubkey->data.len); pk.value = NULL; sc_log(ctx, "DEE r=%d data=%p:%d", r, pubkey->data.value, pubkey->data.len); break; default: pk.len >>= 3; /* convert number of bits to bytes */ pubkey->data = pk; /* save in publey */ pk.value = NULL; break; } /* Now decode what every is in pk as it depends on the key algorthim */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); if (r < 0) goto err; *outpubkey = pubkey; pubkey = NULL; return 0; err: if (pubkey) free(pubkey); if (pk.value) free(pk.value); LOG_TEST_RET(ctx, r, "ASN.1 parsing of subjectPubkeyInfo failed"); 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_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; size_t keybits = key_info->modulus_length; unsigned char raw_pubkey[256]; LOG_FUNC_CALLED(ctx); 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 */ 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: /* EC is supported in MyEID v > 3.5. TODO: set correct return value if older MyEID version. */ /* Here the information about curve is not available, that's why supported algorithm is checked without curve OID. */ if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == 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, "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 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 private key"); /* Fill in data structure */ 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 */ if (pubkey != NULL) { struct sc_cardctl_myeid_data_obj data_obj; 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"); 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 RSA key modulus: 'MYEID_GETDATA' failed"); 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); } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; sc_log(ctx, "curve '%s', len %i, oid '%s'", ecparams->named_curve, ecparams->field_length, sc_dump_oid(&(ecparams->id))); 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"); if (pubkey->u.ec.ecpointQ.value) free(pubkey->u.ec.ecpointQ.value); pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2); if (pubkey->u.ec.ecpointQ.value == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2); pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; if (pubkey->u.ec.params.named_curve) free(pubkey->u.ec.params.named_curve); pubkey->u.ec.params.named_curve = NULL; if (pubkey->u.ec.params.der.value) free(pubkey->u.ec.params.der.value); pubkey->u.ec.params.der.value = NULL; pubkey->u.ec.params.der.len = 0; pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve); if (!pubkey->u.ec.params.named_curve) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); LOG_TEST_RET(ctx, r, "Cannot fix EC parameters"); } } if (file) sc_file_free(file); 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_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; 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 (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"); 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)); r = sc_select_file(card, &key_info->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); LOG_TEST_RET(ctx, r, "No authorisation to store MyEID private key"); if (file) sc_file_free(file); /* Fill in data structure */ memset(&args, 0, sizeof (args)); 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.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"); LOG_FUNC_RETURN(ctx, r); }