예제 #1
0
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;
}
예제 #2
0
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);
}
예제 #3
0
/*
 * 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);
}
예제 #4
0
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);
}
예제 #5
0
/*
 * 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);
}