Commit message: fixed out of bounds writes

Thanks to Eric Sesterhenn from X41 D-SEC GmbH
for reporting the problems.
CVE: CVE-2018-16420
CWE: CWE-415
Vulnerability description: Several buffer overflows when handling responses from an ePass 2003 Card in decrypt_response in libopensc/card-epass2003.c in OpenSC before 0.19.0-rc1 could be used by attackers able to supply crafted smartcards to cause a denial of service (application crash) or possibly have unspecified other impact.

Project: OpenSC
File: card-muscle.c

static void muscle_parse_acls(const sc_file_t* file, unsigned short* read_perm, unsigned short* write_perm, unsigned short* delete_perm)
{
	assert(read_perm && write_perm && delete_perm);
	*read_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_READ));
	*write_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_UPDATE));
	*delete_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_DELETE));
}

Project: OpenSC
File: sc.c

void sc_file_clear_acl_entries(sc_file_t *file, unsigned int operation)
{
	sc_acl_entry_t *e;

	if (file == NULL || operation >= SC_MAX_AC_OPS) {
		return;
	}

	e = file->acl[operation];
	if (e == (sc_acl_entry_t *) 1 ||
	    e == (sc_acl_entry_t *) 2 ||
	    e == (sc_acl_entry_t *) 3) {
		file->acl[operation] = NULL;
		return;
	}

	while (e != NULL) {
		sc_acl_entry_t *tmp = e->next;
		free(e);
		e = tmp;
	}
	file->acl[operation] = NULL;
}

Project: OpenSC
File: pkcs15-sc-hsm.c

int sc_pkcs15emu_sc_hsm_get_curve_oid(sc_cvc_t *cvc, const struct sc_lv_data **oid)
{
	int i;

	for (i = 0; curves[i].oid.value; i++) {
		if ((curves[i].prime.len == cvc->primeOrModuluslen) && !memcmp(curves[i].prime.value, cvc->primeOrModulus, cvc->primeOrModuluslen)) {
			*oid = &curves[i].oid;
			return SC_SUCCESS;
		}
	}
	return SC_ERROR_INVALID_DATA;
}

Project: OpenSC
File: card-cac.c

static struct sc_card_driver * sc_get_driver(void)
{
	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();

	cac_ops = *iso_drv->ops;
	cac_ops.match_card = cac_match_card;
	cac_ops.init = cac_init;
	cac_ops.finish = cac_finish;

	cac_ops.select_file =  cac_select_file; /* need to record object type */
	cac_ops.get_challenge = cac_get_challenge;
	cac_ops.read_binary = cac_read_binary;
	cac_ops.write_binary = cac_write_binary;
	cac_ops.set_security_env = cac_set_security_env;
	cac_ops.restore_security_env = cac_restore_security_env;
	cac_ops.compute_signature = cac_compute_signature;
	cac_ops.decipher =  cac_decipher;
	cac_ops.card_ctl = cac_card_ctl;
	cac_ops.pin_cmd = cac_pin_cmd;

	return &cac_drv;
}

Project: OpenSC
File: card-epass2003.c

openssl_dig(const EVP_MD * digest, const unsigned char *input, size_t length,
		unsigned char *output)
{
	int r = 0;
	EVP_MD_CTX *ctx = NULL;
	unsigned outl = 0;

	ctx = EVP_MD_CTX_create();
	if (ctx == NULL) {
	    r = SC_ERROR_OUT_OF_MEMORY;
	    goto err;
	}
	    
	EVP_MD_CTX_init(ctx);
	EVP_DigestInit_ex(ctx, digest, NULL);
	if (!EVP_DigestUpdate(ctx, input, length)) {
		r = SC_ERROR_INTERNAL;
		goto err;
	}

	if (!EVP_DigestFinal_ex(ctx, output, &outl)) {
		r = SC_ERROR_INTERNAL;
		goto err;
	}
	r = SC_SUCCESS;
err:
	if (ctx)
		EVP_MD_CTX_destroy(ctx);

	return r;
}

Project: OpenSC
File: cryptoflex-tool.c

static char *getpin(const char *prompt)
{
	char *buf, pass[20];
	int i;

	printf("%s", prompt);
	fflush(stdout);
	if (fgets(pass, 20, stdin) == NULL)
		return NULL;
	for (i = 0; i < 20; i++)
		if (pass[i] == '\n')
			pass[i] = 0;
	if (strlen(pass) == 0)
		return NULL;
	buf = malloc(8);
	if (buf == NULL)
		return NULL;
	if (strlen(pass) > 8) {
		fprintf(stderr, "PIN code too long.\n");
		free(buf);
		return NULL;
	}
	memset(buf, 0, 8);
	strlcpy(buf, pass, 8);
	return buf;
}

Project: OpenSC
File: card-epass2003.c

gen_init_key(struct sc_card *card, unsigned char *key_enc, unsigned char *key_mac,
		unsigned char *result, unsigned char key_type)
{
	int r;
	struct sc_apdu apdu;
	unsigned char data[256] = { 0 };
	unsigned char tmp_sm;
	unsigned long blocksize = 0;
	unsigned char cryptogram[256] = { 0 };	/* host cryptogram */
	unsigned char iv[16] = { 0 };
	epass2003_exdata *exdata = NULL;
	
	if (!card->drv_data) 
		return SC_ERROR_INVALID_ARGUMENTS;
	
	exdata = (epass2003_exdata *)card->drv_data;

	LOG_FUNC_CALLED(card->ctx);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x50, 0x00, 0x00);
	apdu.cla = 0x80;
	apdu.lc = apdu.datalen = sizeof(g_random);
	apdu.data = g_random;	/* host random */
	apdu.le = apdu.resplen = 28;
	apdu.resp = result;	/* card random is result[12~19] */

	tmp_sm = exdata->sm;
	exdata->sm = SM_PLAIN;
	r = epass2003_transmit_apdu(card, &apdu);
	exdata->sm = tmp_sm;
	LOG_TEST_RET(card->ctx, r, "APDU gen_init_key failed");

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, r, "gen_init_key failed");

	/* Step 1 - Generate Derivation data */
	memcpy(data, &result[16], 4);
	memcpy(&data[4], g_random, 4);
	memcpy(&data[8], &result[12], 4);
	memcpy(&data[12], &g_random[4], 4);

	/* Step 2,3 - Create S-ENC/S-MAC Session Key */
	if (KEY_TYPE_AES == key_type) {
		aes128_encrypt_ecb(key_enc, 16, data, 16, exdata->sk_enc);
		aes128_encrypt_ecb(key_mac, 16, data, 16, exdata->sk_mac);
	}
	else {
		des3_encrypt_ecb(key_enc, 16, data, 16, exdata->sk_enc);
		des3_encrypt_ecb(key_mac, 16, data, 16, exdata->sk_mac);
	}

	memcpy(data, g_random, 8);
	memcpy(&data[8], &result[12], 8);
	data[16] = 0x80;
	blocksize = (key_type == KEY_TYPE_AES ? 16 : 8);
	memset(&data[17], 0x00, blocksize - 1);

	/* calculate host cryptogram */
	if (KEY_TYPE_AES == key_type)
		aes128_encrypt_cbc(exdata->sk_enc, 16, iv, data, 16 + blocksize, cryptogram);
	else
		des3_encrypt_cbc(exdata->sk_enc, 16, iv, data, 16 + blocksize, cryptogram);

	/* verify card cryptogram */
	if (0 != memcmp(&cryptogram[16], &result[20], 8))
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);

	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

Project: OpenSC
File: pkcs15-gemsafeV1.c

static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
{
	int		    r;
	unsigned int    i;
	struct sc_path  path;
	struct sc_file *file = NULL;
	struct sc_card *card = p15card->card;
	struct sc_apdu  apdu;
	u8		    rbuf[SC_MAX_APDU_BUFFER_SIZE];

	sc_log(p15card->card->ctx, "Setting pkcs15 parameters");

	if (p15card->tokeninfo->label)
		free(p15card->tokeninfo->label);
	p15card->tokeninfo->label = malloc(strlen(APPLET_NAME) + 1);
	if (!p15card->tokeninfo->label)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->tokeninfo->label, APPLET_NAME);

	if (p15card->tokeninfo->serial_number)
		free(p15card->tokeninfo->serial_number);
	p15card->tokeninfo->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1);
	if (!p15card->tokeninfo->serial_number)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER);

	/* the GemSAFE applet version number */
	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03);
	apdu.cla = 0x80;
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	/* Manual says Le=0x05, but should be 0x08 to return full version number */
	apdu.le = 0x08;
	apdu.lc = 0;
	apdu.datalen = 0;
	r = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");

	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
		return SC_ERROR_INTERNAL;
	if (r != SC_SUCCESS)
		return SC_ERROR_INTERNAL;

	/* the manufacturer ID, in this case GemPlus */
	if (p15card->tokeninfo->manufacturer_id)
		free(p15card->tokeninfo->manufacturer_id);
	p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1);
	if (!p15card->tokeninfo->manufacturer_id)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID);

	/* determine allocated key containers and length of certificates */
	r = gemsafe_get_cert_len(card);
	if (r != SC_SUCCESS)
		return SC_ERROR_INTERNAL;

	/* set certs */
	sc_log(p15card->card->ctx, "Setting certificates");
	for (i = 0; i < gemsafe_cert_max; i++) {
		struct sc_pkcs15_id p15Id;
		struct sc_path path;

		if (gemsafe_cert[i].label == NULL)
			continue;
		sc_format_path(gemsafe_cert[i].path, &path);
		sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id);
		path.index = gemsafe_cert[i].index;
		path.count = gemsafe_cert[i].count;
		sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509,
				      gemsafe_cert[i].authority, &path, &p15Id,
				      gemsafe_cert[i].label, gemsafe_cert[i].obj_flags);
	}

	/* set gemsafe_pin */
	sc_log(p15card->card->ctx, "Setting PIN");
	for (i=0; i < gemsafe_pin_max; i++) {
		struct sc_pkcs15_id	p15Id;
		struct sc_path path;

		sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id);
		sc_format_path(gemsafe_pin[i].path, &path);
		if (gemsafe_pin[i].atr_len == 0 ||
		   (gemsafe_pin[i].atr_len == p15card->card->atr.len &&
		    memcmp(p15card->card->atr.value, gemsafe_pin[i].atr,
			   p15card->card->atr.len) == 0)) {
			sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label,
					     &path, gemsafe_pin[i].ref, gemsafe_pin[i].type,
					     gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen,
					     gemsafe_pin[i].flags, gemsafe_pin[i].tries_left,
					     gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags);
			break;
		}
	};

	/* set private keys */
	sc_log(p15card->card->ctx, "Setting private keys");
	for (i = 0; i < gemsafe_cert_max; i++) {
		struct sc_pkcs15_id p15Id, authId, *pauthId;
		struct sc_path path;
		int key_ref = 0x03;

		if (gemsafe_prkeys[i].label == NULL)
			continue;
		sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id);
		if (gemsafe_prkeys[i].auth_id) {
			sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId);
			pauthId = &authId;
		} else
			pauthId = NULL;
		sc_format_path(gemsafe_prkeys[i].path, &path);
		/*
		 * The key ref may be different for different sites;
		 * by adding flags=n where the low order 4 bits can be
		 * the key ref we can force it.
		 */
		if ( p15card->card->flags & 0x0F) {
			key_ref = p15card->card->flags & 0x0F;
			sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Overriding key_ref %d with %d\n",
				 gemsafe_prkeys[i].ref, key_ref);
		} else
			key_ref = gemsafe_prkeys[i].ref;
		sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label,
				       SC_PKCS15_TYPE_PRKEY_RSA,
				       gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage,
				       &path, key_ref, pauthId,
				       gemsafe_prkeys[i].obj_flags);
	}

	/* select the application DF */
	sc_log(p15card->card->ctx, "Selecting application DF");
	sc_format_path(GEMSAFE_APP_PATH, &path);
	r = sc_select_file(card, &path, &file);
	if (r != SC_SUCCESS || !file)
		return SC_ERROR_INTERNAL;
	/* set the application DF */
	if (p15card->file_app)
		free(p15card->file_app);
	p15card->file_app = file;

	return SC_SUCCESS;
}

Project: OpenSC
File: sc.c

int sc_valid_oid(const struct sc_object_id *oid)
{
	int ii;

	if (!oid)
		return 0;
	if (oid->value[0] == -1 || oid->value[1] == -1)
		return 0;
	if (oid->value[0] > 2 || oid->value[1] > 39)
		return 0;
	for (ii=0;ii<SC_MAX_OBJECT_ID_OCTETS;ii++)
		if (oid->value[ii])
			break;
	if (ii==SC_MAX_OBJECT_ID_OCTETS)
		return 0;
	return 1;
}

Project: OpenSC
File: card-epass2003.c

internal_sanitize_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
{
	pin->encoding = SC_PIN_ENCODING_ASCII;
	pin->min_length = 4;
	pin->max_length = 16;
	pin->pad_length = 16;
	pin->offset = 5 + num * 16;
	pin->pad_char = 0x00;
}

Project: OpenSC
File: sc.c

int sc_concatenate_path(sc_path_t *d, const sc_path_t *p1, const sc_path_t *p2)
{
	sc_path_t tpath;

	if (d == NULL || p1 == NULL || p2 == NULL)
		return SC_ERROR_INVALID_ARGUMENTS;

	if (p1->type == SC_PATH_TYPE_DF_NAME || p2->type == SC_PATH_TYPE_DF_NAME)
		/* we do not support concatenation of AIDs at the moment */
		return SC_ERROR_NOT_SUPPORTED;

	if (p1->len + p2->len > SC_MAX_PATH_SIZE)
		return SC_ERROR_INVALID_ARGUMENTS;

	memset(&tpath, 0, sizeof(sc_path_t));
	memcpy(tpath.value, p1->value, p1->len);
	memcpy(tpath.value + p1->len, p2->value, p2->len);
	tpath.len  = p1->len + p2->len;
	tpath.type = SC_PATH_TYPE_PATH;
	/* use 'index' and 'count' entry of the second path object */
	tpath.index = p2->index;
	tpath.count = p2->count;
	/* the result is currently always as path */
	tpath.type  = SC_PATH_TYPE_PATH;

	*d = tpath;

	return SC_SUCCESS;
}

Project: OpenSC
File: sc.c

int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr,
			 size_t prop_attr_len)
{
	u8 *tmp;
	if (!sc_file_valid(file)) {
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	if (prop_attr == NULL) {
		if (file->prop_attr != NULL)
			free(file->prop_attr);
		file->prop_attr = NULL;
		file->prop_attr_len = 0;
		return SC_SUCCESS;
	 }
	tmp = (u8 *) realloc(file->prop_attr, prop_attr_len);
	if (!tmp) {
		if (file->prop_attr)
			free(file->prop_attr);
		file->prop_attr = NULL;
		file->prop_attr_len = 0;
		return SC_ERROR_OUT_OF_MEMORY;
	}
	file->prop_attr = tmp;
	memcpy(file->prop_attr, prop_attr, prop_attr_len);
	file->prop_attr_len = prop_attr_len;

	return SC_SUCCESS;
}

Project: OpenSC
File: cryptoflex-tool.c

static int store_key(void)
{
	u8 prv[1024], pub[1024];
	size_t prvsize, pubsize;
	int r;
	RSA *rsa;

	r = read_rsa_privkey(&rsa);
	if (r)
		return r;
	r = encode_private_key(rsa, prv, &prvsize);
	if (r)
		return r;
	r = encode_public_key(rsa, pub, &pubsize);
	if (r)
		return r;
	if (verbose)
		printf("Storing private key...\n");
	r = select_app_df();
	if (r)
		return r;
	r = update_private_key(prv, prvsize);
	if (r)
		return r;
	if (verbose)
		printf("Storing public key...\n");
	r = select_app_df();
	if (r)
		return r;
	r = update_public_key(pub, pubsize);
	if (r)
		return r;
	return 0;
}

Project: OpenSC
File: card-epass2003.c

get_data(struct sc_card *card, unsigned char type, unsigned char *data, size_t datalen)
{
	int r;
	struct sc_apdu apdu;
	unsigned char resp[SC_MAX_APDU_BUFFER_SIZE] = { 0 };
	size_t resplen = SC_MAX_APDU_BUFFER_SIZE;
	epass2003_exdata *exdata = NULL;

	if (!card->drv_data) 
		return SC_ERROR_INVALID_ARGUMENTS;

	exdata = (epass2003_exdata *)card->drv_data;

	LOG_FUNC_CALLED(card->ctx);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, type);
	apdu.resp = resp;
	apdu.le = 0;
	apdu.resplen = resplen;
	if (0x86 == type) {
		/* No SM temporarily */
		unsigned char tmp_sm = exdata->sm;
		exdata->sm = SM_PLAIN;
		r = sc_transmit_apdu(card, &apdu);
		exdata->sm = tmp_sm;
	}
	else {
		r = sc_transmit_apdu_t(card, &apdu);
	}
	LOG_TEST_RET(card->ctx, r, "APDU get_data failed");
	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, r, "get_data failed");

	memcpy(data, resp, datalen);
	return r;
}

Project: OpenSC
File: card-epass2003.c

epass2003_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2)
{
	const int err_count = sizeof(epass2003_errors)/sizeof(epass2003_errors[0]);
	int i;

	/* Handle special cases here */
	if (sw1 == 0x6C) {
		sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
		return SC_ERROR_WRONG_LENGTH;
	}


	for (i = 0; i < err_count; i++)   {
		if (epass2003_errors[i].SWs == ((sw1 << 8) | sw2)) {
			sc_log(card->ctx, "%s", epass2003_errors[i].errorstr);
			return epass2003_errors[i].errorno;
		}
	}

	sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
	return SC_ERROR_CARD_CMD_FAILED;
}

Project: OpenSC
File: card-epass2003.c

epass2003_finish(sc_card_t *card)
{
	epass2003_exdata *exdata = (epass2003_exdata *)card->drv_data;

	if (exdata)
		free(exdata);
	return SC_SUCCESS;
}

Project: OpenSC
File: card-epass2003.c

epass2003_create_file(struct sc_card *card, sc_file_t * file)
{
	int r;
	size_t len;
	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE] = { 0 };
	struct sc_apdu apdu;

	len = SC_MAX_APDU_BUFFER_SIZE;

	epass2003_hook_file(file, 1);

	if (card->ops->construct_fci == NULL)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);

	r = epass2003_construct_fci(card, file, sbuf, &len);
	LOG_TEST_RET(card->ctx, r, "construct_fci() failed");

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
	apdu.lc = len;
	apdu.datalen = len;
	apdu.data = sbuf;

	r = sc_transmit_apdu_t(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, "APDU sw1/2 wrong");

	epass2003_hook_file(file, 0);
	return r;
}

Project: OpenSC
File: card-muscle.c

static int muscle_card_ctl(sc_card_t *card, unsigned long request, void *data)
{
	switch(request) {
	case SC_CARDCTL_MUSCLE_GENERATE_KEY:
		return muscle_card_generate_key(card, (sc_cardctl_muscle_gen_key_info_t*) data);
	case SC_CARDCTL_MUSCLE_EXTRACT_KEY:
		return muscle_card_extract_key(card, (sc_cardctl_muscle_key_info_t*) data);
	case SC_CARDCTL_MUSCLE_IMPORT_KEY:
		return muscle_card_import_key(card, (sc_cardctl_muscle_key_info_t*) data);
	case SC_CARDCTL_MUSCLE_VERIFIED_PINS:
		return muscle_card_verified_pins(card, (sc_cardctl_muscle_verified_pins_info_t*) data);
	default:
		return SC_ERROR_NOT_SUPPORTED; /* Unsupported.. whatever it is */
	}
}

Project: OpenSC
File: card-epass2003.c

external_key_auth(struct sc_card *card, unsigned char kid,
		unsigned char *data, size_t datalen)
{
	int r;
	struct sc_apdu apdu;
	unsigned char random[16] = { 0 };
	unsigned char tmp_data[16] = { 0 };
	unsigned char hash[HASH_LEN] = { 0 };
	unsigned char iv[16] = { 0 };

	r = sc_get_challenge(card, random, 8);
	LOG_TEST_RET(card->ctx, r, "get challenge external_key_auth failed");

	r = hash_data(data, datalen, hash, SC_ALGORITHM_ECDSA_HASH_SHA1);
	LOG_TEST_RET(card->ctx, r, "hash data failed");

	des3_encrypt_cbc(hash, HASH_LEN, iv, random, 8, tmp_data);
	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x82, 0x01, 0x80 | kid);
	apdu.lc = apdu.datalen = 8;
	apdu.data = tmp_data;

	r = sc_transmit_apdu_t(card, &apdu);
	LOG_TEST_RET(card->ctx, r, "APDU external_key_auth failed");
	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, r, "external_key_auth failed");

	return r;
}

Project: OpenSC
File: card-cac.c

static int cac_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
{
	/* CAC requires 8 byte response */
	u8 rbuf[8];
	u8 *rbufp = &rbuf[0];
	size_t out_len = sizeof rbuf;
	int r;

	LOG_FUNC_CALLED(card->ctx);

	r = cac_apdu_io(card, 0x84, 0x00, 0x00, NULL, 0, &rbufp, &out_len);
	LOG_TEST_RET(card->ctx, r, "Could not get challenge");

	if (len < out_len) {
		out_len = len;
	}
	memcpy(rnd, rbuf, out_len);

	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, (int) out_len);
}

Project: OpenSC
File: card-epass2003.c

des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH],
		const unsigned char *input, size_t length, unsigned char *output)
{
	return openssl_enc(EVP_des_cbc(), key, iv, input, length, output);
}

Project: OpenSC
File: card-epass2003.c

epass2003_refresh(struct sc_card *card)
{
	int r = SC_SUCCESS;
	epass2003_exdata *exdata = NULL;

	if (!card->drv_data) 
		return SC_ERROR_INVALID_ARGUMENTS;

	exdata = (epass2003_exdata *)card->drv_data;

	if (exdata->sm) {
		card->sm_ctx.sm_mode = 0;
		r = mutual_auth(card, g_init_key_enc, g_init_key_mac);
		card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
		LOG_TEST_RET(card->ctx, r, "mutual_auth failed");
	}

	return r;
}

Project: OpenSC
File: pkcs15-sc-hsm.c

int sc_pkcs15emu_sc_hsm_get_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey)
{
	if (cvc->publicPoint && cvc->publicPointlen) {
		return sc_pkcs15emu_sc_hsm_get_ec_public_key(ctx, cvc, pubkey);
	} else {
		return sc_pkcs15emu_sc_hsm_get_rsa_public_key(ctx, cvc, pubkey);
	}
}

Project: OpenSC
File: cryptoflex-tool.c

static int read_public_key(RSA *rsa)
{
	int r;
	sc_path_t path;
	sc_file_t *file;
	u8 buf[2048], *p = buf;
	size_t bufsize, keysize;

	r = select_app_df();
	if (r)
		return 1;
	sc_format_path("I1012", &path);
	r = sc_select_file(card, &path, &file);
	if (r) {
		fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r));
		return 2;
	}
	bufsize = MIN(file->size, sizeof buf);
	sc_file_free(file);
	r = sc_read_binary(card, 0, buf, bufsize, 0);
	if (r < 0) {
		fprintf(stderr, "Unable to read public key file: %s\n", sc_strerror(r));
		return 2;
	}
	bufsize = r;
	do {
		if (bufsize < 4)
			return 3;
		keysize = (p[0] << 8) | p[1];
		if (keysize == 0)
			break;
		if (keysize < 3)
			return 3;
		if (p[2] == opt_key_num)
			break;
		p += keysize;
		bufsize -= keysize;
	} while (1);
	if (keysize == 0) {
		printf("Key number %d not found.\n", opt_key_num);
		return 2;
	}
	return parse_public_key(p, keysize, rsa);
}

Project: OpenSC
File: util.c

util_print_usage_and_die(const char *app_name, const struct option options[],
	const char *option_help[], const char *args)
{
	int i;
	int header_shown = 0;

	if (args)
		printf("Usage: %s [OPTIONS] %s\n", app_name, args);
	else
		printf("Usage: %s [OPTIONS]\n", app_name);

	for (i = 0; options[i].name; i++) {
		char buf[40];
		const char *arg_str;

		/* Skip "hidden" options */
		if (option_help[i] == NULL)
			continue;

		if (!header_shown++)
			printf("Options:\n");

		switch (options[i].has_arg) {
		case 1:
			arg_str = " <arg>";
			break;
		case 2:
			arg_str = " [arg]";
			break;
		default:
			arg_str = "";
			break;
		}
		if (isascii(options[i].val) &&
		    isprint(options[i].val) && !isspace(options[i].val))
			sprintf(buf, "-%c, --%s%s", options[i].val, options[i].name, arg_str);
		else
			sprintf(buf, "    --%s%s", options[i].name, arg_str);

		/* print the line - wrap if necessary */
		if (strlen(buf) > 28) {
			printf("  %s\n", buf);
			buf[0] = '\0';
		}
		printf("  %-28s  %s\n", buf, option_help[i]);
	}

	exit(2);
}

Project: OpenSC
File: card-epass2003.c

epass2003_hook_file(struct sc_file *file, int inc)
{
	int fidl = file->id & 0xff;
	int fidh = file->id & 0xff00;
	if (epass2003_hook_path(&file->path, inc)) {
		if (inc)
			file->id = fidh + fidl * FID_STEP;
		else
			file->id = fidh + fidl / FID_STEP;
	}
}

Project: OpenSC
File: card-muscle.c

static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
{
	mscfs_t *fs = MUSCLE_FS(card);
	msc_id id = file_data->objectId;
	u8* oid = id.id;
	int r;

	if(!file_data->ef) {
		int x;
		mscfs_file_t *childFile;
		/* Delete children */
		mscfs_check_cache(fs);

		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
			"DELETING Children of: %02X%02X%02X%02X\n",
			oid[0],oid[1],oid[2],oid[3]);
		for(x = 0; x < fs->cache.size; x++) {
			msc_id objectId;
			childFile = &fs->cache.array[x];
			objectId = childFile->objectId;

			if(0 == memcmp(oid + 2, objectId.id, 2)) {
				sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
					"DELETING: %02X%02X%02X%02X\n",
					objectId.id[0],objectId.id[1],
					objectId.id[2],objectId.id[3]);
				r = muscle_delete_mscfs_file(card, childFile);
				if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,r);
			}
		}
		oid[0] = oid[2];
		oid[1] = oid[3];
		oid[2] = oid[3] = 0;
		/* ??? objectId = objectId >> 16; */
	}
	if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
		|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4))) {
	}
	r = msc_delete_object(card, id, 1);
	/* Check if its the root... this file generally is virtual
	 * So don't return an error if it fails */
	if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
		|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4)))
		return 0;

	if(r < 0) {
		printf("ID: %02X%02X%02X%02X\n",
					oid[0],oid[1],oid[2],oid[3]);
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,r);
	}
	return 0;
}

Project: OpenSC
File: cryptoflex-tool.c

static int create_key_files(void)
{
	sc_file_t *file;
	int mod_lens[] = { 512, 768, 1024, 2048 };
	int sizes[] = { 163, 243, 323, 643 };
	int size = -1;
	int r;
	size_t i;

	for (i = 0; i < sizeof(mod_lens) / sizeof(int); i++)
		if (mod_lens[i] == opt_mod_length) {
			size = sizes[i];
			break;
		}
	if (size == -1) {
		fprintf(stderr, "Invalid modulus length.\n");
		return 1;
	}

	if (verbose)
		printf("Creating key files for %d keys.\n", opt_key_count);

	file = sc_file_new();
	if (!file) {
		fprintf(stderr, "out of memory.\n");
		return 1;
	}
	file->type = SC_FILE_TYPE_WORKING_EF;
	file->ef_structure = SC_FILE_EF_TRANSPARENT;

	file->id = 0x0012;
	file->size = opt_key_count * size + 3;
	sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NEVER, SC_AC_KEY_REF_NONE);
	sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_CHV, 1);
	sc_file_add_acl_entry(file, SC_AC_OP_INVALIDATE, SC_AC_CHV, 1);
	sc_file_add_acl_entry(file, SC_AC_OP_REHABILITATE, SC_AC_CHV, 1);

	if (select_app_df()) {
		sc_file_free(file);
		return 1;
	}
	r = sc_create_file(card, file);
	sc_file_free(file);
	if (r) {
		fprintf(stderr, "Unable to create private key file: %s\n", sc_strerror(r));
		return 1;
	}

	file = sc_file_new();
	if (!file) {
		fprintf(stderr, "out of memory.\n");
		return 1;
	}
	file->type = SC_FILE_TYPE_WORKING_EF;
	file->ef_structure = SC_FILE_EF_TRANSPARENT;

	file->id = 0x1012;
	file->size = opt_key_count * (size + 4) + 3;
	sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE);
	sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_CHV, 1);
	sc_file_add_acl_entry(file, SC_AC_OP_INVALIDATE, SC_AC_CHV, 1);
	sc_file_add_acl_entry(file, SC_AC_OP_REHABILITATE, SC_AC_CHV, 1);

	if (select_app_df()) {
		sc_file_free(file);
		return 1;
	}
	r = sc_create_file(card, file);
	sc_file_free(file);
	if (r) {
		fprintf(stderr, "Unable to create public key file: %s\n", sc_strerror(r));
		return 1;
	}
	if (verbose)
		printf("Key files generated successfully.\n");
	return 0;
}

Project: OpenSC
File: cryptoflex-tool.c

static BIGNUM * cf2bn(const u8 *buf, size_t bufsize, BIGNUM *num)
{
	u8 tmp[512];

	invert_buf(tmp, buf, bufsize);

	return BN_bin2bn(tmp, bufsize, num);
}

Project: OpenSC
File: sc.c

int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2)
{
	int i;

	if (oid1 == NULL || oid2 == NULL) {
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++)   {
		if (oid1->value[i] != oid2->value[i])
			return 0;
		if (oid1->value[i] == -1)
			break;
	}

	return 1;
}

Project: OpenSC
File: sc.c

int sc_compare_path_prefix(const sc_path_t *prefix, const sc_path_t *path)
{
	sc_path_t tpath;

	if (prefix->len > path->len)
		return 0;

	tpath     = *path;
	tpath.len = prefix->len;

	return sc_compare_path(&tpath, prefix);
}

Project: OpenSC
File: card-cac.c

static int cac_find_first_pki_applet(sc_card_t *card, int *index_out)
{
	int r, i;
	for (i = 0; i < MAX_CAC_SLOTS; i++) {
		r = cac_select_pki_applet(card, i);
		if (r == SC_SUCCESS) {
			/* Try to read first two bytes of the buffer to
			 * make sure it is not just malfunctioning card
			 */
			u8 params[2] = {CAC_FILE_TAG, 2};
			u8 data[2], *out_ptr = data;
			size_t len = 2;
			r = cac_apdu_io(card, CAC_INS_READ_FILE, 0, 0,
			    &params[0], sizeof(params), &out_ptr, &len);
			if (r != 2)
				continue;

			*index_out = i;
			return SC_SUCCESS;
		}
	}
	return SC_ERROR_OBJECT_NOT_FOUND;
}

Project: OpenSC
File: card-cac.c

static int cac_get_serial_nr_from_CUID(sc_card_t* card, sc_serial_number_t* serial)
{
	cac_private_data_t * priv = CAC_DATA(card);

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
        if (card->serialnr.len)   {
                *serial = card->serialnr;
                SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
        }
	if (priv->cac_id_len) {
		serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
		memcpy(serial->value, priv->cac_id, serial->len);
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
	}
	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND);
}

Project: OpenSC
File: card-epass2003.c

epass2003_init(struct sc_card *card)
{
	unsigned int flags;
	unsigned int ext_flags;
	unsigned char data[SC_MAX_APDU_BUFFER_SIZE] = { 0 };
	size_t datalen = SC_MAX_APDU_BUFFER_SIZE;
	epass2003_exdata *exdata = NULL;

	LOG_FUNC_CALLED(card->ctx);

	card->name = "epass2003";
	card->cla = 0x00;
	exdata = (epass2003_exdata *)calloc(1, sizeof(epass2003_exdata));
	if (!exdata)
		return SC_ERROR_OUT_OF_MEMORY;

	card->drv_data = exdata;

	exdata->sm = SM_SCP01;

	/* decide FIPS/Non-FIPS mode */
	if (SC_SUCCESS != get_data(card, 0x86, data, datalen))
		return SC_ERROR_INVALID_CARD;

	if (0x01 == data[2])
		exdata->smtype = KEY_TYPE_AES;
	else
		exdata->smtype = KEY_TYPE_DES;

	if (0x84 == data[14]) {
		if (0x00 == data[16]) { 
			exdata->sm = SM_PLAIN;
		}
	}


	/* mutual authentication */
	card->max_recv_size = 0xD8;
	card->max_send_size = 0xE8;

	card->sm_ctx.ops.open = epass2003_refresh;
	card->sm_ctx.ops.get_sm_apdu = epass2003_sm_get_wrapped_apdu;
	card->sm_ctx.ops.free_sm_apdu = epass2003_sm_free_wrapped_apdu;

	/* FIXME (VT): rather then set/unset 'g_sm', better to implement filter for APDUs to be wrapped */
	epass2003_refresh(card);

	card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;

	flags = SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE;

	_sc_card_add_rsa_alg(card, 512, flags, 0);
	_sc_card_add_rsa_alg(card, 768, flags, 0);
	_sc_card_add_rsa_alg(card, 1024, flags, 0);
	_sc_card_add_rsa_alg(card, 2048, flags, 0);

	//set EC Alg Flags
	flags = SC_ALGORITHM_ONBOARD_KEY_GEN|SC_ALGORITHM_ECDSA_HASH_SHA1|SC_ALGORITHM_ECDSA_HASH_SHA256|SC_ALGORITHM_ECDSA_HASH_NONE|SC_ALGORITHM_ECDSA_RAW;
	ext_flags = 0;
	_sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL);

	card->caps = SC_CARD_CAP_RNG | SC_CARD_CAP_APDU_EXT;

	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

Project: OpenSC
File: card-epass2003.c

epass2003_write_key(struct sc_card *card, sc_epass2003_wkey_data * data)
{
	LOG_FUNC_CALLED(card->ctx);

	if (data->type & SC_EPASS2003_KEY) {
		if (data->type == SC_EPASS2003_KEY_RSA)
			return internal_write_rsa_key(card, data->key_data.es_key.fid,
						      data->key_data.es_key.rsa);
		else
			LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
	} else if (data->type & SC_EPASS2003_SECRET) {
		if (data->type == SC_EPASS2003_SECRET_PRE)
			return internal_install_pre(card);
		else if (data->type == SC_EPASS2003_SECRET_PIN)
			return internal_install_pin(card, data);
		else
			LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
	}
	else {
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
	}

	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

Project: OpenSC
File: card-tcos.c

static int tcos_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
{
	sc_context_t *ctx;
	sc_apdu_t apdu;
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
	tcos_data *data;
	int tcos3, r;

	assert(card != NULL && crgram != NULL && out != NULL);
	ctx = card->ctx;
	tcos3=(card->type==SC_CARD_TYPE_TCOS_V3);
	data=(tcos_data *)card->drv_data;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
		"TCOS3:%d PKCS1:%d\n",tcos3,
		!!(data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1));

	sc_format_apdu(card, &apdu, crgram_len>255 ? SC_APDU_CASE_4_EXT : SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86);
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le = crgram_len;

	apdu.data = sbuf;
	apdu.lc = apdu.datalen = crgram_len+1;
	sbuf[0] = tcos3 ? 0x00 : ((data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) ? 0x81 : 0x02);
	memcpy(sbuf+1, crgram, crgram_len);

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");

	if (apdu.sw1==0x90 && apdu.sw2==0x00) {
		size_t len= (apdu.resplen>outlen) ? outlen : apdu.resplen;
		unsigned int offset=0;
		if(tcos3 && (data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) && apdu.resp[0]==0 && apdu.resp[1]==2){
			offset=2; while(offset<len && apdu.resp[offset]!=0) ++offset;
			offset=(offset<len-1) ? offset+1 : 0;
		}
		memcpy(out, apdu.resp+offset, len-offset);
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len-offset);
	}
	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
}

Project: OpenSC
File: card-cac.c

static int cac_get_properties(sc_card_t *card, cac_properties_t *prop)
{
	u8 *rbuf = NULL;
	size_t rbuflen = 0, len;
	u8 *val, *val_end, tag;
	size_t i = 0;
	int r;
	prop->num_objects = 0;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	r = cac_apdu_io(card, CAC_INS_GET_PROPERTIES, 0x01, 0x00, NULL, 0,
		&rbuf, &rbuflen);
	if (r < 0)
		return r;

	val = rbuf;
	val_end = val + rbuflen;
	for (; val < val_end; val += len) {
		/* get the tag and the length */
		if (sc_simpletlv_read_tag(&val, val_end - val, &tag, &len) != SC_SUCCESS)
			break;

		switch (tag) {
		case CAC_TAG_APPLET_INFORMATION:
			if (len != 5) {
				sc_log(card->ctx, "TAG: Applet Information: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: Applet Information: Family: 0x%0x", val[0]);
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "     Applet Version: 0x%02x 0x%02x 0x%02x 0x%02x",
			    val[1], val[2], val[3], val[4]);
			break;

		case CAC_TAG_NUMBER_OF_OBJECTS:
			if (len != 1) {
				sc_log(card->ctx, "TAG: Num objects: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: Num objects = %hhd", *val);
			/* make sure we do not overrun buffer */
			prop->num_objects = MIN(val[0], CAC_MAX_OBJECTS);
			break;

		case CAC_TAG_TV_BUFFER:
			if (len != 17) {
				sc_log(card->ctx, "TAG: TV Object: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: TV Object nr. %"SC_FORMAT_LEN_SIZE_T"u", i);
			if (i >= CAC_MAX_OBJECTS) {
				free(rbuf);
				return SC_SUCCESS;
			}

			if (cac_parse_properties_object(card, tag, val, len,
			    &prop->objects[i]) == SC_SUCCESS)
				i++;
			break;

		case CAC_TAG_PKI_OBJECT:
			if (len != 17) {
				sc_log(card->ctx, "TAG: PKI Object: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: PKI Object nr. %"SC_FORMAT_LEN_SIZE_T"u", i);
			if (i >= CAC_MAX_OBJECTS) {
				free(rbuf);
				return SC_SUCCESS;
			}

			if (cac_parse_properties_object(card, tag, val, len,
			    &prop->objects[i]) == SC_SUCCESS)
				i++;
			break;

		default:
			/* ignore tags we don't understand */
			sc_log(card->ctx, "TAG: Unknown (0x%02x), len=%"
			    SC_FORMAT_LEN_SIZE_T"u", tag, len);
			break;
		}
	}
	free(rbuf);
	/* sanity */
	if (i != prop->num_objects)
		sc_log(card->ctx, "The announced number of objects (%u) "
		    "did not match reality (%"SC_FORMAT_LEN_SIZE_T"u)",
		    prop->num_objects, i);
	prop->num_objects = i;

	return SC_SUCCESS;
}

Project: OpenSC
File: card-epass2003.c

epass2003_select_aid(struct sc_card *card, const sc_path_t * in_path, sc_file_t ** file_out)
{
	int r = 0;

	if (card->cache.valid
			&& card->cache.current_path.type == SC_PATH_TYPE_DF_NAME
			&& card->cache.current_path.len == in_path->len
			&& memcmp(card->cache.current_path.value, in_path->value, in_path->len) == 0) {
		if (file_out) {
			*file_out = sc_file_new();
			if (!file_out)
				LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
		}
	}
	else {
		r = iso_ops->select_file(card, in_path, file_out);
		LOG_TEST_RET(card->ctx, r, "APDU transmit failed");

		/* update cache */
		card->cache.current_path.type = SC_PATH_TYPE_DF_NAME;
		card->cache.current_path.len = in_path->len;
		memcpy(card->cache.current_path.value, in_path->value, in_path->len);
	}

	if (file_out) {
		sc_file_t *file = *file_out;

		file->type = SC_FILE_TYPE_DF;
		file->ef_structure = SC_FILE_EF_UNKNOWN;
		file->path.len = 0;
		file->size = 0;
		/* AID */
		memcpy(file->name, in_path->value, in_path->len);
		file->namelen = in_path->len;
		file->id = 0x0000;
	}

	LOG_FUNC_RETURN(card->ctx, r);
}

Project: OpenSC
File: card-epass2003.c

static struct sc_card_driver *sc_get_driver(void)
{
	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();

	if (iso_ops == NULL)
		iso_ops = iso_drv->ops;

	epass2003_ops = *iso_ops;

	epass2003_ops.match_card = epass2003_match_card;
	epass2003_ops.init = epass2003_init;
	epass2003_ops.finish = epass2003_finish;
	epass2003_ops.write_binary = NULL;
	epass2003_ops.write_record = NULL;
	epass2003_ops.select_file = epass2003_select_file;
	epass2003_ops.get_response = NULL;
	epass2003_ops.restore_security_env = epass2003_restore_security_env;
	epass2003_ops.set_security_env = epass2003_set_security_env;
	epass2003_ops.decipher = epass2003_decipher;
	epass2003_ops.compute_signature = epass2003_decipher;
	epass2003_ops.create_file = epass2003_create_file;
	epass2003_ops.delete_file = epass2003_delete_file;
	epass2003_ops.list_files = epass2003_list_files;
	epass2003_ops.card_ctl = epass2003_card_ctl;
	epass2003_ops.process_fci = epass2003_process_fci;
	epass2003_ops.construct_fci = epass2003_construct_fci;
	epass2003_ops.pin_cmd = epass2003_pin_cmd;
	epass2003_ops.check_sw = epass2003_check_sw;
	epass2003_ops.get_challenge = epass2003_get_challenge;
	return &epass2003_drv;
}

Project: OpenSC
File: sc.c

int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen)
{
	int err = SC_SUCCESS;
	size_t left, count = 0, in_len;

	if (in == NULL || out == NULL || outlen == NULL) {
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	left = *outlen;
	in_len = strlen(in);

	while (*in != '\0') {
		int byte = 0, nybbles = 2;

		while (nybbles-- && *in && *in != ':' && *in != ' ') {
			char c;
			byte <<= 4;
			c = *in++;
			if ('0' <= c && c <= '9')
				c -= '0';
			else
			if ('a' <= c && c <= 'f')
				c = c - 'a' + 10;
			else
			if ('A' <= c && c <= 'F')
				c = c - 'A' + 10;
			else {
				err = SC_ERROR_INVALID_ARGUMENTS;
				goto out;
			}
			byte |= c;
		}

		/* Detect premature end of string before byte is complete */
		if (in_len > 1 && *in == '\0' && nybbles >= 0) {
			err = SC_ERROR_INVALID_ARGUMENTS;
			break;
		}

		if (*in == ':' || *in == ' ')
			in++;
		if (left <= 0) {
			err = SC_ERROR_BUFFER_TOO_SMALL;
			break;
		}
		out[count++] = (u8) byte;
		left--;
	}

out:
	*outlen = count;
	return err;
}

Project: OpenSC
File: pkcs15-gemsafeV1.c

static int gemsafe_detect_card( sc_pkcs15_card_t *p15card)
{
	if (strcmp(p15card->card->name, "GemSAFE V1"))
		return SC_ERROR_WRONG_CARD;

	return SC_SUCCESS;
}

Project: OpenSC
File: card-muscle.c

static int muscle_card_extract_key(sc_card_t *card, sc_cardctl_muscle_key_info_t *info)
{
	/* CURRENTLY DONT SUPPORT EXTRACTING PRIVATE KEYS... */
	switch(info->keyType) {
	case 1: /* RSA */
		return msc_extract_rsa_public_key(card,
			info->keyLocation,
			&info->modLength,
			&info->modValue,
			&info->expLength,
			&info->expValue);
	default:
		return SC_ERROR_NOT_SUPPORTED;
	}
}

Project: OpenSC
File: card-cac.c

static int cac_get_init_and_get_count(list_t *list, cac_object_t **entry, int *countp)
{
	*countp = list_size(list);
	list_iterator_start(list);
	*entry = list_iterator_next(list);
	return SC_SUCCESS;
}

Project: OpenSC
File: util.c

util_error(const char *fmt, ...)
{
	va_list	ap;

	va_start(ap, fmt);
	fprintf(stderr, "error: ");
	vfprintf(stderr, fmt, ap);
	fprintf(stderr, "\n");
	va_end(ap);
}

Project: OpenSC
File: card-cac.c

static int cac_select_pki_applet(sc_card_t *card, int index)
{
	sc_path_t applet_path = cac_cac_pki_obj.path;
	applet_path.aid.value[applet_path.aid.len-1] = index;
	return cac_select_file_by_type(card, &applet_path, NULL, SC_CARD_TYPE_CAC_II);
}

Project: OpenSC
File: sc.c

unsigned short bebytes2ushort(const u8 *buf)
{
	if (buf == NULL)
		return 0U;
	return (unsigned short) (buf[0] << 8 | buf[1]);
}

Project: OpenSC
File: card-tcos.c

static int tcos_list_files(sc_card_t *card, u8 *buf, size_t buflen)
{
	sc_context_t *ctx;
	sc_apdu_t apdu;
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], p1;
	int r, count = 0;

	assert(card != NULL);
	ctx = card->ctx;

	for (p1=1; p1<=2; p1++) {
		sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, p1, 0);
		apdu.cla = 0x80;
		apdu.resp = rbuf;
		apdu.resplen = sizeof(rbuf);
		apdu.le = 256;
		r = sc_transmit_apdu(card, &apdu);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
		if (apdu.sw1==0x6A && (apdu.sw2==0x82 || apdu.sw2==0x88)) continue;
		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "List Dir failed");
		if (apdu.resplen > buflen) return SC_ERROR_BUFFER_TOO_SMALL;
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
			 "got %"SC_FORMAT_LEN_SIZE_T"u %s-FileIDs\n",
			 apdu.resplen / 2, p1 == 1 ? "DF" : "EF");

		memcpy(buf, apdu.resp, apdu.resplen);
		buf += apdu.resplen;
		buflen -= apdu.resplen;
		count += apdu.resplen;
	}
	return count;
}

Project: OpenSC
File: card-epass2003.c

internal_install_pre(struct sc_card *card)
{
	int r;
	/* init key for enc */
	r = install_secret_key(card, 0x01, 0x00,
			       EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_EVERYONE,
			       EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_EVERYONE,
			       0, g_init_key_enc, 16);
	LOG_TEST_RET(card->ctx, r, "Install init key failed");

	/* init key for mac */
	r = install_secret_key(card, 0x02, 0x00,
			       EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_EVERYONE,
			       EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_EVERYONE,
			       0, g_init_key_mac, 16);
	LOG_TEST_RET(card->ctx, r, "Install init key failed");

	return r;
}

Project: OpenSC
File: card-epass2003.c

aes128_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[16],
		const unsigned char *input, size_t length, unsigned char *output)
{
	return openssl_dec(EVP_aes_128_cbc(), key, iv, input, length, output);
}

Project: OpenSC
File: card-epass2003.c

epass2003_construct_fci(struct sc_card *card, const sc_file_t * file,
		u8 * out, size_t * outlen)
{
	u8 *p = out;
	u8 buf[64];
	unsigned char ops[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
	int rv;
	unsigned ii;

	if (*outlen < 2)
		return SC_ERROR_BUFFER_TOO_SMALL;

	*p++ = 0x62;
	p++;
	if (file->type == SC_FILE_TYPE_WORKING_EF) {
		if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
			buf[0] = (file->size >> 8) & 0xFF;
			buf[1] = file->size & 0xFF;
			sc_asn1_put_tag(0x80, buf, 2, p, *outlen - (p - out), &p);
		}
	}
	if (file->type == SC_FILE_TYPE_DF) {
		buf[0] = 0x38;
		buf[1] = 0x00;
		sc_asn1_put_tag(0x82, buf, 2, p, *outlen - (p - out), &p);
	}
	else if (file->type == SC_FILE_TYPE_WORKING_EF) {
		buf[0] = file->ef_structure & 7;
		if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
			buf[1] = 0x00;
			sc_asn1_put_tag(0x82, buf, 2, p, *outlen - (p - out), &p);
		}
		else if (file->ef_structure == SC_FILE_EF_LINEAR_FIXED
			   || file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE) {
			buf[1] = 0x00;
			buf[2] = 0x00;
			buf[3] = 0x40;	/* record length */
			buf[4] = 0x00;	/* record count */
			sc_asn1_put_tag(0x82, buf, 5, p, *outlen - (p - out), &p);
		}
		else {
			return SC_ERROR_NOT_SUPPORTED;
		}

	}
	else if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
		if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT ||
			file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT) {
			buf[0] = 0x11;
			buf[1] = 0x00;
		}
		else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC ||
				file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) {
			buf[0] = 0x12;
			buf[1] = 0x00;
		}
		else {
			return SC_ERROR_NOT_SUPPORTED;
		}
		sc_asn1_put_tag(0x82, buf, 2, p, *outlen - (p - out), &p);
	}
	else if (file->type == SC_FILE_TYPE_BSO) {
		buf[0] = 0x10;
		buf[1] = 0x00;
		sc_asn1_put_tag(0x82, buf, 2, p, *outlen - (p - out), &p);
	}

	buf[0] = (file->id >> 8) & 0xFF;
	buf[1] = file->id & 0xFF;
	sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p);
	if (file->type == SC_FILE_TYPE_DF) {
		if (file->namelen != 0) {
			sc_asn1_put_tag(0x84, file->name, file->namelen, p, *outlen - (p - out), &p);
		}
		else {
			return SC_ERROR_INVALID_ARGUMENTS;
		}
	}
	if (file->type == SC_FILE_TYPE_DF) {
		unsigned char data[2] = {0x00, 0x7F};
		/* 127 files at most */
		sc_asn1_put_tag(0x85, data, sizeof(data), p, *outlen - (p - out), &p);
	}
	else if (file->type == SC_FILE_TYPE_BSO) {
		buf[0] = file->size & 0xff;
		sc_asn1_put_tag(0x85, buf, 1, p, *outlen - (p - out), &p);
	}
	else if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
		if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT ||
		    file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC||
		    file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT||
		    file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) {
			buf[0] = (file->size >> 8) & 0xFF;
			buf[1] = file->size & 0xFF;
			sc_asn1_put_tag(0x85, buf, 2, p, *outlen - (p - out), &p);
		}
	}
	if (file->sec_attr_len) {
		memcpy(buf, file->sec_attr, file->sec_attr_len);
		sc_asn1_put_tag(0x86, buf, file->sec_attr_len, p, *outlen - (p - out), &p);
	}
	else {
		sc_log(card->ctx, "SC_FILE_ACL");
		if (file->type == SC_FILE_TYPE_DF) {
			ops[0] = SC_AC_OP_LIST_FILES;
			ops[1] = SC_AC_OP_CREATE;
			ops[3] = SC_AC_OP_DELETE;
		}
		else if (file->type == SC_FILE_TYPE_WORKING_EF) {
			if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
				ops[0] = SC_AC_OP_READ;
				ops[1] = SC_AC_OP_UPDATE;
				ops[3] = SC_AC_OP_DELETE;
			}
			else if (file->ef_structure == SC_FILE_EF_LINEAR_FIXED
					|| file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE) {
				ops[0] = SC_AC_OP_READ;
				ops[1] = SC_AC_OP_UPDATE;
				ops[2] = SC_AC_OP_WRITE;
				ops[3] = SC_AC_OP_DELETE;
			}
			else {
				return SC_ERROR_NOT_SUPPORTED;
			}
		}
		else if (file->type == SC_FILE_TYPE_BSO) {
			ops[0] = SC_AC_OP_UPDATE;
			ops[3] = SC_AC_OP_DELETE;
		}
		else if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
			if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT ||
				file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT) {
				ops[1] = SC_AC_OP_UPDATE;
				ops[2] = SC_AC_OP_CRYPTO;
				ops[3] = SC_AC_OP_DELETE;
			}
			else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC||
					file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) {
				ops[0] = SC_AC_OP_READ;
				ops[1] = SC_AC_OP_UPDATE;
				ops[2] = SC_AC_OP_CRYPTO;
				ops[3] = SC_AC_OP_DELETE;
			}
		}
		else {
			return SC_ERROR_NOT_SUPPORTED;
		}

		for (ii = 0; ii < sizeof(ops); ii++) {
			const struct sc_acl_entry *entry;

			buf[ii] = 0xFF;
			if (ops[ii] == 0xFF)
				continue;
			entry = sc_file_get_acl_entry(file, ops[ii]);

			rv = acl_to_ac_byte(card, entry);
			LOG_TEST_RET(card->ctx, rv, "Invalid ACL");

			buf[ii] = rv;
		}
		sc_asn1_put_tag(0x86, buf, sizeof(ops), p, *outlen - (p - out), &p);
		if(file->size == 256)	
		{
			out[4]= 0x13;
		}

	}

	/* VT ??? */
	if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC||
		file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) {
		unsigned char data[2] = {0x00, 0x66};
		sc_asn1_put_tag(0x87, data, sizeof(data), p, *outlen - (p - out), &p);
		if(file->size == 256)	
		{
			out[4]= 0x14;
		}
	}

	out[1] = p - out - 2;

	*outlen = p - out;
	return 0;
}

Project: OpenSC
File: card-muscle.c

static void muscle_load_single_acl(sc_file_t* file, int operation, unsigned short acl)
{
	int key;
	/* Everybody by default.... */
	sc_file_add_acl_entry(file, operation, SC_AC_NONE, 0);
	if(acl == 0xFFFF) {
		sc_file_add_acl_entry(file, operation, SC_AC_NEVER, 0);
		return;
	}
	for(key = 0; key < 16; key++) {
		if(acl >> key & 1) {
			sc_file_add_acl_entry(file, operation, SC_AC_CHV, key);
		}
	}
}

Project: OpenSC
File: sc.c

sc_remote_apdu_free (struct sc_remote_data *rdata)
{
	struct sc_remote_apdu *rapdu = NULL;

	if (!rdata)
		return;

	rapdu = rdata->data;
	while(rapdu)   {
		struct sc_remote_apdu *rr = rapdu->next;

		free(rapdu);
		rapdu = rr;
	}
}

Project: OpenSC
File: sc.c

int sc_mutex_unlock(const sc_context_t *ctx, void *mutex)
{
	if (ctx == NULL)
		return SC_ERROR_INVALID_ARGUMENTS;
	if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL)
		return ctx->thread_ctx->unlock_mutex(mutex);
	else
		return SC_SUCCESS;
}

Project: OpenSC
File: card-epass2003.c

static int epass2003_decipher(struct sc_card *card, const u8 * data, size_t datalen,
		u8 * out, size_t outlen)
{
	int r;
	struct sc_apdu apdu;
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = { 0 };
	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE] = { 0 };
	epass2003_exdata *exdata = NULL;
	
	LOG_FUNC_CALLED(card->ctx);
	
	if (!card->drv_data)
		return SC_ERROR_INVALID_ARGUMENTS;
	
	exdata = (epass2003_exdata *)card->drv_data;

	if(exdata->currAlg == SC_ALGORITHM_EC)
	{
		if(exdata->ecAlgFlags & SC_ALGORITHM_ECDSA_HASH_SHA1)
		{
			r = hash_data(data, datalen, sbuf, SC_ALGORITHM_ECDSA_HASH_SHA1);
			LOG_TEST_RET(card->ctx, r, "hash_data failed"); 
			sc_format_apdu(card, &apdu, SC_APDU_CASE_3,0x2A, 0x9E, 0x9A);
			apdu.data = sbuf;
			apdu.lc = 0x14;
			apdu.datalen = 0x14;
		}
		else if (exdata->ecAlgFlags & SC_ALGORITHM_ECDSA_HASH_SHA256)
		{
			r = hash_data(data, datalen, sbuf, SC_ALGORITHM_ECDSA_HASH_SHA256);
			LOG_TEST_RET(card->ctx, r, "hash_data failed");
			sc_format_apdu(card, &apdu, SC_APDU_CASE_3,0x2A, 0x9E, 0x9A);
			apdu.data = sbuf;
			apdu.lc = 0x20;
			apdu.datalen = 0x20;
		}
		else
		{
			return SC_ERROR_NOT_SUPPORTED;
		}
		apdu.resp = rbuf;
		apdu.resplen = sizeof(rbuf);
		apdu.le = 0;

		r = sc_transmit_apdu_t(card, &apdu);
		LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
		if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
			size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
			memcpy(out, apdu.resp, len);
			LOG_FUNC_RETURN(card->ctx, len);
		}
		LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
	}
	else if(exdata->currAlg == SC_ALGORITHM_RSA)
	{
		sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86);
		apdu.resp = rbuf;
		apdu.resplen = sizeof(rbuf);
		apdu.le = 0;

		memcpy(sbuf, data, datalen);
		apdu.data = sbuf;
		apdu.lc = datalen;
		apdu.datalen = datalen;
	}
	else
	{
		sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86);
		apdu.resp = rbuf;
		apdu.resplen = sizeof(rbuf);
		apdu.le = 256;

		memcpy(sbuf, data, datalen);
		apdu.data = sbuf;
		apdu.lc = datalen;
		apdu.datalen = datalen;
	}

	r = sc_transmit_apdu_t(card, &apdu);
	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");

	if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
		size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
		memcpy(out, apdu.resp, len);
		LOG_FUNC_RETURN(card->ctx, len);
	}

	LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
}

Project: OpenSC
File: card-muscle.c

static int muscle_card_verified_pins(sc_card_t *card, sc_cardctl_muscle_verified_pins_info_t *info)
{
	muscle_private_t* priv = MUSCLE_DATA(card);
	info->verifiedPins = priv->verifiedPins;
	return 0;
}

Project: OpenSC
File: card-cac.c

static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out, int type)
{
	struct sc_context *ctx;
	struct sc_apdu apdu;
	unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
	unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
	int r, pathlen, pathtype;
	struct sc_file *file = NULL;
	cac_private_data_t * priv = CAC_DATA(card);

	assert(card != NULL && in_path != NULL);
	ctx = card->ctx;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	memcpy(path, in_path->value, in_path->len);
	pathlen = in_path->len;
	pathtype = in_path->type;

	sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
		 "path->aid=%x %x %x %x %x %x %x  len=%"SC_FORMAT_LEN_SIZE_T"u, path->value = %x %x %x %x len=%"SC_FORMAT_LEN_SIZE_T"u path->type=%d (%x)",
		 in_path->aid.value[0], in_path->aid.value[1],
		 in_path->aid.value[2], in_path->aid.value[3],
		 in_path->aid.value[4], in_path->aid.value[5],
		 in_path->aid.value[6], in_path->aid.len, in_path->value[0],
		 in_path->value[1], in_path->value[2], in_path->value[3],
		 in_path->len, in_path->type, in_path->type);
	sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "file_out=%p index=%d count=%d\n",
		 file_out, in_path->index, in_path->count);

	/* Sigh, sc_key_select expects paths to keys to have specific formats. There is no override.
	 * we have to add some bytes to the path to make it happy. A better fix would be to give sc_key_file
	 * a flag that says 'no, really this path is fine'.  We only need to do this for private keys */
	if ((pathlen > 2) && (pathlen <= 4) && memcmp(path, "\x3F\x00", 2) == 0) {
		if (pathlen > 2) {
			path += 2;
			pathlen -= 2;
		}
	}


	/* CAC has multiple different type of objects that aren't PKCS #15. When we read
	 * them we need convert them to something PKCS #15 would understand. Find the object
	 * and object type here:
	 */
	if (priv) { /* don't record anything if we haven't been initialized yet */
		priv->object_type = CAC_OBJECT_TYPE_GENERIC;
		if (cac_is_cert(priv, in_path)) {
			priv->object_type = CAC_OBJECT_TYPE_CERT;
		}

		/* forget any old cached values */
		if (priv->cache_buf) {
			free(priv->cache_buf);
			priv->cache_buf = NULL;
		}
		priv->cache_buf_len = 0;
		priv->cached = 0;
	}

	if (in_path->aid.len) {
		if (!pathlen) {
			memcpy(path, in_path->aid.value, in_path->aid.len);
			pathlen = in_path->aid.len;
			pathtype = SC_PATH_TYPE_DF_NAME;
		} else {
			/* First, select the application */
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"select application" );
			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
			apdu.data = in_path->aid.value;
			apdu.datalen = in_path->aid.len;
			apdu.lc = in_path->aid.len;

			r = sc_transmit_apdu(card, &apdu);
			LOG_TEST_RET(ctx, r, "APDU transmit failed");
			r = sc_check_sw(card, apdu.sw1, apdu.sw2);
			if (r)
				LOG_FUNC_RETURN(ctx, r);

		}
	}

	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);

	switch (pathtype) {
	/* ideally we would had SC_PATH_TYPE_OBJECT_ID and add code to the iso7816 select.
	 * Unfortunately we'd also need to update the caching code as well. For now just
	 * use FILE_ID and change p1 here */
	case SC_PATH_TYPE_FILE_ID:
		apdu.p1 = 2;
		if (pathlen != 2)
			return SC_ERROR_INVALID_ARGUMENTS;
		break;
	case SC_PATH_TYPE_DF_NAME:
		apdu.p1 = 4;
		break;
	default:
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
	}
	apdu.lc = pathlen;
	apdu.data = path;
	apdu.datalen = pathlen;
	apdu.resp = buf;
	apdu.resplen = sizeof(buf);
	apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;

	if (file_out != NULL) {
		apdu.p2 = 0;		/* first record, return FCI */
	}
	else {
		apdu.p2 = 0x0C;
	}

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

	if (file_out == NULL) {
		/* For some cards 'SELECT' can be only with request to return FCI/FCP. */
		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
		if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
			apdu.p2 = 0x00;
			apdu.resplen = sizeof(buf);
			if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
				r = sc_check_sw(card, apdu.sw1, apdu.sw2);
		}
		if (apdu.sw1 == 0x61)
			LOG_FUNC_RETURN(ctx, SC_SUCCESS);
		LOG_FUNC_RETURN(ctx, r);
	}

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	if (r)
		LOG_FUNC_RETURN(ctx, r);

	/* This needs to come after the applet selection */
	if (priv && in_path->len >= 2) {
		/* get applet properties to know if we can treat the
		 * buffer as SimpleLTV and if we have PKI applet.
		 *
		 * Do this only if we select applets for reading
		 * (not during driver initialization)
		 */
		cac_properties_t prop;
		size_t i = -1;

		r = cac_get_properties(card, &prop);
		if (r == SC_SUCCESS) {
			for (i = 0; i < prop.num_objects; i++) {
				sc_log(card->ctx, "Searching for our OID: 0x%02x 0x%02x = 0x%02x 0x%02x",
				    prop.objects[i].oid[0], prop.objects[i].oid[1],
					in_path->value[0], in_path->value[1]);
				if (memcmp(prop.objects[i].oid,
				    in_path->value, 2) == 0)
					break;
			}
		}
		if (i < prop.num_objects) {
			if (prop.objects[i].privatekey)
				priv->object_type = CAC_OBJECT_TYPE_CERT;
			else if (prop.objects[i].simpletlv == 0)
				priv->object_type = CAC_OBJECT_TYPE_TLV_FILE;
		}
	}

	/* CAC cards never return FCI, fake one */
	file = sc_file_new();
	if (file == NULL)
			LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
	file->path = *in_path;
	file->size = CAC_MAX_SIZE; /* we don't know how big, just give a large size until we can read the file */

	*file_out = file;
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);

}

Project: OpenSC
File: card-epass2003.c

epass2003_restore_security_env(struct sc_card *card, int se_num)
{
	LOG_FUNC_CALLED(card->ctx);
	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

Project: OpenSC
File: card-epass2003.c

get_external_key_maxtries(struct sc_card *card, unsigned char *maxtries)
{
	unsigned char maxcounter[2] = { 0 };
	static const sc_path_t file_path = {
		{0x3f, 0x00, 0x50, 0x15, 0x9f, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6,
		0,
		0,
		SC_PATH_TYPE_PATH,
		{{0}, 0}
	};
	int ret;

	ret = sc_select_file(card, &file_path, NULL);
	LOG_TEST_RET(card->ctx, ret, "select max counter file failed");

	ret = sc_read_binary(card, 0, maxcounter, 2, 0);
	LOG_TEST_RET(card->ctx, ret, "read max counter file failed");

	*maxtries = maxcounter[0];
	return SC_SUCCESS;
}

Project: OpenSC
File: util.c

void util_print_binary(FILE *f, const u8 *buf, int count)
{
	int i;

	for (i = 0; i < count; i++) {
		unsigned char c = buf[i];
		const char *format;
		if (!isprint(c))
			format = "\\x%02X";
		else
			format = "%c";
		fprintf(f, format, c);
	}
	(void) fflush(f);
}

Project: OpenSC
File: cryptoflex-tool.c

static int encode_public_key(RSA *rsa, u8 *key, size_t *keysize)
{
	u8 buf[1024], *p = buf;
	u8 bnbuf[256];
	int base = 0;
	int r;
	const BIGNUM *rsa_n, *rsa_e;

	switch (RSA_bits(rsa)) {
	case 512:
		base = 32;
		break;
	case 768:
		base = 48;
		break;
	case 1024:
		base = 64;
		break;
	case 2048:
		base = 128;
		break;
	}
	if (base == 0) {
		fprintf(stderr, "Key length invalid.\n");
		return 2;
	}
	*p++ = (5 * base + 7) >> 8;
	*p++ = (5 * base + 7) & 0xFF;
	*p++ = opt_key_num;

	RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
	r = bn2cf(rsa_n, bnbuf);
	if (r != 2*base) {
		fprintf(stderr, "Invalid public key.\n");
		return 2;
	}
	memcpy(p, bnbuf, 2*base);
	p += 2*base;

	memset(p, 0, base);
	p += base;

	memset(bnbuf, 0, 2*base);
	memcpy(p, bnbuf, 2*base);
	p += 2*base;
	r = bn2cf(rsa_e, bnbuf);
	memcpy(p, bnbuf, 4);
	p += 4;

	memcpy(key, buf, p - buf);
	*keysize = p - buf;

	return 0;
}

Project: OpenSC
File: card-epass2003.c

acl_to_ac_byte(struct sc_card *card, const struct sc_acl_entry *e)
{
	if (e == NULL)
		return SC_ERROR_OBJECT_NOT_FOUND;

	switch (e->method) {
	case SC_AC_NONE:
		LOG_FUNC_RETURN(card->ctx, EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_EVERYONE);
	case SC_AC_NEVER:
		LOG_FUNC_RETURN(card->ctx, EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_NOONE);
	default:
		LOG_FUNC_RETURN(card->ctx, EPASS2003_AC_MAC_NOLESS | EPASS2003_AC_USER);
	}

	LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
}

Project: OpenSC
File: card-cac.c

struct sc_card_driver * sc_get_cac_driver(void)
{
	return sc_get_driver();
}

Project: OpenSC
File: sc.c

int sc_file_valid(const sc_file_t *file) {
	if (file == NULL)
		return 0;
	return file->magic == SC_FILE_MAGIC;
}

Project: OpenSC
File: card-epass2003.c

openssl_dec(const EVP_CIPHER * cipher, const unsigned char *key, const unsigned char *iv,
		const unsigned char *input, size_t length, unsigned char *output)
{
	int r = SC_ERROR_INTERNAL;
	EVP_CIPHER_CTX * ctx = NULL;
	int outl = 0;
	int outl_tmp = 0;
	unsigned char iv_tmp[EVP_MAX_IV_LENGTH] = { 0 };

	memcpy(iv_tmp, iv, EVP_MAX_IV_LENGTH);
	ctx = EVP_CIPHER_CTX_new();
	if (ctx == NULL)
		goto out;
	EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv_tmp);
	EVP_CIPHER_CTX_set_padding(ctx, 0);

	if (!EVP_DecryptUpdate(ctx, output, &outl, input, length))
		goto out;

	if (!EVP_DecryptFinal_ex(ctx, output + outl, &outl_tmp))
		goto out;

	r = SC_SUCCESS;
out:
	if (ctx)
		EVP_CIPHER_CTX_free(ctx);
	return r;
}

Project: OpenSC
File: card-epass2003.c

epass2003_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
{
	int r;

	LOG_FUNC_CALLED(card->ctx);

	r = sc_transmit_apdu_t(card, apdu);
	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");

	return r;
}

Project: OpenSC
File: card-cac.c

static int cac_parse_properties_object(sc_card_t *card, u8 type,
    u8 *data, size_t data_len, cac_properties_object_t *object)
{
	size_t len;
	u8 *val, *val_end, tag;
	int parsed = 0;

	if (data_len < 11)
		return -1;

	/* Initilize: non-PKI applet */
	object->privatekey = 0;

	val = data;
	val_end = data + data_len;
	for (; val < val_end; val += len) {
		/* get the tag and the length */
		if (sc_simpletlv_read_tag(&val, val_end - val, &tag, &len) != SC_SUCCESS)
			break;

		switch (tag) {
		case CAC_TAG_OBJECT_ID:
			if (len != 2) {
				sc_log(card->ctx, "TAG: Object ID: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: Object ID = 0x%02x 0x%02x", val[0], val[1]);
			memcpy(&object->oid, val, 2);
			parsed++;
			break;

		case CAC_TAG_BUFFER_PROPERTIES:
			if (len != 5) {
				sc_log(card->ctx, "TAG: Buffer Properties: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			/* First byte is "Type of Tag Supported" */
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: Buffer Properties: Type of Tag Supported = 0x%02x",
			    val[0]);
			object->simpletlv = val[0];
			parsed++;
			break;

		case CAC_TAG_PKI_PROPERTIES:
			/* 4th byte is "Private Key Initialized" */
			if (len != 4) {
				sc_log(card->ctx, "TAG: PKI Properties: "
				    "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
				break;
			}
			if (type != CAC_TAG_PKI_OBJECT) {
				sc_log(card->ctx, "TAG: PKI Properties outside of PKI Object");
				break;
			}
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: PKI Properties: Private Key Initialized = 0x%02x",
			    val[2]);
			object->privatekey = val[2];
			parsed++;
			break;

		default:
			/* ignore tags we don't understand */
			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
			    "TAG: Unknown (0x%02x)",tag );
			break;
		}
	}
	if (parsed < 2)
		return SC_ERROR_INVALID_DATA;

	return SC_SUCCESS;
}

Project: OpenSC
File: pkcs15-gemsafeV1.c

sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
		const char *label, void *data,
		const sc_pkcs15_id_t *auth_id, int obj_flags)
{
	sc_pkcs15_object_t *obj;
	int		df_type;

	obj = calloc(1, sizeof(*obj));

	obj->type  = type;
	obj->data  = data;

	if (label)
		strncpy(obj->label, label, sizeof(obj->label)-1);

	obj->flags = obj_flags;
	if (auth_id)
		obj->auth_id = *auth_id;

	switch (type & SC_PKCS15_TYPE_CLASS_MASK) {
	case SC_PKCS15_TYPE_AUTH:
		df_type = SC_PKCS15_AODF;
		break;
	case SC_PKCS15_TYPE_PRKEY:
		df_type = SC_PKCS15_PRKDF;
		break;
	case SC_PKCS15_TYPE_PUBKEY:
		df_type = SC_PKCS15_PUKDF;
		break;
	case SC_PKCS15_TYPE_CERT:
		df_type = SC_PKCS15_CDF;
		break;
	default:
		sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type);
		free(obj);
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	obj->df = sc_pkcs15emu_get_df(p15card, df_type);
	sc_pkcs15_add_object(p15card, obj);

	return 0;
}

Project: OpenSC
File: card-cac.c

static int cac_parse_cardurl(sc_card_t *card, cac_private_data_t *priv, cac_card_url_t *val, int len)
{
	cac_object_t new_object;
	const cac_object_t *obj;
	unsigned short object_id;
	int r;

	r = cac_path_from_cardurl(card, &new_object.path, val, len);
	if (r != SC_SUCCESS) {
		return r;
	}
	switch (val->cardApplicationType) {
	case CAC_APP_TYPE_PKI:
		/* we don't want to overflow the cac_label array. This test could
		 * go way if we create a label function that will create a unique label
		 * from a cert index.
		 */
		if (priv->cert_next >= MAX_CAC_SLOTS)
			break; /* don't fail just because we have more certs than we can support */
		new_object.name = cac_labels[priv->cert_next];
		new_object.fd = priv->cert_next+1;
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: pki_object found, cert_next=%d (%s),", priv->cert_next, new_object.name);
		cac_add_object_to_list(&priv->pki_list, &new_object);
		priv->cert_next++;
		break;
	case CAC_APP_TYPE_GENERAL:
		object_id = bebytes2ushort(val->objectID);
		obj = cac_find_obj_by_id(object_id);
		if (obj == NULL)
			break; /* don't fail just because we don't recognize the object */
		new_object.name = obj->name;
		new_object.fd = 0;
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: gen_object found, objectID=%x (%s),", object_id, new_object.name);
		cac_add_object_to_list(&priv->general_list, &new_object);
		break;
	case CAC_APP_TYPE_SKI:
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: ski_object found");
	break;
	default:
		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: unknown object_object found (type=0x%02x)", val->cardApplicationType);
		/* don't fail just because there is an unknown object in the CCC */
		break;
	}
	return SC_SUCCESS;
}

Project: OpenSC
File: sc.c

int sc_path_print(char *buf, size_t buflen, const sc_path_t *path)
{
	size_t i;

	if (buf == NULL || path == NULL)
		return SC_ERROR_INVALID_ARGUMENTS;

	if (buflen < path->len * 2 + path->aid.len * 2 + 1)
		return SC_ERROR_BUFFER_TOO_SMALL;

	buf[0] = '\0';
	if (path->aid.len)   {
		for (i = 0; i < path->aid.len; i++)
			snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->aid.value[i]);
		snprintf(buf + strlen(buf), buflen - strlen(buf), "::");
	}

	for (i = 0; i < path->len; i++)
		snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->value[i]);
	if (!path->aid.len && path->type == SC_PATH_TYPE_DF_NAME)
		snprintf(buf + strlen(buf), buflen - strlen(buf), "::");

	return SC_SUCCESS;
}

Project: OpenSC
File: sc.c

int sc_file_set_content(sc_file_t *file, const u8 *content,
			 size_t content_len)
{
	u8 *tmp;
	if (!sc_file_valid(file)) {
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	if (content == NULL) {
		if (file->encoded_content != NULL)
			free(file->encoded_content);
		file->encoded_content = NULL;
		file->encoded_content_len = 0;
		return SC_SUCCESS;
	}

	tmp = (u8 *) realloc(file->encoded_content, content_len);
	if (!tmp) {
		if (file->encoded_content)
			free(file->encoded_content);
		file->encoded_content = NULL;
		file->encoded_content_len = 0;
		return SC_ERROR_OUT_OF_MEMORY;
	}

	file->encoded_content = tmp;
	memcpy(file->encoded_content, content, content_len);
	file->encoded_content_len = content_len;

	return SC_SUCCESS;
}

Project: OpenSC
File: card-muscle.c

static int muscle_decipher(sc_card_t * card,
			 const u8 * crgram, size_t crgram_len, u8 * out,
			 size_t out_len)
{
	muscle_private_t* priv = MUSCLE_DATA(card);

	u8 key_id;
	int r;

	/* sanity check */
	if (priv->env.operation != SC_SEC_OPERATION_DECIPHER)
		return SC_ERROR_INVALID_ARGUMENTS;

	key_id = priv->rsa_key_ref * 2; /* Private key */

	if (out_len < crgram_len) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Output buffer too small");
		return SC_ERROR_BUFFER_TOO_SMALL;
	}

	r = msc_compute_crypt(card,
		key_id,
		0x00, /* RSA NO PADDING */
		0x04, /* decrypt */
		crgram,
		out,
		crgram_len,
		out_len);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Card signature failed");
	return r;
}

Project: OpenSC
File: pkcs15-sc-hsm.c

static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey)
{
	struct sc_ec_parameters *ecp;
	const struct sc_lv_data *oid;
	int r;

	pubkey->algorithm = SC_ALGORITHM_EC;

	r = sc_pkcs15emu_sc_hsm_get_curve_oid(cvc, &oid);
	if (r != SC_SUCCESS)
		return r;

	ecp = calloc(1, sizeof(struct sc_ec_parameters));
	if (!ecp)
		return SC_ERROR_OUT_OF_MEMORY;

	ecp->der.len = oid->len + 2;
	ecp->der.value = calloc(ecp->der.len, 1);
	if (!ecp->der.value) {
		free(ecp);
		return SC_ERROR_OUT_OF_MEMORY;
	}

	*(ecp->der.value + 0) = 0x06;
	*(ecp->der.value + 1) = (u8)oid->len;
	memcpy(ecp->der.value + 2, oid->value, oid->len);
	ecp->type = 1;		// Named curve

	pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id));
	if (!pubkey->alg_id) {
		free(ecp->der.value);
		free(ecp);
		return SC_ERROR_OUT_OF_MEMORY;
	}

	pubkey->alg_id->algorithm = SC_ALGORITHM_EC;
	pubkey->alg_id->params = ecp;

	pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen);
	if (!pubkey->u.ec.ecpointQ.value)
		return SC_ERROR_OUT_OF_MEMORY;
	memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen);
	pubkey->u.ec.ecpointQ.len = cvc->publicPointlen;

	pubkey->u.ec.params.der.value = malloc(ecp->der.len);
	if (!pubkey->u.ec.params.der.value)
		return SC_ERROR_OUT_OF_MEMORY;
	memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len);
	pubkey->u.ec.params.der.len = ecp->der.len;

	/* FIXME: check return value? */
	sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params);

	return SC_SUCCESS;
}

Project: OpenSC
File: pkcs15-sc-hsm.c

static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2],
		u8 *efbin, size_t *len, int optional)
{
	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 || !efbin
			|| 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);
		if (r < 0) {
			sc_log(p15card->card->ctx, "Could not select EF");
		} else {
			r = sc_read_binary(p15card->card, 0, efbin, *len, 0);
		}

		if (r < 0) {
			sc_log(p15card->card->ctx, "Could not read EF");
			if (!optional) {
				return r;
			}
			/* optional files are saved as empty files to avoid card
			 * transactions. Parsing the file's data will reveal that they were
			 * missing. */
			*len = 0;
		} else {
			*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;
}

Project: OpenSC
File: card-epass2003.c

construct_le_tlv(struct sc_apdu *apdu, unsigned char *apdu_buf, size_t data_tlv_len,
		unsigned char *le_tlv, size_t * le_tlv_len, const unsigned char key_type)
{
	size_t block_size = (KEY_TYPE_AES == key_type ? 16 : 8);

	*(apdu_buf + block_size + data_tlv_len) = 0x97;
	if (apdu->le > 0x7F) {
		/* Le' > 0x7E, use extended APDU */
		*(apdu_buf + block_size + data_tlv_len + 1) = 2;
		*(apdu_buf + block_size + data_tlv_len + 2) = (unsigned char)(apdu->le / 0x100);
		*(apdu_buf + block_size + data_tlv_len + 3) = (unsigned char)(apdu->le % 0x100);
		memcpy(le_tlv, apdu_buf + block_size + data_tlv_len, 4);
		*le_tlv_len = 4;
	}
	else {
		*(apdu_buf + block_size + data_tlv_len + 1) = 1;
		*(apdu_buf + block_size + data_tlv_len + 2) = (unsigned char)apdu->le;
		memcpy(le_tlv, apdu_buf + block_size + data_tlv_len, 3);
		*le_tlv_len = 3;
	}
	return 0;
}

Project: OpenSC
File: pkcs15-gemsafeV1.c

sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type)
{
	sc_pkcs15_df_t	*df;
	sc_file_t	*file;
	int		created = 0;

	while (1) {
		for (df = p15card->df_list; df; df = df->next) {
			if (df->type == type) {
				if (created)
					df->enumerated = 1;
				return df;
			}
		}

		assert(created == 0);

		file = sc_file_new();
		if (!file)
			return NULL;
		sc_format_path("11001101", &file->path);
		sc_pkcs15_add_df(p15card, type, &file->path);
		sc_file_free(file);
		created++;
	}
}