int sc_pkcs15_encode_tokeninfo(sc_context_t *ctx,
			       sc_pkcs15_tokeninfo_t *ti,
			       u8 **buf, size_t *buflen)
{
	int r;
	int version = ti->version;
	size_t serial_len, mnfid_len, label_len, flags_len, last_upd_len;
	
	struct sc_asn1_entry asn1_toki[14], asn1_tokeninfo[2];

	sc_copy_asn1_entry(c_asn1_toki, asn1_toki);
	sc_copy_asn1_entry(c_asn1_tokeninfo, asn1_tokeninfo);
	version--;
	sc_format_asn1_entry(asn1_toki + 0, &version, NULL, 1);
	if (ti->serial_number != NULL) {
		u8 serial[128];
		serial_len = 0;
		if (strlen(ti->serial_number)/2 > sizeof(serial))
			return SC_ERROR_BUFFER_TOO_SMALL;
		serial_len = sizeof(serial);
		if (sc_hex_to_bin(ti->serial_number, serial, &serial_len) < 0)
			return SC_ERROR_INVALID_ARGUMENTS;
		sc_format_asn1_entry(asn1_toki + 1, serial, &serial_len, 1);
	} else
		sc_format_asn1_entry(asn1_toki + 1, NULL, NULL, 0);
	if (ti->manufacturer_id != NULL) {
		mnfid_len = strlen(ti->manufacturer_id);
		sc_format_asn1_entry(asn1_toki + 2, ti->manufacturer_id, &mnfid_len, 1);
	} else
		sc_format_asn1_entry(asn1_toki + 2, NULL, NULL, 0);
	if (ti->label != NULL) {
		label_len = strlen(ti->label);
		sc_format_asn1_entry(asn1_toki + 3, ti->label, &label_len, 1);
	} else
		sc_format_asn1_entry(asn1_toki + 3, NULL, NULL, 0);
	if (ti->flags) {
		flags_len = sizeof(ti->flags);
		sc_format_asn1_entry(asn1_toki + 5, &ti->flags, &flags_len, 1);
	} else
		sc_format_asn1_entry(asn1_toki + 5, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 6, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 7, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 8, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 9, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 10, NULL, NULL, 0);
	if (ti->last_update != NULL) {
		last_upd_len = strlen(ti->last_update);
		sc_format_asn1_entry(asn1_toki + 11, ti->last_update, &last_upd_len, 1);
	} else
		sc_format_asn1_entry(asn1_toki + 11, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_toki + 12, NULL, NULL, 0);
	sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1);

	r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
	if (r) {
		sc_error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
		return r;
	}
	return 0;
}
Beispiel #2
0
/*
 * Encode a card verifiable certificate as defined in TR-03110.
 */
int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card,
		sc_cvc_t *cvc,
		u8 ** buf, size_t *buflen)
{
	sc_card_t *card = p15card->card;
	struct sc_asn1_entry asn1_cvc[C_ASN1_CVC_SIZE];
	struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE];
	struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE];
	struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE];
	unsigned int cla,tag;
	size_t taglen;
	size_t lenchr;
	size_t lencar;
	int r;

	sc_copy_asn1_entry(c_asn1_cvc, asn1_cvc);
	sc_copy_asn1_entry(c_asn1_cvcert, asn1_cvcert);
	sc_copy_asn1_entry(c_asn1_cvc_body, asn1_cvc_body);
	sc_copy_asn1_entry(c_asn1_cvc_pubkey, asn1_cvc_pubkey);

	asn1_cvc_pubkey[1].flags = SC_ASN1_OPTIONAL;
	asn1_cvcert[1].flags = SC_ASN1_OPTIONAL;

	sc_format_asn1_entry(asn1_cvc_pubkey    , &cvc->pukoid, NULL, 1);
	if (cvc->primeOrModulus && (cvc->primeOrModuluslen > 0)) {
		sc_format_asn1_entry(asn1_cvc_pubkey + 1, cvc->primeOrModulus, &cvc->primeOrModuluslen, 1);
	}
	sc_format_asn1_entry(asn1_cvc_pubkey + 2, cvc->coefficientAorExponent, &cvc->coefficientAorExponentlen, 1);
	if (cvc->coefficientB && (cvc->coefficientBlen > 0)) {
		sc_format_asn1_entry(asn1_cvc_pubkey + 3, cvc->coefficientB, &cvc->coefficientBlen, 1);
		sc_format_asn1_entry(asn1_cvc_pubkey + 4, cvc->basePointG, &cvc->basePointGlen, 1);
		sc_format_asn1_entry(asn1_cvc_pubkey + 5, cvc->order, &cvc->orderlen, 1);
		if (cvc->publicPoint && (cvc->publicPointlen > 0)) {
			sc_format_asn1_entry(asn1_cvc_pubkey + 6, cvc->publicPoint, &cvc->publicPointlen, 1);
		}
		sc_format_asn1_entry(asn1_cvc_pubkey + 7, cvc->cofactor, &cvc->cofactorlen, 1);
	}
	if (cvc->modulusSize > 0) {
		sc_format_asn1_entry(asn1_cvc_pubkey + 8, &cvc->modulusSize, NULL, 1);
	}

	sc_format_asn1_entry(asn1_cvc_body    , &cvc->cpi, NULL, 1);
	lencar = strlen(cvc->car);
	sc_format_asn1_entry(asn1_cvc_body + 1, &cvc->car, &lencar, 1);
	sc_format_asn1_entry(asn1_cvc_body + 2, &asn1_cvc_pubkey, NULL, 1);
	lenchr = strlen(cvc->chr);
	sc_format_asn1_entry(asn1_cvc_body + 3, &cvc->chr, &lenchr, 1);

	sc_format_asn1_entry(asn1_cvcert    , &asn1_cvc_body, NULL, 1);
	if (cvc->signature && (cvc->signatureLen > 0)) {
		sc_format_asn1_entry(asn1_cvcert + 1, cvc->signature, &cvc->signatureLen, 1);
	}

	sc_format_asn1_entry(asn1_cvc , &asn1_cvcert, NULL, 1);

	r = sc_asn1_encode(card->ctx, asn1_cvc, buf, buflen);
	LOG_TEST_RET(card->ctx, r, "Could not encode card verifiable certificate");

	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
Beispiel #3
0
static int encode_dir_record(sc_context_t *ctx, const sc_app_info_t *app,
			     u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2];
	sc_app_info_t   tapp = *app;
	int r;
	size_t label_len;

	sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord);
	sc_copy_asn1_entry(c_asn1_dir, asn1_dir);
	sc_format_asn1_entry(asn1_dir + 0, asn1_dirrecord, NULL, 1);
	sc_format_asn1_entry(asn1_dirrecord + 0, (void *) tapp.aid.value, (void *) &tapp.aid.len, 1);
	if (tapp.label != NULL) {
		label_len = strlen(tapp.label);
		sc_format_asn1_entry(asn1_dirrecord + 1, tapp.label, &label_len, 1);
	}
	if (tapp.path.len)
		sc_format_asn1_entry(asn1_dirrecord + 2, (void *) tapp.path.value,
				     (void *) &tapp.path.len, 1);
	if (tapp.ddo.value != NULL && tapp.ddo.len)
		sc_format_asn1_entry(asn1_dirrecord + 3, (void *) tapp.ddo.value,
				     (void *) &tapp.ddo.len, 1);
	r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
	LOG_TEST_RET(ctx, r, "Encode DIR record error");

	return SC_SUCCESS;
}
int
sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx,
		struct sc_pkcs15_pubkey_dsa *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_public_key[2];
	struct sc_asn1_entry asn1_dsa_pub_coeff[5];
	int r;
	
	sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
	sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coeff);

	sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coeff, NULL, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coeff + 0,
				key->pub.data, &key->pub.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coeff + 1,
				key->g.data, &key->g.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coeff + 2,
				key->p.data, &key->p.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coeff + 3,
				key->q.data, &key->q.len, 1);

	r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed");

	return 0;
}
Beispiel #5
0
int sc_pkcs15_encode_dodf_entry(sc_context_t *ctx,
			       const struct sc_pkcs15_object *obj,
			       u8 **buf, size_t *bufsize)
{
	struct sc_asn1_entry	asn1_com_data_attr[4],
				asn1_type_data_attr[2],
				asn1_data[2];
	struct sc_pkcs15_data_info *info;
	struct sc_asn1_pkcs15_object data_obj = { (struct sc_pkcs15_object *) obj,
							asn1_com_data_attr, NULL,
							asn1_type_data_attr };
	size_t label_len;

	info = (struct sc_pkcs15_data_info *) obj->data;
	label_len = strlen(info->app_label);

	sc_copy_asn1_entry(c_asn1_com_data_attr, asn1_com_data_attr);
	sc_copy_asn1_entry(c_asn1_type_data_attr, asn1_type_data_attr);
	sc_copy_asn1_entry(c_asn1_data, asn1_data);

	if (label_len)
		sc_format_asn1_entry(asn1_com_data_attr + 0, &info->app_label, &label_len, 1);

	if (sc_valid_oid(&info->app_oid))
		sc_format_asn1_entry(asn1_com_data_attr + 1, &info->app_oid, NULL, 1);

	sc_format_asn1_entry(asn1_type_data_attr + 0, &info->path, NULL, 1);
	sc_format_asn1_entry(asn1_data + 0, &data_obj, NULL, 1);

	return sc_asn1_encode(ctx, asn1_data, buf, bufsize);
}
int
sc_pkcs15_encode_enveloped_data(sc_context_t *ctx,
				struct sc_pkcs15_enveloped_data *data,
				u8 **buf, size_t *buflen)
{
	static struct sc_object_id oid_id_data = {{ 1, 2, 840, 113549, 1, 7, 1, -1 }};
	struct sc_asn1_entry	asn1_enveloped_data_attr[5],
				asn1_content_attr[4],
				asn1_encr_content[2],
				asn1_recipients_attr[2],
				asn1_kekri_attr[5],
				asn1_kek_attr[4];
	int version2 = 2, version4 = 4, r;

	sc_copy_asn1_entry(c_asn1_enveloped_data_attr, asn1_enveloped_data_attr);
	sc_copy_asn1_entry(c_asn1_content_attr, asn1_content_attr);
	sc_copy_asn1_entry(c_asn1_encr_content, asn1_encr_content);
	sc_copy_asn1_entry(c_asn1_recipients_attr, asn1_recipients_attr);
	sc_copy_asn1_entry(c_asn1_kekri_attr, asn1_kekri_attr);
	sc_copy_asn1_entry(c_asn1_kek_attr, asn1_kek_attr);

	sc_format_asn1_entry(asn1_enveloped_data_attr + 0,
				&version2, NULL, 1);
	sc_format_asn1_entry(asn1_enveloped_data_attr + 2,
				asn1_recipients_attr, NULL, 1);
	sc_format_asn1_entry(asn1_enveloped_data_attr + 3,
				asn1_content_attr, NULL, 1);

	sc_format_asn1_entry(asn1_content_attr + 0, &oid_id_data, NULL, 1);
	sc_format_asn1_entry(asn1_content_attr + 1, &data->ce_alg, NULL, 1);
	sc_format_asn1_entry(asn1_content_attr + 2,
			asn1_encr_content, NULL, 1);
	sc_format_asn1_entry(asn1_encr_content + 0,
			data->content, &data->content_len, 1);

	sc_format_asn1_entry(asn1_recipients_attr + 0,
			asn1_kekri_attr, NULL, 1);

	sc_format_asn1_entry(asn1_kekri_attr + 0,
			&version4, NULL, 1);
	sc_format_asn1_entry(asn1_kekri_attr + 1,
			asn1_kek_attr, NULL, 1);
	sc_format_asn1_entry(asn1_kekri_attr + 2,
			&data->ke_alg, NULL, 1);
	sc_format_asn1_entry(asn1_kekri_attr + 3,
			data->key, &data->key_len, 1);

	sc_format_asn1_entry(asn1_kek_attr + 0,
			&data->id, &data->id.len, 1);

	memset(&data, 0, sizeof(data));

	r = sc_asn1_encode(ctx, asn1_enveloped_data_attr, buf, buflen);
	return r;
}
static int
sc_pkcs15_encode_prkey_dsa(sc_context_t *ctx,
		struct sc_pkcs15_prkey_dsa *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry	asn1_dsa_prkey_obj[2];

	sc_copy_asn1_entry(c_asn1_dsa_prkey_obj, asn1_dsa_prkey_obj);
	sc_format_asn1_entry(asn1_dsa_prkey_obj + 0,
			key->priv.data, &key->priv.len, 1);

	return sc_asn1_encode(ctx, asn1_dsa_prkey_obj, buf, buflen);
}
Beispiel #8
0
int
sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE];
	int r;

	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);

	r = sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen);
	LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

	sc_log(ctx, "EC key->ecpointQ=%p:%d *buf=%p:%d", key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen);
	return 0;
}
Beispiel #9
0
int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2];
	struct sc_asn1_entry asn1_auth_type[2];
	struct sc_asn1_entry asn1_auth_type_choice[4];
	struct sc_pkcs15_auth_info *info = (struct sc_pkcs15_auth_info *) obj->data;
	struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj,
						 asn1_com_ao_attr, NULL, asn1_type_pin_attr };
	int r;
	size_t flags_len;
	size_t padchar_len = 1;

	if (info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_NOT_SUPPORTED;

	sc_copy_asn1_entry(c_asn1_auth_type, asn1_auth_type);
	sc_copy_asn1_entry(c_asn1_auth_type_choice, asn1_auth_type_choice);
        sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr);
        sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr);
        sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr);

	sc_format_asn1_entry(asn1_auth_type + 0, asn1_auth_type_choice, NULL, 1);
	sc_format_asn1_entry(asn1_auth_type_choice + 0, &pin_obj, NULL, 1);

	sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1);

	flags_len = sizeof(info->attrs.pin.flags);
	sc_format_asn1_entry(asn1_pin_attr + 0, &info->attrs.pin.flags, &flags_len, 1);
	sc_format_asn1_entry(asn1_pin_attr + 1, &info->attrs.pin.type, NULL, 1);
	sc_format_asn1_entry(asn1_pin_attr + 2, &info->attrs.pin.min_length, NULL, 1);
	sc_format_asn1_entry(asn1_pin_attr + 3, &info->attrs.pin.stored_length, NULL, 1);
	if (info->attrs.pin.max_length > 0)
		sc_format_asn1_entry(asn1_pin_attr + 4, &info->attrs.pin.max_length, NULL, 1);
	if (info->attrs.pin.reference >= 0)
		sc_format_asn1_entry(asn1_pin_attr + 5, &info->attrs.pin.reference, NULL, 1);
	/* FIXME: check if pad_char present */
	sc_format_asn1_entry(asn1_pin_attr + 6, &info->attrs.pin.pad_char, &padchar_len, 1);
	sc_format_asn1_entry(asn1_pin_attr + 8, &info->path, NULL, info->path.len ? 1 : 0);

	sc_format_asn1_entry(asn1_com_ao_attr + 0, &info->auth_id, NULL, 1);

	r = sc_asn1_encode(ctx, asn1_auth_type, buf, buflen);

	return r;
}
Beispiel #10
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);
}
Beispiel #11
0
int
sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx,
		struct sc_pkcs15_pubkey_gostr3410 *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_gostr3410_pub_coeff[C_ASN1_GOSTR3410_PUB_COEFFICIENTS_SIZE];
	int r;

	LOG_FUNC_CALLED(ctx);
	sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_pub_coeff);
	sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 0, key->xy.data, &key->xy.len, 1);

	r = sc_asn1_encode(ctx, asn1_gostr3410_pub_coeff, buf, buflen);
	LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static int encode_ddo(struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_ddo[5];
	int r;
	size_t label_len;
	
	sc_copy_asn1_entry(c_asn1_ddo, asn1_ddo);

	sc_format_asn1_entry(asn1_ddo + 1, &card->file_odf.path, NULL, 0);
	sc_format_asn1_entry(asn1_ddo + 2, &card->file_tokeninfo.path, NULL, 0);

	r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
	if (r) {
		sc_error(ctx, "sc_asn1_encode() failed: %s\n",
		      sc_strerror(r));
		return r;
	}
	return 0;
}
Beispiel #13
0
int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2];
	struct sc_asn1_entry asn1_pin[2];
	struct sc_pkcs15_pin_info *pin =
                (struct sc_pkcs15_pin_info *) obj->data;
	struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj,
						 asn1_com_ao_attr, NULL, asn1_type_pin_attr };
	int r;
	size_t flags_len;
	size_t padchar_len = 1;

	sc_copy_asn1_entry(c_asn1_pin, asn1_pin);
        sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr);
        sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr);
        sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr);

	sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 1);

	sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1);

	flags_len = sizeof(pin->flags);
	sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 1);
	sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 1);
	sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 1);
	sc_format_asn1_entry(asn1_pin_attr + 3, &pin->stored_length, NULL, 1);
	if (pin->max_length > 0)
		sc_format_asn1_entry(asn1_pin_attr + 4, &pin->max_length, NULL, 1);
	if (pin->reference >= 0)
		sc_format_asn1_entry(asn1_pin_attr + 5, &pin->reference, NULL, 1);
	/* FIXME: check if pad_char present */
	sc_format_asn1_entry(asn1_pin_attr + 6, &pin->pad_char, &padchar_len, 1);
	sc_format_asn1_entry(asn1_pin_attr + 8, &pin->path, NULL, pin->path.len ? 1 : 0);

	sc_format_asn1_entry(asn1_com_ao_attr + 0, &pin->auth_id, NULL, 1);

	assert(pin->magic == SC_PKCS15_PIN_MAGIC);
	r = sc_asn1_encode(ctx, asn1_pin, buf, buflen);

	return r;
}
Beispiel #14
0
int
sc_pkcs15_encode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_public_key[C_ASN1_PUBLIC_KEY_SIZE];
	struct sc_asn1_entry asn1_rsa_pub_coefficients[C_ASN1_RSA_PUB_COEFFICIENTS_SIZE];
	int r;

	sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
	sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coefficients, NULL, 1);

	sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_pub_coefficients);
	sc_format_asn1_entry(asn1_rsa_pub_coefficients + 0, key->modulus.data, &key->modulus.len, 1);
	sc_format_asn1_entry(asn1_rsa_pub_coefficients + 1, key->exponent.data, &key->exponent.len, 1);

	r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
	LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

	return 0;
}
Beispiel #15
0
int
sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key,
		u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_public_key[C_ASN1_PUBLIC_KEY_SIZE];
	struct sc_asn1_entry asn1_dsa_pub_coefficients[C_ASN1_DSA_PUB_COEFFICIENTS_SIZE];
	int r;

	LOG_FUNC_CALLED(ctx);
	sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
	sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coefficients);

	sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coefficients, NULL, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coefficients + 0, key->pub.data, &key->pub.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coefficients + 1, key->g.data, &key->g.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coefficients + 2, key->p.data, &key->p.len, 1);
	sc_format_asn1_entry(asn1_dsa_pub_coefficients + 3, key->q.data, &key->q.len, 1);

	r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
	LOG_TEST_RET(ctx, r, "ASN.1 encoding failed");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Beispiel #16
0
int
sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj,
                           u8 **buf, size_t *bufsize)
{
    struct sc_asn1_entry	asn1_cred_ident[3], asn1_com_cert_attr[4],
                  asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
                  asn1_cert[2], asn1_x509_cert_value_choice[3];
    struct sc_pkcs15_cert_info *infop = (sc_pkcs15_cert_info_t *) obj->data;
    sc_pkcs15_der_t *der = &infop->value;
    struct sc_asn1_pkcs15_object cert_obj = { (struct sc_pkcs15_object *) obj,
               asn1_com_cert_attr, NULL,
               asn1_type_cert_attr
    };
    int r;

    sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
    sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr);
    sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr);
    sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice);
    sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
    sc_copy_asn1_entry(c_asn1_cert, asn1_cert);

    sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &infop->id, NULL, 1);
    if (infop->authority)
        sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1);
    if (infop->path.len || !der->value) {
        sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &infop->path, NULL, 1);
    } else {
        sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, der->value, &der->len, 1);
    }
    sc_format_asn1_entry(asn1_type_cert_attr + 0, &asn1_x509_cert_value_choice, NULL, 1);
    sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1);

    r = sc_asn1_encode(ctx, asn1_cert, buf, bufsize);

    return r;
}
Beispiel #17
0
int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE];
	struct sc_asn1_entry asn1_com_pubkey_attr[C_ASN1_COM_PUBKEY_ATTR_SIZE];
	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 };
	struct sc_asn1_pkcs15_object gostr3410key_obj =  { (struct sc_pkcs15_object *) obj,
						    asn1_com_key_attr,
						    asn1_com_pubkey_attr, asn1_gostr3410_type_attr };
	struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
	int r;
	size_t af_len, usage_len;

	sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
	sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
	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);
	sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
	sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
	sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);

	switch (obj->type) {
	case SC_PKCS15_TYPE_PUBKEY_RSA:
		sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 1);

		sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 1);
		if (pubkey->path.len || !obj->content.value)
			sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &pubkey->path, NULL, 1);
		else
			sc_format_asn1_entry(asn1_rsakey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 1, &pubkey->modulus_length, NULL, 1);
		break;

	case SC_PKCS15_TYPE_PUBKEY_DSA:
		sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 1);

		sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 1);

		sc_format_asn1_entry(asn1_dsakey_attr + 0, &pubkey->path, NULL, 1);
		break;

	case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
		sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 1);

		sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 1);

		sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &pubkey->path, NULL, 1);
		if (pubkey->params.len == sizeof(*keyinfo_gostparams))   {
			keyinfo_gostparams = pubkey->params.data;
			sc_format_asn1_entry(asn1_gostr3410key_attr + 1,
					&keyinfo_gostparams->gostr3410, NULL, 1);
			sc_format_asn1_entry(asn1_gostr3410key_attr + 2,
					&keyinfo_gostparams->gostr3411, NULL, 1);
			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:
		sc_log(ctx,  "Unsupported public key type: %X", obj->type);
		LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
		break;
	}

	sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1);
	usage_len = sizeof(pubkey->usage);
	sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1);
	if (pubkey->native == 0)
		sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1);
	if (pubkey->access_flags) {
		af_len = sizeof(pubkey->access_flags);
		sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1);
	}
	if (pubkey->key_reference >= 0)
		sc_format_asn1_entry(asn1_com_key_attr + 4, &pubkey->key_reference, NULL, 1);
	sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 1);

	if (pubkey->subject.value && pubkey->subject.len)
		sc_format_asn1_entry(asn1_com_pubkey_attr + 0, pubkey->subject.value, &pubkey->subject.len, 1);
	else
		memset(asn1_com_pubkey_attr, 0, sizeof(asn1_com_pubkey_attr));

	r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen);

	sc_log(ctx, "Key path %s", sc_print_path(&pubkey->path));
	return r;
}
/* 
 * 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[3];
	struct sc_asn1_entry asn1_ec_pointQ[2];

	sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"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;

	sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE pk_alg.algorithm=%d",pk_alg.algorithm);

	/* pk.len is in bits at this point */
	switch (pk_alg.algorithm) {
		case SC_ALGORITHM_EC:
			/* 
			 * 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 a bitstring, but 
			 * in PKCS#11 it is an octet string and we just decoded its 
			 * contents from the bitstring in the certificate. So we need to encode it 
			 * back to an octet string so we can store it as an octet string. 
			 */
			pk.len >>= 3;  /* Assume it is multiple of 8 */
//			pubkey->u.ec.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);
		sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"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);

	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 parsing of  subjectPubkeyInfo failed");
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}
Beispiel #19
0
int boxing_pace_output_to_buf(sc_context_t *ctx,
        const struct establish_pace_channel_output *output,
        unsigned char **asn1, size_t *asn1_len)
{
    uint16_t status_mse_set_at = ((output->mse_set_at_sw1 & 0xff) << 8) | output->mse_set_at_sw2;
    size_t result_len = sizeof output->result,
           status_mse_set_at_len = sizeof status_mse_set_at;
    struct sc_asn1_entry EstablishPACEChannelOutput_data[
        sizeof g_EstablishPACEChannelOutput_data/
        sizeof *g_EstablishPACEChannelOutput_data];
    struct sc_asn1_entry EstablishPACEChannel[
        sizeof g_EstablishPACEChannel/
        sizeof *g_EstablishPACEChannel];
    struct sc_asn1_entry errorCode[
        sizeof g_octet_string/
        sizeof *g_octet_string];
    struct sc_asn1_entry statusMSESetAT[
        sizeof g_octet_string/
        sizeof *g_octet_string];
    struct sc_asn1_entry idPICC[
        sizeof g_octet_string/
        sizeof *g_octet_string];
    struct sc_asn1_entry curCAR[
        sizeof g_octet_string/
        sizeof *g_octet_string];
    struct sc_asn1_entry prevCAR[
        sizeof g_octet_string/
        sizeof *g_octet_string];

    sc_copy_asn1_entry(g_EstablishPACEChannel,
            EstablishPACEChannel);
    sc_format_asn1_entry(EstablishPACEChannel,
            EstablishPACEChannelOutput_data, 0, 1);

    sc_copy_asn1_entry(g_EstablishPACEChannelOutput_data,
            EstablishPACEChannelOutput_data);

    sc_format_asn1_entry(EstablishPACEChannelOutput_data+0,
            errorCode, 0, 1);
    sc_copy_asn1_entry(g_octet_string,
            errorCode);
    sc_format_asn1_entry(errorCode,
            (unsigned char *) &output->result, &result_len, 1);

    sc_format_asn1_entry(EstablishPACEChannelOutput_data+1,
            statusMSESetAT, 0, 1);
    sc_copy_asn1_entry(g_octet_string,
            statusMSESetAT);
    sc_format_asn1_entry(statusMSESetAT,
            &status_mse_set_at, &status_mse_set_at_len, 1);

    if (output->ef_cardaccess) {
        sc_format_asn1_entry(EstablishPACEChannelOutput_data+2,
                output->ef_cardaccess, (size_t *) &output->ef_cardaccess_length, 1);
    }

    if (output->id_icc) {
        sc_format_asn1_entry(EstablishPACEChannelOutput_data+3,
                idPICC, 0, 1);
        sc_copy_asn1_entry(g_octet_string,
                idPICC);
        sc_format_asn1_entry(idPICC,
                output->id_icc, (size_t *) &output->id_icc_length, 1);
    }

    if (output->recent_car) {
        sc_format_asn1_entry(EstablishPACEChannelOutput_data+4,
                curCAR, 0, 1);
        sc_copy_asn1_entry(g_octet_string,
                curCAR);
        sc_format_asn1_entry(curCAR,
                output->recent_car, (size_t *) &output->recent_car_length, 1);
    }

    if (output->previous_car) {
        sc_format_asn1_entry(EstablishPACEChannelOutput_data+5,
            prevCAR, 0, 1);
        sc_copy_asn1_entry(g_octet_string,
                prevCAR);
        sc_format_asn1_entry(prevCAR,
            output->previous_car, (size_t *) &output->previous_car_length, 1);
    }

    return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len);
}
int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1];
	struct sc_asn1_entry asn1_rsakey_value_choice[3];
	struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2];
	struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2];
	struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2];
	struct sc_asn1_entry asn1_pubkey_choice[4];
	struct sc_asn1_entry asn1_pubkey[2];
	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 dsakey_obj = { (struct sc_pkcs15_object *) obj,
						    asn1_com_key_attr,
						    asn1_com_pubkey_attr, asn1_dsa_type_attr };
	struct sc_asn1_pkcs15_object gostr3410key_obj =  { (struct sc_pkcs15_object *) obj,
						    asn1_com_key_attr,
						    asn1_com_pubkey_attr, asn1_gostr3410_type_attr };
	struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
	int r;
	size_t af_len, usage_len;

	sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey);
	sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice);
	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_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);
	sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);
	sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr);
	sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);

	switch (obj->type) {
	case SC_PKCS15_TYPE_PUBKEY_RSA:
		sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 1);

		sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 1);
		if (pubkey->path.len || !obj->content.value)
			sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &pubkey->path, NULL, 1);
		else
			sc_format_asn1_entry(asn1_rsakey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 1, &pubkey->modulus_length, NULL, 1);
		break;

	case SC_PKCS15_TYPE_PUBKEY_DSA:
		sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 1);

		sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 1);

		sc_format_asn1_entry(asn1_dsakey_attr + 0, &pubkey->path, NULL, 1);
		break;

	case SC_PKCS15_TYPE_PUBKEY_GOSTR3410:
		sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 1);

		sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 1);

		sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &pubkey->path, NULL, 1);
		if (pubkey->params.len == sizeof(*keyinfo_gostparams))
		{
			keyinfo_gostparams = pubkey->params.data;
			sc_format_asn1_entry(asn1_gostr3410key_attr + 1,
					&keyinfo_gostparams->gostr3410, NULL, 1);
			sc_format_asn1_entry(asn1_gostr3410key_attr + 2,
					&keyinfo_gostparams->gostr3411, NULL, 1);
			sc_format_asn1_entry(asn1_gostr3410key_attr + 3,
					&keyinfo_gostparams->gost28147, NULL, 1);
		}
		break;
	default:
		/* TODO: -DEE Should add ECC  but don't have PKCS15 card with ECC */
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key type: %X\n", obj->type);
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL);
		break;
	}

	sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1);
	usage_len = sizeof(pubkey->usage);
	sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1);
	if (pubkey->native == 0)
		sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1);
	if (pubkey->access_flags) {
		af_len = sizeof(pubkey->access_flags);
		sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1);
	}
	if (pubkey->key_reference >= 0)
		sc_format_asn1_entry(asn1_com_key_attr + 4, &pubkey->key_reference, NULL, 1);
	sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 1);

	r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen);

	return r;
}
Beispiel #21
0
/*
 * Encode a pubkey as a SPKI, useful for pkcs15-tool, and for PKCS#15 files.
 */
int
sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubkey,
		u8 **buf, size_t *len)
{
	int r;
	struct sc_asn1_entry  asn1_spki_key[2],
	asn1_spki_key_items[3];
	struct sc_pkcs15_u8 pkey;
	size_t key_len;

	LOG_FUNC_CALLED(ctx);
	pkey.value =  NULL;
	pkey.len = 0;

	sc_log(ctx, "Encoding public key with algorithm %i", pubkey->algorithm);
	if (!pubkey->alg_id)   {
		pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id));
		if (!pubkey->alg_id)
			LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);

		sc_init_oid(&pubkey->alg_id->oid);
		pubkey->alg_id->algorithm = pubkey->algorithm;
	}

	/* make sure we have a der encoded value first */
	if (pubkey->data.value == NULL){
	    r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pubkey->data.value, &pubkey->data.len);
	    LOG_TEST_RET(ctx, r, "public key encoding failed");
	}

	switch (pubkey->algorithm) {
	case SC_ALGORITHM_EC:
		/*
		 * most keys, but not EC have only one encoding.
		 * For a SPKI, the ecpoint is placed directly in the
		 * BIT STRING
		 */
		key_len = pubkey->u.ec.ecpointQ.len * 8;
		pkey.value = pubkey->u.ec.ecpointQ.value;
		pkey.len = 0; /* flag as do not delete */
		/* TODO make sure algorithm params are available*/
		/* if not can we copy them from the u.ec */
		r = 0;
		break;
	case SC_ALGORITHM_GOSTR3410:
		/* TODO is this needed?  does it cause mem leak? */
		pubkey->alg_id->params = &pubkey->u.gostr3410.params;
		r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
		key_len = pkey.len * 8;
		break;
	default:
		r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
		key_len = pkey.len * 8;
		break;
	}

	if (r == 0) {
		sc_copy_asn1_entry(c_asn1_spki_key, asn1_spki_key);
		sc_copy_asn1_entry(c_asn1_spki_key_items, asn1_spki_key_items);
		sc_format_asn1_entry(asn1_spki_key + 0, asn1_spki_key_items, NULL, 1);
		sc_format_asn1_entry(asn1_spki_key_items + 0, pubkey->alg_id, NULL, 1);
		sc_format_asn1_entry(asn1_spki_key_items + 1, pkey.value, &key_len, 1);

		r =  sc_asn1_encode(ctx, asn1_spki_key, buf, len);
	}

	if (pkey.len && pkey.value)
		free(pkey.value);

	LOG_FUNC_RETURN(ctx, r);
}
int sc_pkcs15_encode_odf(sc_context_t *ctx,
			 struct sc_pkcs15_card *p15card,
			 u8 **buf, size_t *buflen)
{
	sc_path_t path;
	struct sc_asn1_entry asn1_obj_or_path[] = {
		{ "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	struct sc_asn1_entry *asn1_paths = NULL;
	struct sc_asn1_entry *asn1_odf = NULL;
	int df_count = 0, r, c = 0;
	const int nr_indexes = sizeof(odf_indexes)/sizeof(odf_indexes[0]);
	struct sc_pkcs15_df *df;
	
	df = p15card->df_list;
	while (df != NULL) {
		df_count++;
		df = df->next;
	};
	if (df_count == 0) {
		sc_error(ctx, "No DF's found.\n");
		return SC_ERROR_OBJECT_NOT_FOUND;
	}
	asn1_odf = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count + 1));
	if (asn1_odf == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}
	asn1_paths = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count * 2));
	if (asn1_paths == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}
	for (df = p15card->df_list; df != NULL; df = df->next) {
		int j, type = -1;

		for (j = 0; j < nr_indexes; j++)
			if (odf_indexes[j] == df->type) {
				type = j;
				break;
			}
		if (type == -1) {
			sc_error(ctx, "Unsupported DF type.\n");
			continue;
		}
		asn1_odf[c] = c_asn1_odf[type];
		sc_format_asn1_entry(asn1_odf + c, asn1_paths + 2*c, NULL, 1);
		sc_copy_asn1_entry(asn1_obj_or_path, asn1_paths + 2*c);
		sc_format_asn1_entry(asn1_paths + 2*c, &df->path, NULL, 1);
		c++;
	}
	asn1_odf[c].name = NULL;
	r = sc_asn1_encode(ctx, asn1_odf, buf, buflen);
err:
	if (asn1_paths != NULL)
		free(asn1_paths);
	if (asn1_odf != NULL)
		free(asn1_odf);
	return r;
}
Beispiel #23
0
static int sm_decrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
        const sc_apdu_t *sm_apdu, sc_apdu_t *apdu)
{
    int r;
    struct sc_asn1_entry sm_rapdu[4];
    struct sc_asn1_entry my_sm_rapdu[4];
    u8 sw[2], mac[8], fdata[SC_MAX_EXT_APDU_BUFFER_SIZE];
    size_t sw_len = sizeof sw, mac_len = sizeof mac, fdata_len = sizeof fdata,
           buf_len, asn1_len;
    const u8 *buf;
    u8 *data = NULL, *mac_data = NULL, *asn1 = NULL;

    sc_copy_asn1_entry(c_sm_rapdu, sm_rapdu);
    sc_format_asn1_entry(sm_rapdu + 0, fdata, &fdata_len, 0);
    sc_format_asn1_entry(sm_rapdu + 1, sw, &sw_len, 0);
    sc_format_asn1_entry(sm_rapdu + 2, mac, &mac_len, 0);

    r = sc_asn1_decode(card->ctx, sm_rapdu, sm_apdu->resp, sm_apdu->resplen,
            &buf, &buf_len);
    if (r < 0)
        goto err;
    if (buf_len > 0) {
        r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
        goto err;
    }


    if (sm_rapdu[2].flags & SC_ASN1_PRESENT) {
        /* copy from sm_apdu to my_sm_apdu, but leave mac at default */
        sc_copy_asn1_entry(sm_rapdu, my_sm_rapdu);
        sc_copy_asn1_entry(&c_sm_rapdu[2], &my_sm_rapdu[2]);

        r = sc_asn1_encode(card->ctx, my_sm_rapdu, &asn1, &asn1_len);
        if (r < 0)
            goto err;
        r = add_padding(ctx, asn1, asn1_len, &mac_data);
        if (r < 0) {
            goto err;
        }
        
        r = ctx->verify_authentication(card, ctx, mac, mac_len,
                mac_data, r);
        if (r < 0)
            goto err;
    } else {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Cryptographic Checksum missing");
        r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
        goto err;
    }


    if (sm_rapdu[0].flags & SC_ASN1_PRESENT) {
        if (ctx->padding_indicator != fdata[0]) {
            r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
            goto err;
        }
        r = ctx->decrypt(card, ctx, fdata + 1, fdata_len - 1, &data);
        if (r < 0)
            goto err;
        buf_len = r;

        r = rm_padding(ctx->padding_indicator, data, buf_len);
        if (r < 0) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not remove padding");
            goto err;
        }

        if (apdu->resplen < r || (r && !apdu->resp)) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
                    "Response of SM APDU %u byte%s too long", r-apdu->resplen,
                    r-apdu->resplen < 2 ? "" : "s");
            r = SC_ERROR_OUT_OF_MEMORY;
            goto err;
        }
        /* Flawfinder: ignore */
        memcpy(apdu->resp, data, r);
        apdu->resplen = r;
    } else {
        apdu->resplen = 0;
    }

    if (sm_rapdu[1].flags & SC_ASN1_PRESENT) {
        if (sw_len != 2) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Length of processing status bytes must be 2");
            r = SC_ERROR_ASN1_END_OF_CONTENTS;
            goto err;
        }
        apdu->sw1 = sw[0];
        apdu->sw2 = sw[1];
    } else {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Authenticated status bytes are missing");
        r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
        goto err;
    }

    sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU sw1=%02x sw2=%02x",
            apdu->sw1, apdu->sw2);
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU response data",
            apdu->resp, apdu->resplen);

    r = SC_SUCCESS;

err:
    free(asn1);
    free(mac_data);
    if (data) {
        sc_mem_clear(data, buf_len);
        free(data);
    }

    return r;
}
Beispiel #24
0
int boxing_pace_capabilities_to_buf(sc_context_t *ctx,
        const unsigned long sc_reader_t_capabilities,
        unsigned char **asn1, size_t *asn1_len)
{
    int yes = 1, no = 0;
    struct sc_asn1_entry PACECapabilities_data[
        sizeof g_PACECapabilities_data/
        sizeof *g_PACECapabilities_data];
    struct sc_asn1_entry PACECapabilities[
        sizeof g_PACECapabilities/
        sizeof *g_PACECapabilities];
    struct sc_asn1_entry capabilityPACE[
        sizeof g_boolean/
        sizeof *g_boolean];
    struct sc_asn1_entry capabilityEID[
        sizeof g_boolean/
        sizeof *g_boolean];
    struct sc_asn1_entry capabilityESign[
        sizeof g_boolean/
        sizeof *g_boolean];
    struct sc_asn1_entry capabilityDestroy[
        sizeof g_boolean/
        sizeof *g_boolean];

    sc_copy_asn1_entry(g_EstablishPACEChannel,
            PACECapabilities);
    sc_format_asn1_entry(PACECapabilities,
            PACECapabilities_data, 0, 1);

    sc_copy_asn1_entry(g_PACECapabilities_data,
            PACECapabilities_data);
    sc_format_asn1_entry(PACECapabilities_data+0,
            &capabilityPACE, NULL, 1);
    sc_format_asn1_entry(PACECapabilities_data+1,
            &capabilityEID, NULL, 1);
    sc_format_asn1_entry(PACECapabilities_data+2,
            &capabilityESign, NULL, 1);
    sc_format_asn1_entry(PACECapabilities_data+3,
            &capabilityDestroy, NULL, 1);

    sc_copy_asn1_entry(g_boolean,
            capabilityPACE);
    sc_format_asn1_entry(capabilityPACE,
            sc_reader_t_capabilities & SC_READER_CAP_PACE_GENERIC
            ? &yes : &no, NULL, 1);

    sc_copy_asn1_entry(g_boolean,
            capabilityEID);
    sc_format_asn1_entry(capabilityEID,
            sc_reader_t_capabilities & SC_READER_CAP_PACE_EID
            ? &yes : &no, NULL, 1);

    sc_copy_asn1_entry(g_boolean,
            capabilityESign);
    sc_format_asn1_entry(capabilityESign,
            sc_reader_t_capabilities & SC_READER_CAP_PACE_ESIGN
            ? &yes : &no, NULL, 1);

    sc_copy_asn1_entry(g_boolean,
            capabilityDestroy);
    sc_format_asn1_entry(capabilityDestroy,
            sc_reader_t_capabilities & SC_READER_CAP_PACE_DESTROY_CHANNEL
            ? &yes : &no, NULL, 1);

    return sc_asn1_encode(ctx, PACECapabilities, asn1, asn1_len);
}
int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[1];
	struct sc_asn1_entry asn1_rsakey_attr[4], asn1_prk_rsa_attr[2];
	struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2],
			asn1_dsakey_value_attr[3],
			asn1_dsakey_i_p_attr[2];
	struct sc_asn1_entry asn1_prkey[3];
	struct sc_asn1_pkcs15_object rsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
						       asn1_com_prkey_attr, asn1_prk_rsa_attr };
	struct sc_asn1_pkcs15_object dsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
						       asn1_com_prkey_attr, asn1_prk_dsa_attr };
	struct sc_pkcs15_prkey_info *prkey =
                (struct sc_pkcs15_prkey_info *) obj->data;
	int r;
	size_t af_len, usage_len;

        sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);

        sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
        sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
        sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
        sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
	sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr);
	sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr);

        sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
        sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);

	switch (obj->type) {
	case SC_PKCS15_TYPE_PRKEY_RSA:
		sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 1);
		sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 1);
		break;
	case SC_PKCS15_TYPE_PRKEY_DSA:
		sc_format_asn1_entry(asn1_prkey + 1, &dsa_prkey_obj, NULL, 1);
		sc_format_asn1_entry(asn1_prk_dsa_attr + 0, asn1_dsakey_value_attr, NULL, 1);
		if (prkey->path.type != SC_PATH_TYPE_PATH_PROT) {
			/* indirect: just add the path */
			sc_format_asn1_entry(asn1_dsakey_value_attr + 0,
					&prkey->path, NULL, 1);
		} else {
			/* indirect-protected */
			sc_format_asn1_entry(asn1_dsakey_value_attr + 1,
					asn1_dsakey_i_p_attr, NULL, 1);
			sc_format_asn1_entry(asn1_dsakey_i_p_attr + 0,
					&prkey->path, NULL, 1);
		}
                break;
	default:
		sc_error(ctx, "Invalid private key type: %X\n", obj->type);
		SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
		break;
	}
	sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1);
	usage_len = sizeof(prkey->usage);
	sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1);
	if (prkey->native == 0)
		sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1);
	if (prkey->access_flags) {
		af_len = sizeof(prkey->access_flags);
		sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1);
	}
	if (prkey->key_reference >= 0)
		sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 1);
	r = sc_asn1_encode(ctx, asn1_prkey, buf, buflen);

	return r;
}
Beispiel #26
0
int boxing_pace_input_to_buf(sc_context_t *ctx,
        const struct establish_pace_channel_input *input,
        unsigned char **asn1, size_t *asn1_len)
{
    size_t pin_id_len = sizeof input->pin_id;
    struct sc_asn1_entry EstablishPACEChannelInput_data[
        sizeof g_EstablishPACEChannelInput_data/
        sizeof *g_EstablishPACEChannelInput_data];
    struct sc_asn1_entry EstablishPACEChannel[
        sizeof g_EstablishPACEChannel/
        sizeof *g_EstablishPACEChannel];
    struct sc_asn1_entry passwordID[
        sizeof g_int_as_octet_string/
        sizeof *g_int_as_octet_string];
    struct sc_asn1_entry transmittedPassword[
        sizeof g_numeric_string_as_octet_string/
        sizeof *g_numeric_string_as_octet_string];
    struct sc_asn1_entry cHAT[
        sizeof g_octet_string/
        sizeof *g_octet_string];

    sc_copy_asn1_entry(g_EstablishPACEChannel,
            EstablishPACEChannel);
    sc_format_asn1_entry(EstablishPACEChannel,
            EstablishPACEChannelInput_data, 0, 1);

    sc_copy_asn1_entry(g_EstablishPACEChannelInput_data,
            EstablishPACEChannelInput_data);

    sc_format_asn1_entry(EstablishPACEChannelInput_data+0,
            passwordID, 0, 1);
    sc_copy_asn1_entry(g_int_as_octet_string,
            passwordID);
    sc_format_asn1_entry(passwordID,
            (unsigned char *) &input->pin_id, &pin_id_len, 1);

    if (input->pin) {
        sc_format_asn1_entry(EstablishPACEChannelInput_data+1,
                transmittedPassword,
                0, 1);
        sc_copy_asn1_entry(g_numeric_string_as_octet_string,
                transmittedPassword);
        sc_format_asn1_entry(transmittedPassword,
                (unsigned char *) input->pin,
                (size_t *) &input->pin_length, 1);
    }

    if (input->chat) {
        sc_format_asn1_entry(EstablishPACEChannelInput_data+2,
                cHAT,
                0, 1);
        sc_copy_asn1_entry(g_octet_string,
                cHAT);
        sc_format_asn1_entry(cHAT,
                (unsigned char *) input->chat,
                (size_t *) &input->chat_length, 1);
    }

    if (input->certificate_description) {
        sc_format_asn1_entry(EstablishPACEChannelInput_data+3,
                (unsigned char *) input->certificate_description,
                (size_t *) &input->certificate_description_length, 1);
    }

    return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len);
}
Beispiel #27
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);
}
int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
				 const struct sc_pkcs15_object *obj,
				 u8 **buf, size_t *buflen)
{
	struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[2];
	struct sc_asn1_entry asn1_rsakey_attr[4], asn1_prk_rsa_attr[2];
	struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2],
			asn1_dsakey_value_attr[3],
			asn1_dsakey_i_p_attr[2];
	struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_prk_gostr3410_attr[2];
	struct sc_asn1_entry asn1_prkey[4];
	struct sc_asn1_pkcs15_object rsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
						       asn1_com_prkey_attr, asn1_prk_rsa_attr };
	struct sc_asn1_pkcs15_object dsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
						       asn1_com_prkey_attr, asn1_prk_dsa_attr };
	struct sc_asn1_pkcs15_object gostr3410_prkey_obj =  { (struct sc_pkcs15_object *) obj,
						       asn1_com_key_attr, asn1_com_prkey_attr,
						       asn1_prk_gostr3410_attr };
	struct sc_pkcs15_prkey_info *prkey =
                (struct sc_pkcs15_prkey_info *) obj->data;
	struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams;
	int r;
	size_t af_len, usage_len;

	sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey);

	sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr);
	sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr);
	sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr);
	sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr);
	sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr);
	sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr);
	sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr);
	sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr);

	sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr);
	sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);

	switch (obj->type) {
	case SC_PKCS15_TYPE_PRKEY_RSA:
		sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 1);
		sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 1);
		sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 1);
		break;
	case SC_PKCS15_TYPE_PRKEY_DSA:
		sc_format_asn1_entry(asn1_prkey + 1, &dsa_prkey_obj, NULL, 1);
		sc_format_asn1_entry(asn1_prk_dsa_attr + 0, asn1_dsakey_value_attr, NULL, 1);
		if (prkey->path.type != SC_PATH_TYPE_PATH_PROT) {
			/* indirect: just add the path */
			sc_format_asn1_entry(asn1_dsakey_value_attr + 0,
					&prkey->path, NULL, 1);
		} else {
			/* indirect-protected */
			sc_format_asn1_entry(asn1_dsakey_value_attr + 1,
					asn1_dsakey_i_p_attr, NULL, 1);
			sc_format_asn1_entry(asn1_dsakey_i_p_attr + 0,
					&prkey->path, NULL, 1);
		}
                break;
	case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
		sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 1);
		sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 1);
		sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &prkey->path, NULL, 1);
		if (prkey->params.len == sizeof(*keyinfo_gostparams))
		{
			keyinfo_gostparams = prkey->params.data;
			sc_format_asn1_entry(asn1_gostr3410key_attr + 1,
					&keyinfo_gostparams->gostr3410, NULL, 1);
			sc_format_asn1_entry(asn1_gostr3410key_attr + 2,
					&keyinfo_gostparams->gostr3411, NULL, 1);
			sc_format_asn1_entry(asn1_gostr3410key_attr + 3,
					&keyinfo_gostparams->gost28147, NULL, 1);
		}
		break;
	default:
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Invalid private key type: %X", obj->type);
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL);
		break;
	}
	sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1);
	usage_len = sizeof(prkey->usage);
	sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1);
	if (prkey->native == 0)
		sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1);
	if (prkey->access_flags) {
		af_len = sizeof(prkey->access_flags);
		sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1);
	}
	if (prkey->key_reference >= 0)
		sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 1);

	sc_format_asn1_entry(asn1_com_prkey_attr + 0, prkey->subject.value, &prkey->subject.len, prkey->subject.len != 0);

	r = sc_asn1_encode(ctx, asn1_prkey, buf, buflen);

	return r;
}
Beispiel #29
0
static int
parse_x509_cert(sc_context_t *ctx, struct sc_pkcs15_der *der, struct sc_pkcs15_cert *cert)
{
    int r;
    struct sc_algorithm_id sig_alg;
    struct sc_pkcs15_pubkey *pubkey = NULL;
    unsigned char *serial = NULL, *issuer = NULL, *subject = NULL, *buf =  der->value;
    size_t serial_len = 0, issuer_len = 0, subject_len = 0, data_len = 0, buflen = der->len;
    struct sc_asn1_entry asn1_version[] = {
        { "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, &cert->version, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_x509v3[] = {
        { "certificatePolicies",	SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
        { "subjectKeyIdentifier",	SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
        { "crlDistributionPoints",	SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, &cert->crl, &cert->crl_len },
        { "authorityKeyIdentifier",	SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
        { "keyUsage",			SC_ASN1_BOOLEAN, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_extensions[] = {
        { "x509v3",		SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_x509v3, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_tbscert[] = {
        { "version",		SC_ASN1_STRUCT,    SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_version, NULL },
        { "serialNumber",	SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, &serial, &serial_len },
        { "signature",		SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
        { "issuer",		SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &issuer, &issuer_len },
        { "validity",		SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
        { "subject",		SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &subject, &subject_len },
        /* Use a callback to get the algorithm, parameters and pubkey into sc_pkcs15_pubkey */
        { "subjectPublicKeyInfo",SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki,  &pubkey },
        { "extensions",		SC_ASN1_STRUCT,    SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_extensions, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_cert[] = {
        { "tbsCertificate",	SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert, NULL },
        { "signatureAlgorithm",	SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, &sig_alg, NULL },
        { "signatureValue",	SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_serial_number[] = {
        { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_subject[] = {
        { "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_issuer[] = {
        { "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };

    const u8 *obj;
    size_t objlen;

    memset(cert, 0, sizeof(*cert));
    obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &objlen);
    if (obj == NULL)
        LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found");

    data_len = objlen + (obj - buf);
    cert->data.value = malloc(data_len);
    if (!cert->data.value)
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
    memcpy(cert->data.value, buf, data_len);
    cert->data.len = data_len;

    r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL);
    LOG_TEST_RET(ctx, r, "ASN.1 parsing of certificate failed");

    cert->version++;

    if (!pubkey)
        LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert");
    cert->key = pubkey;

    sc_asn1_clear_algorithm_id(&sig_alg);

    if (serial && serial_len)   {
        sc_format_asn1_entry(asn1_serial_number + 0, serial, &serial_len, 1);
        r = sc_asn1_encode(ctx, asn1_serial_number, &cert->serial, &cert->serial_len);
        free(serial);
        LOG_TEST_RET(ctx, r, "ASN.1 encoding of serial failed");
    }

    if (subject && subject_len)   {
        sc_format_asn1_entry(asn1_subject + 0, subject, &subject_len, 1);
        r = sc_asn1_encode(ctx, asn1_subject, &cert->subject, &cert->subject_len);
        free(subject);
        LOG_TEST_RET(ctx, r, "ASN.1 encoding of subject");
    }

    if (issuer && issuer_len)   {
        sc_format_asn1_entry(asn1_issuer + 0, issuer, &issuer_len, 1);
        r = sc_asn1_encode(ctx, asn1_issuer, &cert->issuer, &cert->issuer_len);
        free(issuer);
        LOG_TEST_RET(ctx, r, "ASN.1 encoding of issuer");
    }

    return SC_SUCCESS;
}
int sc_pkcs15_encode_unusedspace(sc_context_t *ctx,
			 struct sc_pkcs15_card *p15card,
			 u8 **buf, size_t *buflen)
{
	sc_path_t dummy_path;
	static const struct sc_asn1_entry c_asn1_unusedspace[] = {
		{ "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	static const struct sc_asn1_entry c_asn1_unusedspace_values[] = {
		{ "path", SC_ASN1_PATH,	SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
		{ "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	struct sc_asn1_entry *asn1_unusedspace = NULL;
	struct sc_asn1_entry *asn1_values = NULL;
	int unusedspace_count = 0, r, c = 0;
	sc_pkcs15_unusedspace_t *unusedspace;

	sc_format_path("3F00", &dummy_path);
	dummy_path.index = dummy_path.count = 0;

	unusedspace = p15card->unusedspace_list;
	for ( ; unusedspace != NULL; unusedspace = unusedspace->next)
		unusedspace_count++;
	if (unusedspace_count == 0) {
		/* The standard says there has to be at least 1 entry,
		 * so we use a path with a length of 0 bytes */
		r = sc_pkcs15_add_unusedspace(p15card, &dummy_path, NULL);
		if (r)
			return r;
		unusedspace_count = 1;
	}

	asn1_unusedspace = (struct sc_asn1_entry *)
		malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count + 1));
	if (asn1_unusedspace == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}
	asn1_values = (struct sc_asn1_entry *)
		malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count * 3));
	if (asn1_values == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}

	for (unusedspace = p15card->unusedspace_list; unusedspace != NULL; unusedspace = unusedspace->next) {
		sc_copy_asn1_entry(c_asn1_unusedspace, asn1_unusedspace + c);
		sc_format_asn1_entry(asn1_unusedspace + c, asn1_values + 3*c, NULL, 1);
		sc_copy_asn1_entry(c_asn1_unusedspace_values, asn1_values + 3*c);
		sc_format_asn1_entry(asn1_values + 3*c, &unusedspace->path, NULL, 1);
		sc_format_asn1_entry(asn1_values + 3*c+1, &unusedspace->auth_id, NULL, unusedspace->auth_id.len);
		c++;
	}
	asn1_unusedspace[c].name = NULL;

	r = sc_asn1_encode(ctx, asn1_unusedspace, buf, buflen);

err:
	if (asn1_values != NULL)
		free(asn1_values);
	if (asn1_unusedspace != NULL)
		free(asn1_unusedspace);

	/* If we added the dummy entry, remove it now */
	if (unusedspace_count == 1 && sc_compare_path(&p15card->unusedspace_list->path, &dummy_path))
		sc_pkcs15_remove_unusedspace(p15card, p15card->unusedspace_list);

	return r;
}