Ejemplo n.º 1
0
/*
 * Object deletion.
 */
static int
cardos_delete_object(sc_profile_t *profile, struct sc_pkcs15_card *p15card,
		struct sc_pkcs15_object *obj, const struct sc_path *path)
{
	int r = SC_SUCCESS, stored_in_ef = 0, algorithm = 0;
	size_t keybits;
	sc_file_t *file = NULL;
	struct sc_pkcs15_prkey_info *key_info;
	struct sc_pkcs15_prkey_rsa key_obj;
	struct sc_context *ctx = p15card->card->ctx;
	uint8_t abignum[256];

	LOG_FUNC_CALLED(ctx);
	/*
	 * If we are deleting a private key, overwrite it so it can't be used.
	 */
	if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) {
		key_info = obj->data;
		keybits = key_info->modulus_length & ~7UL;
		init_key_object(&key_obj, abignum, keybits >> 3);
		r = cardos_key_algorithm(key_info->usage, keybits, &algorithm);
		LOG_TEST_RET(ctx, r, "cardos_key_algorithm failed");

		r = sc_select_file(p15card->card, &key_info->path, &file);
		LOG_TEST_RET(ctx, r, "Failed to store key: cannot select parent DF");

		r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
		sc_file_free(file);
		LOG_TEST_RET(ctx, r, "Failed to store key: UPDATE authentication failed");

		r = cardos_put_key(profile, p15card, algorithm, key_info, &key_obj);
		LOG_TEST_RET(ctx, r, "cardos_put_key failed");
	}
Ejemplo n.º 2
0
/*
 * Certificates with a related private key are stored in the fid range CE00 - CEFF. The
 * second byte in the fid matches the key id.
 * Certificates without a related private key (e.g. CA certificates) are stored in the fid range
 * CA00 - CAFF. The second byte is a free selected id.
 */
static int sc_hsm_emu_store_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
		struct sc_pkcs15_object *object,
		struct sc_pkcs15_der *data)

{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
	struct sc_pkcs15_object *prkey;
	sc_path_t path;
	u8 id[2];
	int r;

	r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, &cert_info->id , &prkey);

	if (r == SC_ERROR_OBJECT_NOT_FOUND) {
		r = sc_hsm_determine_free_id(p15card, CA_CERTIFICATE_PREFIX);
		LOG_TEST_RET(p15card->card->ctx, r, "Out of identifier to store certificate description");

		id[0] = CA_CERTIFICATE_PREFIX;
		id[1] = r;
	} else {
		LOG_TEST_RET(p15card->card->ctx, r, "Error locating matching private key");

		id[0] = EE_CERTIFICATE_PREFIX;
		id[1] = ((struct sc_pkcs15_prkey_info *)prkey->data)->key_reference;
	}

	sc_path_set(&path, SC_PATH_TYPE_FILE_ID, id, 2, 0, -1);
	cert_info->path = path;

	r = sc_hsm_update_ef(p15card, id[0], id[1], 1, data->value, data->len);
	return r;
}
Ejemplo n.º 3
0
int
sm_authentic_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
		unsigned char *init_data, size_t init_len, struct sc_remote_data *rdata,
		int release_sm)
{
	int rv = 0;

	LOG_FUNC_CALLED(ctx);
	if (!sm_info)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

	sc_log(ctx, "SM get APDUs: rdata:%p, init_len:%i", rdata, init_len);
	sc_log(ctx, "SM get APDUs: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));

	if (init_data)   {
		rv = sm_gp_external_authentication(ctx, sm_info, init_data, init_len, rdata, sm_oberthur_diversify_keyset);
		LOG_TEST_RET(ctx, rv, "SM get APDUs: cannot authenticate card");
	}

	switch (sm_info->cmd)  {
	case SM_CMD_APDU_TRANSMIT:
		rv = sm_authentic_encode_apdu(ctx, sm_info);
		LOG_TEST_RET(ctx, rv, "SM get APDUs: cannot encode APDU");
		break;
	case SM_CMD_INITIALIZE:
		break;
	default:
		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported SM command");
	}

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 4
0
int
sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
		const struct sc_pkcs15_data_info *info,
		struct sc_pkcs15_data **data_object_out)
{
        struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_data *data_object;
	struct sc_pkcs15_der der;
	int r;

	LOG_FUNC_CALLED(ctx);
	if (!info || !data_object_out)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

	if (!info->data.value)   {
		r = sc_pkcs15_read_file(p15card, &info->path, &info->data.value, &info->data.len);
		LOG_TEST_RET(ctx, r, "Cannot get DATA object data");
	}

	sc_der_copy(&der, &info->data);
	data_object = calloc(sizeof(struct sc_pkcs15_data), 1);
	if (!data_object && !der.value)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for data object");

	data_object->data = der.value;
	data_object->data_len = der.len;
	*data_object_out = data_object;

	LOG_FUNC_RETURN(ctx,SC_SUCCESS);
}
Ejemplo n.º 5
0
/*
 * SELECT an applet on the smartcard. (Not in the emulated filesystem.)
 * The response will be written to resp.
 *
 * @param[in]     card
 * @param[in]     aid      The applet ID.
 * @param[in]     aid_len  The legth of aid.
 * @param[out]    resp     The response of the applet upon selection.
 * @param[in,out] resp_len In: The buffer size of resp. Out: The length of the response.
 *
 * @return SC_SUCCESS: The applet is present and could be selected.
 *         any other:  Transmit failure or the card returned an error.
 *                     The card will return an error when the applet is
 *                     not present.
 */
static int
isoApplet_select_applet(sc_card_t *card, const u8 *aid, const size_t aid_len, u8 *resp, size_t *resp_len)
{
	int rv;
	sc_context_t *ctx = card->ctx;
	sc_apdu_t apdu;

	LOG_FUNC_CALLED(card->ctx);

	if(aid_len > SC_MAX_APDU_BUFFER_SIZE)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xa4, 0x04, 0x00);
	apdu.lc = aid_len;
	apdu.data = aid;
	apdu.datalen = aid_len;
	apdu.resp = resp;
	apdu.resplen = *resp_len;
	apdu.le = 0;

	rv = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(ctx, rv, "APDU transmit faiure.");

	rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, rv, "Card returned error");

	*resp_len = apdu.resplen;
	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
Ejemplo n.º 6
0
static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2],
		u8 *efbin, size_t *len)
{
	sc_path_t path;
	int r;

	sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0);
	/* look this up with our AID */
	path.aid = sc_hsm_aid;
	/* we don't have a pre-known size of the file */
	path.count = -1;
	if (!p15card->opts.use_file_cache
			|| SC_SUCCESS != sc_pkcs15_read_cached_file(p15card, &path, &efbin, len)) {
		/* avoid re-selection of SC-HSM */
		path.aid.len = 0;
		r = sc_select_file(p15card->card, &path, NULL);
		LOG_TEST_RET(p15card->card->ctx, r, "Could not select EF");

		r = sc_read_binary(p15card->card, 0, efbin, *len, 0);
		LOG_TEST_RET(p15card->card->ctx, r, "Could not read EF");

		*len = r;

		if (p15card->opts.use_file_cache) {
			/* save this with our AID */
			path.aid = sc_hsm_aid;
			sc_pkcs15_cache_file(p15card, &path, efbin, *len);
		}
	}

	return SC_SUCCESS;
}
Ejemplo n.º 7
0
static int
sm_gp_encrypt_command_data(struct sc_context *ctx, unsigned char *session_key,
		const unsigned char *in, size_t in_len, unsigned char **out, size_t *out_len)
{
	unsigned char *data = NULL;
	int rv, len;

	if (!out || !out_len)
		LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "SM GP encrypt command data error");

	sc_debug(ctx, SC_LOG_DEBUG_SM,
	       "SM GP encrypt command data(len:%"SC_FORMAT_LEN_SIZE_T"u,%p)",
	       in_len, in);
	if (in==NULL || in_len==0)   {
		*out = NULL;
		*out_len = 0;
		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
	}

	len = in_len + 8;
	len -= (len%8);

	data = calloc(1, len);
	if (!data)
		LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);

	*data = in_len;
	memcpy(data + 1, in, in_len);

	rv = sm_encrypt_des_cbc3(ctx, session_key, data, in_len + 1, out, out_len, 1);
	free(data);
	LOG_TEST_RET(ctx, rv, "SM GP encrypt command data: encryption error");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Ejemplo n.º 8
0
int
iasecc_sm_sdo_update(struct sc_card *card, unsigned se_num, struct iasecc_sdo_update *update)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_sdo_update() SE#%i, SDO(class:0x%X,ref:%i)", se_num, update->sdo_class, update->sdo_ref);

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_SDO_UPDATE);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM INITIALIZE failed");

	sc_log(ctx, "current DF '%s'", sc_print_path(&sm_info->current_path_df));

	sm_info->cmd_data = update;

	sc_remote_data_init(&rdata);
	rv = iasecc_sm_cmd(card, &rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM 'SDO UPDATE' failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 9
0
int
iasecc_sm_pin_reset(struct sc_card *card, unsigned se_num, struct sc_pin_cmd_data *data)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_pin_reset() SE#%i, PIN(ref:%i,len:%i)", se_num, data->pin_reference, data->pin2.len);

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_PIN_RESET);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM INITIALIZE failed");

	sm_info->cmd_data = data;

	sc_remote_data_init(&rdata);
	rv = iasecc_sm_cmd(card, &rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM 'PIN RESET' failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 10
0
static int
iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_chv *chv)
{
	struct sc_context *ctx = card->ctx;
	size_t offs = 0;
	int rv;

	LOG_FUNC_CALLED(ctx);
	while(offs < data_len)   {
		struct iasecc_extended_tlv tlv;

		rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
		LOG_TEST_RET(ctx, rv, "iasecc_parse_chv() get and parse TLV error");

		sc_log(ctx, "iasecc_parse_chv() get and parse TLV returned %i; tag %X; size %i",  rv, tlv.tag, tlv.size);

		if (tlv.tag == IASECC_SDO_CHV_TAG_SIZE_MAX)
			chv->size_max = tlv;
		else if (tlv.tag == IASECC_SDO_CHV_TAG_SIZE_MIN)
			chv->size_min = tlv;
		else if (tlv.tag == IASECC_SDO_CHV_TAG_VALUE)
			chv->value = tlv;
		else
			LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "parse error: non CHV SDO tag");

		offs += rv;
	}

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Ejemplo n.º 11
0
int
iasecc_sm_pin_verify(struct sc_card *card, unsigned se_num, struct sc_pin_cmd_data *data, int *tries_left)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_pin_verify() SE#%i, PIN(ref:%i,len:%i)", se_num, data->pin_reference, data->pin1.len);

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_PIN_VERIFY);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM INITIALIZE failed");

	sm_info->cmd_data = data;

	sc_remote_data_init(&rdata);
	rv = iasecc_sm_cmd(card, &rdata);
	if (rv && rdata.length && tries_left)
		if (rdata.data->apdu.sw1 == 0x63 && (rdata.data->apdu.sw2 & 0xF0) == 0xC0)
			*tries_left = rdata.data->apdu.sw2 & 0x0F;

	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM 'PIN VERIFY' failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 12
0
static int
iso7816_update_binary(struct sc_card *card,
		unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
{
	struct sc_apdu apdu;
	int r;

	if (idx > 0x7fff) {
		sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
		return SC_ERROR_OFFSET_TOO_LARGE;
	}

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD6, (idx >> 8) & 0x7F, idx & 0xFF);
	apdu.lc = count;
	apdu.datalen = count;
	apdu.data = buf;

	fixup_transceive_length(card, &apdu);
	r = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, r, "Card returned error");

	LOG_FUNC_RETURN(card->ctx, count);
}
Ejemplo n.º 13
0
/** Sends a single APDU to the card reader and calls GET RESPONSE to get the return data if necessary.
 *  @param  card  sc_card_t object for the smartcard
 *  @param  apdu  APDU to be sent
 *  @return SC_SUCCESS on success and an error value otherwise
 */
static int
sc_transmit(sc_card_t *card, sc_apdu_t *apdu)
{
	struct sc_context *ctx  = card->ctx;
	size_t       olen  = apdu->resplen;
	int          r;

	LOG_FUNC_CALLED(ctx);

	r = sc_single_transmit(card, apdu);
	LOG_TEST_RET(ctx, r, "transmit APDU failed");

	/* ok, the APDU was successfully transmitted. Now we have two special cases:
	 * 1. the card returned 0x6Cxx: in this case APDU will be re-trasmitted with Le set to SW2
	 * (possible only if response buffer size is larger than new Le = SW2)
	 */
	if (apdu->sw1 == 0x6C && (apdu->flags & SC_APDU_FLAGS_NO_RETRY_WL) == 0)
		r = sc_set_le_and_transmit(card, apdu, olen);
	LOG_TEST_RET(ctx, r, "cannot re-transmit APDU ");

	/* 2. the card returned 0x61xx: more data can be read from the card
	 *    using the GET RESPONSE command (mostly used in the T0 protocol).
	 *    Unless the SC_APDU_FLAGS_NO_GET_RESP is set we try to read as
	 *    much data as possible using GET RESPONSE.
	 */
	if (apdu->sw1 == 0x61 && (apdu->flags & SC_APDU_FLAGS_NO_GET_RESP) == 0)
		r = sc_get_response(card, apdu, olen);
	LOG_TEST_RET(ctx, r, "cannot get all data with 'GET RESPONSE'");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Ejemplo n.º 14
0
static int
sc_awp_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
{
	struct sc_context *ctx = p15card->card->ctx;
	unsigned char *buf = NULL;
	size_t buf_len;
	int rv;

	LOG_FUNC_CALLED(ctx);
	if (df->type != SC_PKCS15_PRKDF && df->type != SC_PKCS15_DODF)
		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);

	if (df->enumerated)
		LOG_FUNC_RETURN(ctx, SC_SUCCESS);

	rv = sc_oberthur_read_file(p15card, AWP_OBJECTS_LIST_PRV, &buf, &buf_len, 1);
	LOG_TEST_RET(ctx, rv, "Parse DF: read pribate objects info failed");

	rv = sc_oberthur_parse_privateinfo(p15card, buf, buf_len, 0);

	if (buf)
		free(buf);

	if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)
		LOG_FUNC_RETURN(ctx, SC_SUCCESS);

	LOG_TEST_RET(ctx, rv, "Parse DF: private info parse error");
	df->enumerated = 1;

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 15
0
static int esteid_get_pin_remaining_tries(sc_card_t *card, int pin_reference) {
	unsigned char get_pin_info[] = {0x4D, 0x08, 0x70, 0x06, 0xBF, 0x81, 0xFF, 0x02, 0xA0, 0x80};

	struct sc_apdu apdu;
	unsigned char apdu_resp[SC_MAX_APDU_RESP_SIZE];
	LOG_FUNC_CALLED(card->ctx);

	// We don't get the file information here, so we need to be ugly
	if (pin_reference == PIN1_REF || pin_reference == PUK_REF) {
		LOG_TEST_RET(card->ctx, esteid_select(card, 0x00, 0x3F, 0x00), "Cannot select MF");
	} else if (pin_reference == PIN2_REF) {
		LOG_TEST_RET(card->ctx, esteid_select_file(card, &adf2, NULL), "Cannot select QSCD AID");
	} else {
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
	}

	get_pin_info[6] = pin_reference & 0x0F; // mask out local/global
	sc_format_apdu_ex(card, &apdu, 0xCB, 0x3F, 0xFF, get_pin_info, sizeof(get_pin_info), apdu_resp, sizeof(apdu_resp));
	SC_TRANSMIT_TEST_RET(card, apdu, "GET DATA(pin info) failed");
	if (apdu.resplen < 32) {
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
	}

	// XXX: sc_asn1_find_tag with the following payload (to get to tag 0x9B):
	// https://lapo.it/asn1js/#cB6_gQEaoBiaAQObAQOhEIwG8wAAc0MAnAbzAABzQwA
	return (int)apdu_resp[13];
}
Ejemplo n.º 16
0
/**
 * Initialize
 *
 * Read keyset from the OpenSC configuration file,
 * get and return the APDU(s) to initialize SM session.
 */
int
initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *out)
{
	int rv = SC_ERROR_NOT_SUPPORTED;

	LOG_FUNC_CALLED(ctx);
	if (!sm_info)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

	sc_log(ctx, "Current AID: %s", sc_dump_hex(sm_info->current_aid.value, sm_info->current_aid.len));
	switch (sm_info->sm_type)   {
	case SM_TYPE_GP_SCP01:
		rv = sm_gp_config_get_keyset(ctx, sm_info);
		LOG_TEST_RET(ctx, rv, "SM gp configuration error");

		rv = sm_gp_initialize(ctx, sm_info, out);
		LOG_TEST_RET(ctx, rv, "SM gp initializing error");
		break;
	case SM_TYPE_CWA14890:
		rv = sm_cwa_config_get_keyset(ctx, sm_info);
		LOG_TEST_RET(ctx, rv, "SM iasecc configuration error");

		rv = sm_cwa_initialize(ctx, sm_info, out);
		LOG_TEST_RET(ctx, rv, "SM iasecc initializing error");
		break;
	default:
		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported SM type");
	};

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 17
0
/**
 * Get APDU(s)
 *
 * Get securized APDU(s) corresponding
 * to the asked command.
 */
int
get_apdus(struct sc_context *ctx, struct sm_info *sm_info, unsigned char *init_data, size_t init_len,
		struct sc_remote_data *out)
{
	int rv = SC_ERROR_NOT_SUPPORTED;

	LOG_FUNC_CALLED(ctx);
	if (!sm_info)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

	sc_log(ctx, "SM get APDUs: out:%p", out);
	sc_log(ctx, "SM get APDUs: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));

	if (sm_info->card_type == SC_CARD_TYPE_OBERTHUR_AUTHENTIC_3_2)   {
		rv = sm_authentic_get_apdus(ctx, sm_info, init_data, init_len, out, 1);
		LOG_TEST_RET(ctx, rv, "SM get APDUs: failed for AuthentIC");
	}
	else if (sm_info->card_type/10*10 == SC_CARD_TYPE_IASECC_BASE)   {
		rv = sm_iasecc_get_apdus(ctx, sm_info, init_data, init_len, out, 1);
		LOG_TEST_RET(ctx, rv, "SM get APDUs: failed for IAS/ECC");
	}
	else   {
		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "SM get APDUs: unsupported card type");
	}

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 18
0
static int
iasecc_sm_transmit_apdus(struct sc_card *card, struct sc_remote_data *rdata,
		unsigned char *out, size_t *out_len)
{
	struct sc_context *ctx = card->ctx;
	struct sc_remote_apdu *rapdu = rdata->data;
	int rv = SC_SUCCESS, offs = 0;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_transmit_apdus() rdata-length %i", rdata->length);

	while (rapdu)   {
		sc_log(ctx, "iasecc_sm_transmit_apdus() rAPDU flags 0x%lX", rapdu->apdu.flags);
		rv = sc_transmit_apdu(card, &rapdu->apdu);
		LOG_TEST_RET(ctx, rv, "iasecc_sm_transmit_apdus() failed to execute r-APDU");
		rv = sc_check_sw(card, rapdu->apdu.sw1, rapdu->apdu.sw2);
		if (rv < 0 && !(rapdu->flags & SC_REMOTE_APDU_FLAG_NOT_FATAL))
			LOG_TEST_RET(ctx, rv, "iasecc_sm_transmit_apdus() fatal error %i");

		if (out && out_len && (rapdu->flags & SC_REMOTE_APDU_FLAG_RETURN_ANSWER))   {
			int len = rapdu->apdu.resplen > (*out_len - offs) ? (*out_len - offs) : rapdu->apdu.resplen;

			memcpy(out + offs, rapdu->apdu.resp, len);
			offs += len;
			/* TODO: decode and gather data answers */
		}

		rapdu = rapdu->next;
	}

	if (out_len)
		*out_len = offs;

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 19
0
static int
iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo)
{
	struct sc_context *ctx = card->ctx;
	size_t offs = 0;
	int rv;

	LOG_FUNC_CALLED(ctx);
	while(offs < data_len)   {
		struct iasecc_extended_tlv tlv;

		rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
		LOG_TEST_RET(ctx, rv, "iasecc_parse_get_tlv() get and parse TLV error");

		sc_log(ctx, "iasecc_parse_docp() parse_get_tlv retuned %i; tag %X; size %i",  rv, tlv.tag, tlv.size);

		if (tlv.tag == IASECC_DOCP_TAG_ACLS)   {
			int _rv = iasecc_parse_docp(card, tlv.value, tlv.size, sdo);
			free(tlv.value);
			LOG_TEST_RET(ctx, _rv, "parse error: cannot parse DOCP");
		}
		else if (tlv.tag == IASECC_DOCP_TAG_ACLS_CONTACT)   {
			sdo->docp.acls_contact = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_ACLS_CONTACTLESS)   {
			sdo->docp.acls_contactless = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_SIZE)   {
			sdo->docp.size = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_NAME)   {
			sdo->docp.name = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_ISSUER_DATA)   {
			sdo->docp.issuer_data = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_NON_REPUDATION)   {
			sdo->docp.non_repudiation = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_USAGE_REMAINING)   {
			sdo->docp.usage_remaining = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_TRIES_MAXIMUM)   {
			sdo->docp.tries_maximum = tlv;
		}
		else if (tlv.tag == IASECC_DOCP_TAG_TRIES_REMAINING)   {
			sdo->docp.tries_remaining = tlv;
		}
		else   {
			LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "iasecc_parse_get_tlv() parse error: non DOCP tag");
		}

		offs += rv;
	}

	rv = iasecc_parse_acls(card, &sdo->docp, 0);
	LOG_TEST_RET(ctx, rv, "Cannot parse ACLs in DOCP");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Ejemplo n.º 20
0
static int
iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_keyset *keyset)
{
	struct sc_context *ctx = card->ctx;
	size_t offs = 0;
	int rv;

	LOG_FUNC_CALLED(ctx);
	while(offs < data_len)   {
		struct iasecc_extended_tlv tlv;

		rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
		LOG_TEST_RET(ctx, rv, "iasecc_parse_keyset() get and parse TLV error");

		sc_log(ctx, "iasecc_parse_prvkey() get and parse TLV returned %i; tag %X; size %i",  rv, tlv.tag, tlv.size);

		if (tlv.tag == IASECC_SDO_KEYSET_TAG_COMPULSORY)
			keyset->compulsory = tlv;
		else
			LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "parse error: non KeySet SDO tag");

		offs += rv;
	}

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Ejemplo n.º 21
0
int
iasecc_sm_create_file(struct sc_card *card, unsigned se_num, unsigned char *fcp, size_t fcp_len)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	struct iasecc_sm_cmd_create_file cmd_data;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_create_file() SE#%i, fcp(%i) '%s'", se_num, fcp_len, sc_dump_hex(fcp, fcp_len));

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_CREATE);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM INITIALIZE failed");

	cmd_data.data = fcp;
	cmd_data.size = fcp_len;
	sm_info->cmd_data = &cmd_data;

	sc_remote_data_init(&rdata);
	rv= iasecc_sm_cmd(card, &rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM 'UPDATE BINARY' failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 22
0
static int ias_compute_signature(sc_card_t *card, const u8 *data,
		size_t data_len, u8 *out, size_t outlen)
{
	sc_apdu_t	apdu;
	size_t		len;
	/*
	** XXX: Ensure sufficient space exists for the card's response
	** as the caller's buffer size may not be sufficient
	*/
	u8		rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_context_t	*ctx = card->ctx;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	if (data_len > 64) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "error: input data too long: %lu bytes\n", data_len);
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	
	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x02, 0x00);
	apdu.data = (u8 *) data;
	apdu.lc = data_len;
	apdu.datalen = data_len;
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le = 256;

	LOG_TEST_RET(card->ctx, sc_transmit_apdu(card, &apdu), "APDU transmit failed");
	LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "INTERNAL AUTHENTICATE failed");

	len = apdu.resplen > outlen ? outlen : apdu.resplen;
	memcpy(out, apdu.resp, len);
	
	LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
Ejemplo n.º 23
0
int
iasecc_sm_delete_file(struct sc_card *card, unsigned se_num, unsigned int file_id)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "SM delete file: SE#:%X, file-id:%X", se_num, file_id);

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_DELETE);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM INITIALIZE failed");

	sm_info->cmd_data = (void *)file_id;

	sc_remote_data_init(&rdata);
	rv = iasecc_sm_cmd(card, &rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM 'FILE DELETE' failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 24
0
/*
 * Add a unrelated certificate object and description in PKCS#15 format to the framework
 */
static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) {

	sc_card_t *card = p15card->card;
	sc_pkcs15_cert_info_t *cert_info;
	sc_pkcs15_object_t obj;
	u8 fid[2];
	u8 efbin[512];
	const u8 *ptr;
	size_t len;
	int r;

	fid[0] = CD_PREFIX;
	fid[1] = id;

	/* Try to select a related EF containing the PKCS#15 description of the data */
	len = sizeof efbin;
	r = read_file(p15card, fid, efbin, &len);
	LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD");

	ptr = efbin;

	memset(&obj, 0, sizeof(obj));
	r = sc_pkcs15_decode_cdf_entry(p15card, &obj, &ptr, &len);
	LOG_TEST_RET(card->ctx, r, "Could not decode EF.CD");

	cert_info = (sc_pkcs15_cert_info_t *)obj.data;

	r = sc_pkcs15emu_add_x509_cert(p15card, &obj, cert_info);

	LOG_TEST_RET(card->ctx, r, "Could not add data object to framework");

	return SC_SUCCESS;
}
Ejemplo n.º 25
0
/*
 * Erase the card.
 */
static int
myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) {
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_cardctl_myeid_data_obj data_obj;
	struct sc_file *mf = NULL;
	unsigned char data[8];
	int r;

	LOG_FUNC_CALLED(ctx);

	r = myeid_get_init_applet_data(profile, p15card, data, sizeof (data));
	LOG_TEST_RET(ctx, r, "Get init applet date error");

	/* Select parent DF and verify PINs/key as necessary */
	r = sc_select_file(p15card->card, sc_get_mf_path(), &mf);
	LOG_TEST_RET(ctx, r, "Cannot select MF");

	/* ACLs are not actives if file is not in the operational state */
	if (mf->status == SC_FILE_STATUS_ACTIVATED)
		r = sc_pkcs15init_authenticate(profile, p15card, mf, SC_AC_OP_DELETE);
	LOG_TEST_RET(ctx, r, "'DELETE' authentication failed on MF");

	data_obj.P1 = 0x01;
	data_obj.P2 = 0xE0;
	data_obj.Data = data;
	data_obj.DataLen = sizeof (data);

	r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj);

	LOG_FUNC_RETURN(p15card->card->ctx, r);
}
Ejemplo n.º 26
0
static int
jpki_compute_signature(sc_card_t * card,
		const u8 * data, size_t datalen, u8 * out, size_t outlen)
{
	int rc;
	sc_apdu_t apdu;
	unsigned char resp[SC_MAX_APDU_BUFFER_SIZE];

	LOG_FUNC_CALLED(card->ctx);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, 0x80);
	apdu.cla = 0x80;
	apdu.data = data;
	apdu.datalen = datalen;
	apdu.lc = datalen;
	apdu.resp = resp;
	apdu.resplen = sizeof(resp);
	apdu.le = 0;
	rc = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
	rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, rc, "SW Check failed");
	if (apdu.resplen > outlen) {
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
	}
	memcpy(out, resp, apdu.resplen);
	LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
Ejemplo n.º 27
0
static int
sc_set_le_and_transmit(struct sc_card *card, struct sc_apdu *apdu, size_t olen)
{
	struct sc_context *ctx  = card->ctx;
	size_t nlen = apdu->sw2 ? (size_t)apdu->sw2 : 256;
	int rv;

	LOG_FUNC_CALLED(ctx);
	/* we cannot re-transmit the APDU with the demanded Le value
	 * as the buffer is too small => error */
	if (olen < nlen)
		LOG_TEST_RET(ctx, SC_ERROR_WRONG_LENGTH, "wrong length: required length exceeds resplen");

	/* don't try again if it doesn't work this time */
	apdu->flags  |= SC_APDU_FLAGS_NO_GET_RESP;
	/* set the new expected length */
	apdu->resplen = olen;
	apdu->le      = nlen;
	/* Belpic V1 applets have a problem: if the card sends a 6C XX (only XX bytes available), 
	 * and we resend the command too soon (i.e. the reader is too fast), the card doesn't respond. 
	 * So we build in a delay. */
	if (card->type == SC_CARD_TYPE_BELPIC_EID)
		msleep(40);

	/* re-transmit the APDU with new Le length */
	rv = sc_single_transmit(card, apdu);
	LOG_TEST_RET(ctx, rv, "cannot re-transmit APDU");

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 28
0
int
iasecc_sm_rsa_update(struct sc_card *card, unsigned se_num, struct iasecc_sdo_rsa_update *udata)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sc_remote_data rdata;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "SM update RSA: SE#: 0x%X, SDO(class:0x%X:ref:%X)", se_num,
			udata->sdo_prv_key->sdo_class, udata->sdo_prv_key->sdo_ref);

	rv = iasecc_sm_initialize(card, se_num, SM_CMD_RSA_UPDATE);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM initialize failed");

	sm_info->cmd_data = udata;

	sc_remote_data_init(&rdata);
	rv = iasecc_sm_cmd(card, &rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM cmd failed");

	rv = sm_release (card, &rdata, NULL, 0);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM release failed");

	rdata.free(&rdata);
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 29
0
static int
sm_iasecc_get_apdu_delete_file(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
	unsigned int file_id = (unsigned int)sm_info->cmd_data;
	struct sc_remote_apdu *rapdu = NULL;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "SM get 'DELETE FILE' APDU: file-id %04X", file_id);

	if (!file_id)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

        if (!rdata || !rdata->alloc)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

 	rv = rdata->alloc(rdata, &rapdu);
	LOG_TEST_RET(ctx, rv, "SM get 'DELETE FILE' APDUs: cannot allocate remote APDU");

	rapdu->apdu.cse = SC_APDU_CASE_1;
	rapdu->apdu.cla = 0x00;
	rapdu->apdu.ins = 0xE4;
	rapdu->apdu.p1 = 0x00;
	rapdu->apdu.p2 = 0x00;

	/** 99 02 SW   8E 08 MAC **/
	rapdu->apdu.le = 0x0E;

	rv = sm_cwa_securize_apdu(ctx, sm_info, rapdu);
	LOG_TEST_RET(ctx, rv, "SM get 'DELETE FILE' APDUs: securize APDU error");

	rapdu->flags |= SC_REMOTE_APDU_FLAG_RETURN_ANSWER;

	LOG_FUNC_RETURN(ctx, rv);
}
Ejemplo n.º 30
0
/*
 * Store a private key
 */
static int
myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
		struct sc_pkcs15_object *object) {
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_card *card = p15card->card;
	struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
	struct sc_file *file = NULL;
	int keybits = key_info->modulus_length, r;

	LOG_FUNC_CALLED(card->ctx);

	/* Check that the card supports the requested modulus length */
	switch (object->type) {
		case SC_PKCS15_TYPE_PRKEY_RSA:
			if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
				LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
					"Unsupported RSA key size");
			break;
		case SC_PKCS15_TYPE_PRKEY_EC:
			if (sc_card_find_ec_alg(p15card->card, keybits) == NULL)
				LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
					"Unsupported EC key size");
			break;
		default:
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
					"Unsupported key type");
			break;
	}

	sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id));

	/* Get the private key file */
	r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file);
	LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file");

	sc_log(ctx, "Key file size %d", keybits);
	file->size = keybits;

	if (object->type == SC_PKCS15_TYPE_PRKEY_RSA)
		file->ef_structure = SC_CARDCTL_MYEID_KEY_RSA;
	else if (object->type == SC_PKCS15_TYPE_PRKEY_EC)
		file->ef_structure = SC_CARDCTL_MYEID_KEY_EC;

	memcpy(&key_info->path.value, &file->path.value, file->path.len);
	key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF;

	sc_log(ctx, "Path of MyEID private key file to create %s",
			sc_print_path(&file->path));

	/* Now create the key file */
	r = sc_pkcs15init_create_file(profile, p15card, file);
	sc_file_free(file);
	LOG_TEST_RET(ctx, r, "Cannot create MyEID private key file");

	LOG_FUNC_RETURN(ctx, r);
}