/*
 * Add a key and the key description in PKCS#15 format to the framework
 */
static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) {

	sc_card_t *card = p15card->card;
	sc_pkcs15_cert_info_t cert_info;
	sc_pkcs15_object_t cert_obj;
	struct sc_pkcs15_object prkd;
	sc_pkcs15_prkey_info_t *key_info;
	sc_path_t path;
	u8 fid[2];
	u8 efbin[512];
	u8 *ptr;
	size_t len;
	int r;

	fid[0] = PRKD_PREFIX;
	fid[1] = keyid;

	/* Try to select a related EF containing the PKCS#15 description of the key */
	sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0);
	r = sc_select_file(card, &path, NULL);

	if (r != SC_SUCCESS) {
		return SC_SUCCESS;
	}

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

	memset(&prkd, 0, sizeof(prkd));
	ptr = efbin;
	len = r;

	r = sc_pkcs15_decode_prkdf_entry(p15card, &prkd, (const u8 **)&ptr, &len);
	LOG_TEST_RET(card->ctx, r, "Could not decode EF.PRKD");

	/* All keys require user PIN authentication */
	prkd.auth_id.len = 1;
	prkd.auth_id.value[0] = 1;

	/*
	 * Set private key flag as all keys are private anyway
	 */
	prkd.flags |= SC_PKCS15_CO_FLAG_PRIVATE;

	key_info = (sc_pkcs15_prkey_info_t *)prkd.data;
	key_info->key_reference = keyid;

	if (prkd.type == SC_PKCS15_TYPE_PRKEY_RSA) {
		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkd, key_info);
	} else {
		r = sc_pkcs15emu_add_ec_prkey(p15card, &prkd, key_info);
	}

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

	/* Check if we also have a certificate for the private key */
	fid[0] = EE_CERTIFICATE_PREFIX;

	sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0);
	r = sc_select_file(card, &path, NULL);

	if (r != SC_SUCCESS) {
		return SC_SUCCESS;
	}

	/* Check if the certificate is a X.509 certificate */
	r = sc_read_binary(p15card->card, 0, efbin, 1, 0);

	if (r < 0) {
		return SC_SUCCESS;
	}

	if (efbin[0] == 0x67) {		/* Decode CSR and create public key object */
		sc_pkcs15emu_sc_hsm_add_pubkey(p15card, key_info, prkd.label);
		return SC_SUCCESS;		/* Ignore any errors */
	}

	if (efbin[0] != 0x30) {
		return SC_SUCCESS;
	}

	memset(&cert_info, 0, sizeof(cert_info));
	memset(&cert_obj, 0, sizeof(cert_obj));

	cert_info.id = key_info->id;
	cert_info.path = path;
	cert_info.path.count = -1;

	strlcpy(cert_obj.label, prkd.label, sizeof(cert_obj.label));
	r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
	LOG_TEST_RET(card->ctx, r, "Could not add certificate");

	return SC_SUCCESS;
}
Beispiel #2
0
int do_genkey(sc_card_t *card, u8 in_key_id, const char *keytype)
{
	int r;
	sc_cardctl_openpgp_keygen_info_t key_info;
	u8 fingerprints[60];
	sc_path_t path;
	sc_file_t *file;

	/* validate in_key_id */
	if (in_key_id < 1 || in_key_id > 3) {
		util_error("unknown key ID %d", in_key_id);
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	/* fall back to RSA 2048 if keytype is not given */
	if (!keytype)
		keytype = "RSA2048";

	memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t));

	/* generate key depending on keytype passed */
	if (strncasecmp("RSA", keytype, strlen("RSA")) == 0) {
		size_t keylen = 2048;	/* default length for RSA keys */
		const char *keylen_ptr = keytype + strlen("RSA");

		/* try to get key length from keytype, e.g. "rsa3072" -> 3072 */
		if (strlen(keylen_ptr) > 0) {
			if (strspn(keylen_ptr, "0123456789") == strlen(keylen_ptr) &&
			    atol(keylen_ptr) >= 1024 && atol(keylen_ptr) <= 4096) {
				keylen = atol(keylen_ptr);
			}
			else {
				util_error("illegal key type: %s", keytype);
				return EXIT_FAILURE;
			}
		}

		/* set key_info */
		key_info.key_id = in_key_id;
		key_info.algorithm = SC_OPENPGP_KEYALGO_RSA;
		key_info.u.rsa.modulus_len = keylen;
		key_info.u.rsa.modulus = malloc(BYTES4BITS(keylen));

		r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info);
		free(key_info.u.rsa.modulus);
		if (r < 0) {
			util_error("failed to generate key: %s", sc_strerror(r));
			return EXIT_FAILURE;
		}
	}
	else {
		//TODO: deal with EC keys
		util_error("Generating non-RSA keys is not yet implemented");
		return EXIT_FAILURE;
	}

	sc_format_path("006E007300C5", &path);
	r = sc_select_file(card, &path, &file);
	if (r < 0) {
		util_error("failed to retrieve fingerprints: %s", sc_strerror(r));
		return EXIT_FAILURE;
	}
	r = sc_read_binary(card, 0, fingerprints, 60, 0);
	if (r < 0) {
		util_error("failed to retrieve fingerprints: %s", sc_strerror(r));
		return EXIT_FAILURE;
	}
	printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(in_key_id - 1), 20));

	return EXIT_SUCCESS;
}
Beispiel #3
0
static int
sc_pkcs15emu_oberthur_init(struct sc_pkcs15_card * p15card)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_auth_info auth_info;
	struct sc_pkcs15_object   obj;
	struct sc_card *card = p15card->card;
	struct sc_path path;
	int rv, ii, tries_left;
	char serial[0x10];
	unsigned char sopin_reference = 0x04;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
	sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial, sizeof(serial), 0);
	p15card->tokeninfo->serial_number = strdup(serial);

	p15card->ops.parse_df = sc_awp_parse_df;
	p15card->ops.clear = sc_awp_clear;

	sc_log(ctx, "Oberthur init: serial %s", p15card->tokeninfo->serial_number);

	sc_format_path(AWP_PIN_DF, &path);
	rv = sc_select_file(card, &path, NULL);
	LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot select PIN dir");

	tries_left = -1;
	rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
	if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT)   {
		sopin_reference = 0x84;
		rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
	}
	if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT)
		LOG_TEST_RET(ctx, rv, "Invalid state of SO-PIN");

	/* add PIN */
	memset(&auth_info, 0, sizeof(auth_info));
	memset(&obj,  0, sizeof(obj));

	auth_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
	auth_info.auth_method	= SC_AC_CHV;
	auth_info.auth_id.len = 1;
	auth_info.auth_id.value[0] = 0xFF;
	auth_info.attrs.pin.min_length		= 4;
	auth_info.attrs.pin.max_length		= 64;
	auth_info.attrs.pin.stored_length	= 64;
	auth_info.attrs.pin.type		= SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
	auth_info.attrs.pin.reference		= sopin_reference;
	auth_info.attrs.pin.pad_char		= 0xFF;
	auth_info.attrs.pin.flags		= SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
				| SC_PKCS15_PIN_FLAG_INITIALIZED
				| SC_PKCS15_PIN_FLAG_NEEDS_PADDING
				| SC_PKCS15_PIN_FLAG_SO_PIN;
	auth_info.tries_left		= tries_left;
	auth_info.logged_in = SC_PIN_STATE_UNKNOWN;

	strncpy(obj.label, "SO PIN", SC_PKCS15_MAX_LABEL_SIZE-1);
	obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;

	sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
			sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
	rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
	LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object");

	tries_left = -1;
	rv = sc_verify(card, SC_AC_CHV, 0x81, (unsigned char *)"", 0, &tries_left);
	if (rv == SC_ERROR_PIN_CODE_INCORRECT)   {
		/* add PIN */
		memset(&auth_info, 0, sizeof(auth_info));
		memset(&obj,  0, sizeof(obj));

		auth_info.auth_id.len = sizeof(PinDomainID) > sizeof(auth_info.auth_id.value)
				? sizeof(auth_info.auth_id.value) : sizeof(PinDomainID);
		memcpy(auth_info.auth_id.value, PinDomainID, auth_info.auth_id.len);
		auth_info.auth_method	= SC_AC_CHV;

		auth_info.attrs.pin.min_length		= 4;
		auth_info.attrs.pin.max_length		= 64;
		auth_info.attrs.pin.stored_length	= 64;
		auth_info.attrs.pin.type		= SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
		auth_info.attrs.pin.reference		= 0x81;
		auth_info.attrs.pin.pad_char		= 0xFF;
		auth_info.attrs.pin.flags		= SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
					| SC_PKCS15_PIN_FLAG_INITIALIZED
					| SC_PKCS15_PIN_FLAG_NEEDS_PADDING
					| SC_PKCS15_PIN_FLAG_LOCAL;
		auth_info.tries_left		= tries_left;

		strncpy(obj.label, PIN_DOMAIN_LABEL, SC_PKCS15_MAX_LABEL_SIZE-1);
		obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
		if (sopin_reference == 0x84) {
			/*
			 * auth_pin_reset_oberthur_style() in card-oberthur.c
			 * always uses PUK with reference 0x84 for
			 * unblocking of User PIN
			 */
			obj.auth_id.len = 1;
			obj.auth_id.value[0] = 0xFF;
		}

		sc_format_path(AWP_PIN_DF, &auth_info.path);
		auth_info.path.type = SC_PATH_TYPE_PATH;

		sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
				sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
		rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
		LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object");
	}
	else if (rv != SC_ERROR_DATA_OBJECT_NOT_FOUND)    {
		LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot verify PIN");
	}

	for (ii=0; oberthur_infos[ii].name; ii++)   {
		sc_log(ctx, "Oberthur init: read %s file", oberthur_infos[ii].name);
		rv = sc_oberthur_read_file(p15card, oberthur_infos[ii].path,
				&oberthur_infos[ii].content, &oberthur_infos[ii].len, 1);
		LOG_TEST_RET(ctx, rv, "Oberthur init failed: read oberthur file error");

		sc_log(ctx,
		       "Oberthur init: parse %s file, content length %"SC_FORMAT_LEN_SIZE_T"u",
		       oberthur_infos[ii].name, oberthur_infos[ii].len);
		rv = oberthur_infos[ii].parser(p15card, oberthur_infos[ii].content, oberthur_infos[ii].len,
				oberthur_infos[ii].postpone_allowed);
		LOG_TEST_RET(ctx, rv, "Oberthur init failed: parse error");
	}

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
Beispiel #4
0
int main(int argc, char * const argv[])
{
	int r, c, long_optind = 0, err = 0;
	char *line;
	int cargc;
	char *cargv[260];
	sc_context_param_t ctx_param;
	int lcycle = SC_CARDCTRL_LIFECYCLE_ADMIN;
	FILE *script = stdin;

	printf("OpenSC Explorer version %s\n", sc_get_version());

	while (1) {
		c = getopt_long(argc, argv, "r:c:vwm:", options, &long_optind);
		if (c == -1)
			break;
		if (c == '?')
			util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]");
		switch (c) {
		case 'r':
			opt_reader = optarg;
			break;
		case 'c':
			opt_driver = optarg;
			break;
		case 'w':
			opt_wait = 1;
			break;
		case 'v':
			verbose++;
			break;
		case 'm':
			opt_startfile = optarg;
			break;
		}
	}

	memset(&ctx_param, 0, sizeof(ctx_param));
	ctx_param.ver      = 0;
	ctx_param.app_name = app_name;

	r = sc_context_create(&ctx, &ctx_param);
	if (r) {
		fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
		return 1;
	}

	ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;

	if (verbose > 1) {
		ctx->debug = verbose;
		ctx->debug_file = stderr;
        }

	if (opt_driver != NULL) {
		err = sc_set_card_driver(ctx, opt_driver);
		if (err) {
			fprintf(stderr, "Driver '%s' not found!\n", opt_driver);
			err = 1;
			goto end;
		}
	}

	err = util_connect_card(ctx, &card, opt_reader, opt_wait, 0);
	if (err)
		goto end;

	if (opt_startfile) {
		if(*opt_startfile) {
			char startpath[1024];
			char *args[] = { startpath };

			strncpy(startpath, opt_startfile, sizeof(startpath)-1);
			r = do_cd(1, args);
			if (r) {
				printf("unable to select file %s: %s\n",
					opt_startfile, sc_strerror(r));
				return -1;
			}
		}
	} else {
		sc_format_path("3F00", &current_path);
		r = sc_select_file(card, &current_path, &current_file);
		if (r) {
			printf("unable to select MF: %s\n", sc_strerror(r));
			return 1;
		}
	}

	r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle);
	if (r && r != SC_ERROR_NOT_SUPPORTED)
		printf("unable to change lifecycle: %s\n", sc_strerror(r));

	switch (argc - optind) {
	default:
		util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]");
		break;
	case 0:
		script = stdin;
		break;
	case 1:
		if (strcmp(argv[optind], "-") == 0) {
			script = stdin;
		}
		else if ((script = fopen(argv[optind], "r")) == NULL) {
			util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]");
		}
		break;
	}

	while (!feof(script)) {
		struct command *cmd;
		char prompt[3*SC_MAX_PATH_STRING_SIZE];

		sprintf(prompt, "OpenSC [%s]> ", path_to_filename(&current_path, '/'));
		line = read_cmdline(script, prompt);
		if (line == NULL)
			break;
		cargc = parse_cmdline(line, cargv, DIM(cargv));
		if ((cargc < 1) || (*cargv[0] == '#'))
			continue;
		for (r=cargc; r < (int)DIM(cargv); r++)
			cargv[r] = "";
		cmd = ambiguous_match(cmds, cargv[0]);
		if (cmd == NULL) {
			do_help(0, NULL);
		} else {
			cmd->func(cargc-1, cargv+1);
		}
	}
end:
	die(err);

	return 0; /* not reached */
}
Beispiel #5
0
static int do_cat(int argc, char **argv)
{
	int r, err = 1;
	sc_path_t path;
	sc_file_t *file = NULL;
	int not_current = 1;
	int sfi = 0;

	if (argc > 1)
		return usage(do_cat);

	if (!argc) {
		path = current_path;
		file = current_file;
		not_current = 0;
	} else {
		const char sfi_prefix[] = "sfi:";

		if (strncasecmp(argv[0], sfi_prefix, strlen(sfi_prefix)) == 0) {
			const char *sfi_n = argv[0] + strlen(sfi_prefix);

			if(!current_file) {
				printf("A DF must be selected to read by SFI\n");
				goto err;
			}
			path = current_path;
			file = current_file;
			not_current = 0;
			sfi = atoi(sfi_n);
			if ((sfi < 1) || (sfi > 30)) {
				printf("Invalid SFI: %s\n", sfi_n);
				return usage(do_cat);
			}
		} else {
			if (arg_to_path(argv[0], &path, 0) != 0)
				return usage(do_cat);

			r = sc_select_file(card, &path, &file);
			if (r) {
				check_ret(r, SC_AC_OP_SELECT, "unable to select file",
					current_file);
				goto err;
			}
		}
	}
	if (file->type != SC_FILE_TYPE_WORKING_EF &&
		!(file->type == SC_FILE_TYPE_DF && sfi)) {
		printf("only working EFs may be read\n");
		goto err;
	}
	if (file->ef_structure == SC_FILE_EF_TRANSPARENT && !sfi)
		read_and_util_print_binary_file(file);
	else
		read_and_print_record_file(file, sfi);

	err = 0;
err:
	if (not_current) {
		if (file != NULL)
			sc_file_free(file);
		select_current_path_or_die();
	}

	return -err;
}
Beispiel #6
0
/*
 * Key generation
 */
static int
incrypto34_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
		sc_pkcs15_object_t *obj,
		sc_pkcs15_pubkey_t *pubkey)
{
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	sc_card_t *card = p15card->card;
	struct sc_pkcs15_prkey_rsa key_obj;
	struct sc_cardctl_incrypto34_genkey_info args;
	struct sc_file	*temp;
	u8		abignum[RSAKEY_MAX_SIZE];
	unsigned int	keybits;
	int		algorithm, r, delete_it = 0;

	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Incrypto34 supports only RSA keys.");
		return SC_ERROR_NOT_SUPPORTED;
	}

	if (incrypto34_key_algorithm(key_info->usage, &algorithm) < 0) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Incrypto34 does not support keys "
			       "that can both sign _and_ decrypt.");
		return SC_ERROR_NOT_SUPPORTED;
	}

	keybits = key_info->modulus_length & ~7UL;
	if (keybits > RSAKEY_MAX_BITS) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to generate key, max size is %d",
				RSAKEY_MAX_BITS);
		return SC_ERROR_INVALID_ARGUMENTS;
	}

	if (sc_profile_get_file(profile, "tempfile", &temp) < 0) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Profile doesn't define temporary file "
				"for key generation.");
		return SC_ERROR_NOT_SUPPORTED;
	}
	memset(pubkey, 0, sizeof(*pubkey));

	if ((r = sc_pkcs15init_create_file(profile, p15card, temp)) < 0)
		goto out;
	delete_it = 1;

	/* Create a key object, initializing components to 0xff */
	memset(&key_obj, 0, sizeof(key_obj));
	memset(abignum, 0xFF, sizeof(abignum));
	key_obj.modulus.data = abignum;
	key_obj.modulus.len = keybits >> 3;
	key_obj.d.data = abignum;
	key_obj.d.len = keybits >> 3;
	r = incrypto34_put_key(profile, p15card, algorithm, key_info, &key_obj);
	if (r < 0)
		goto out;

	memset(&args, 0, sizeof(args));
	args.key_id = key_info->key_reference;
	args.key_bits = keybits;
	args.fid = temp->id;
	r = sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_GENERATE_KEY, &args);
	if (r < 0)
		goto out;

	/* extract public key from file and delete it */
	if ((r = sc_select_file(card, &temp->path, NULL)) < 0)
		goto out;
	r = incrypto34_extract_pubkey(card, 1, 0x10, &pubkey->u.rsa.modulus);
	if (r < 0)
		goto out;
	r = incrypto34_extract_pubkey(card, 2, 0x11, &pubkey->u.rsa.exponent);
	if (r < 0)
		goto out;
	pubkey->algorithm = SC_ALGORITHM_RSA;

out:	if (delete_it) {
		sc_pkcs15init_rmdir(p15card, profile, temp);
	}
	sc_file_free(temp);
	if (r < 0) {
		if (pubkey->u.rsa.modulus.data)
			free (pubkey->u.rsa.modulus.data);
		if (pubkey->u.rsa.exponent.data)
			free (pubkey->u.rsa.exponent.data);
	}
	return r;
}
Beispiel #7
0
static int do_put(int argc, char **argv)
{
	u8 buf[256];
	int r, err = 1;
	size_t count = 0;
	unsigned int idx = 0;
	sc_path_t path;
	sc_file_t *file = NULL;
	const char *filename;
	FILE *outf = NULL;

	if (argc < 1 || argc > 2)
		return usage(do_put);
	if (arg_to_path(argv[0], &path, 0) != 0)
		return usage(do_put);

	filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_');
	outf = fopen(filename, "rb");
	if (outf == NULL) {
		perror(filename);
		goto err;
	}
	r = sc_select_file(card, &path, &file);
	if (r) {
		check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
		goto err;
	}
	count = file->size;
	while (count) {
		int c = count > sizeof(buf) ? sizeof(buf) : count;

		r = fread(buf, 1, c, outf);
		if (r < 0) {
			perror("fread");
			goto err;
		}
		if (r != c)
			count = c = r;
		r = sc_update_binary(card, idx, buf, c, 0);
		if (r < 0) {
			check_ret(r, SC_AC_OP_READ, "update failed", file);
			goto err;
		}
		if (r != c) {
			printf("expecting %d, wrote only %d bytes.\n", c, r);
			goto err;
		}
		idx += c;
		count -= c;
	}
	printf("Total of %d bytes written.\n", idx);

	err = 0;
err:
	if (file)
		sc_file_free(file);
	if (outf)
		fclose(outf);
	select_current_path_or_die();
	return -err;
}
Beispiel #8
0
static int detect_netkey(
	sc_pkcs15_card_t *p15card
){
	sc_card_t *card=p15card->card;
	sc_path_t p;
	sc_file_t *f;
	int keylen;
	char dir[10];
	const char *c_auth;

	/* NKS-Applikation ? */
	memset(&p, 0, sizeof(sc_path_t));
	p.type=SC_PATH_TYPE_DF_NAME;
	memcpy(p.value, "\xD2\x76\x00\x00\x03\x01\x02", p.len=7);
	if (sc_select_file(card,&p,&f)!=SC_SUCCESS) return 1;
	sprintf(dir,"%04X", f->id);
	sc_file_free(f);

	p15card->tokeninfo->manufacturer_id = strdup("TeleSec GmbH");
	p15card->tokeninfo->label = strdup(card->type==SC_CARD_TYPE_TCOS_V3 ? "NetKey V3 Card" : "NetKey Card");
	keylen= card->type==SC_CARD_TYPE_TCOS_V3 ? 2048 : 1024;
	c_auth= card->type==SC_CARD_TYPE_TCOS_V3 ? "C500" : "C100";

	insert_cert(p15card, dirpath(dir,"4331"), 0x45, 1, "Signatur Zertifikat 1");
	insert_cert(p15card, dirpath(dir,"4332"), 0x45, 1, "Signatur Zertifikat 2");
	insert_cert(p15card, dirpath(dir,"C000"), 0x45, 0, "Telesec Signatur Zertifikat");
	insert_cert(p15card, dirpath(dir,"43B1"), 0x46, 1, "Verschluesselungs Zertifikat 1");
	insert_cert(p15card, dirpath(dir,"43B2"), 0x46, 1, "Verschluesselungs Zertifikat 2");
	insert_cert(p15card, dirpath(dir,"C200"), 0x46, 0, "Telesec Verschluesselungs Zertifikat");
	insert_cert(p15card, dirpath(dir,"4371"), 0x47, 1, "Authentifizierungs Zertifikat 1");
	insert_cert(p15card, dirpath(dir,"4372"), 0x47, 1, "Authentifizierungs Zertifikat 2");
	insert_cert(p15card, dirpath(dir,c_auth), 0x47, 0, "Telesec Authentifizierungs Zertifikat");
	insert_cert(p15card, dirpath(dir,"C201"), 0x48, 0, "Telesec 1024bit Zertifikat");

	insert_key(p15card, dirpath(dir,"5331"), 0x45, 0x80, keylen, 4, "Signatur Schluessel");
	insert_key(p15card, dirpath(dir,"53B1"), 0x46, 0x81, keylen, 3, "Verschluesselungs Schluessel");
	insert_key(p15card, dirpath(dir,"5371"), 0x47, 0x82, keylen, 3, "Authentifizierungs Schluessel");
	insert_key(p15card, dirpath(dir,"0000"), 0x48, 0x83, 1024,   3, "1024bit Schluessel");

	insert_pin(p15card, "5000", 1, 2, 0x00, 6, "PIN",
		SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED
	);
	insert_pin(p15card, "5001", 2, 0, 0x01, 8, "PUK",
		SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
		SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN
	);
	if(card->type==SC_CARD_TYPE_TCOS_V3){
		insert_pin(p15card, dirpath(dir,"0000"), 3, 1, 0x83, 6, "NetKey PIN2",
			SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
			SC_PKCS15_PIN_FLAG_INITIALIZED
		);
	} else {
		insert_pin(p15card, dirpath(dir,"5080"), 3, 1, 0x80, 6, "NetKey PIN0",
			SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
			SC_PKCS15_PIN_FLAG_INITIALIZED
		);
	}
	insert_pin(p15card, dirpath(dir,"5081"), 4, 1, 0x81, 6, "NetKey PIN1",
		SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
		SC_PKCS15_PIN_FLAG_INITIALIZED
	);

	/* SigG-Applikation */
	p.len=7; p.type=SC_PATH_TYPE_DF_NAME;
	memcpy(p.value, "\xD2\x76\x00\x00\x66\x01", p.len=6);
	if (sc_select_file(card,&p,&f)==SC_SUCCESS){
		sprintf(dir,"%04X", f->id);
		sc_file_free(f);

		insert_cert(p15card, dirpath(dir,"C000"), 0x49, 1, "SigG Zertifikat 1");
		insert_cert(p15card, dirpath(dir,"4331"), 0x49, 1, "SigG Zertifikat 2");
		insert_cert(p15card, dirpath(dir,"4332"), 0x49, 1, "SigG Zertifikat 3");
		
		if(card->type==SC_CARD_TYPE_TCOS_V3){
			insert_key(p15card, dirpath(dir,"0000"), 0x49, 0x84, 2048, 5, "SigG Schluessel");
		} else {
			insert_key(p15card, dirpath(dir,"5331"), 0x49, 0x80, 1024, 5, "SigG Schluessel");
		}

		insert_pin(p15card, dirpath(dir,"5081"), 5, 0, 0x81, 6, "SigG PIN",
			SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
			SC_PKCS15_PIN_FLAG_INITIALIZED
		);
		if(card->type==SC_CARD_TYPE_TCOS_V3){
			insert_pin(p15card, dirpath(dir,"0000"), 6, 0, 0x83, 8, "SigG PIN2",
				SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
				SC_PKCS15_PIN_FLAG_INITIALIZED
			);
		}
	}

	return 0;
}
Beispiel #9
0
static int insert_key(
	sc_pkcs15_card_t *p15card,
	const char       *path,
	unsigned char     id,
	unsigned char     key_reference,
	int               key_length,
	unsigned char     auth_id,
	const char       *label
){
	sc_card_t *card=p15card->card;
	sc_context_t *ctx=p15card->card->ctx;
	sc_file_t *f;
	struct sc_pkcs15_prkey_info prkey_info;
	struct sc_pkcs15_object prkey_obj;
	int r, can_sign, can_crypt;

	memset(&prkey_info, 0, sizeof(prkey_info));
	prkey_info.id.len         = 1;
	prkey_info.id.value[0]    = id;
	prkey_info.native         = 1;
	prkey_info.key_reference  = key_reference;
	prkey_info.modulus_length = key_length;
	sc_format_path(path, &prkey_info.path);

	memset(&prkey_obj, 0, sizeof(prkey_obj));
	strlcpy(prkey_obj.label, label, sizeof(prkey_obj.label));
	prkey_obj.flags            = SC_PKCS15_CO_FLAG_PRIVATE;
	prkey_obj.auth_id.len      = 1;
	prkey_obj.auth_id.value[0] = auth_id;

	can_sign=can_crypt=0;
	if(card->type==SC_CARD_TYPE_TCOS_V3){
		unsigned char buf[256];
		int i, rec_no=0;
		if(prkey_info.path.len>=2) prkey_info.path.len-=2;
		sc_append_file_id(&prkey_info.path, 0x5349);
		if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
				"Select(%s) failed\n",
				sc_print_path(&prkey_info.path));
			return 1;
		}
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
			"Searching for Key-Ref %02X\n", key_reference);
		while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){
			int found=0;
			if(buf[0]!=0xA0) continue;
			for(i=2;i<buf[1]+2;i+=2+buf[i+1]){
				if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==key_reference) ++found;
			}
			if(found) break;
		}
		if(r<=0){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_KEYD-Record found\n");
			return 1;
		}
		for(i=0;i<r;i+=2+buf[i+1]){
			if(buf[i]==0xB6) can_sign++;
			if(buf[i]==0xB8) can_crypt++;
		}
	} else {
		if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
				"Select(%s) failed\n",
				sc_print_path(&prkey_info.path));
			return 1;
		}
		if (f->prop_attr[1] & 0x04) can_crypt=1;
		if (f->prop_attr[1] & 0x08) can_sign=1;
		sc_file_free(f);
	}
	prkey_info.usage= SC_PKCS15_PRKEY_USAGE_SIGN;
	if(can_crypt) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT|SC_PKCS15_PRKEY_USAGE_DECRYPT;
	if(can_sign) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;

	r=sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
	if(r!=SC_SUCCESS){
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", path);
		return 4;
	}
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK%s%s\n", path, can_sign ? ", Sign" : "", can_crypt ? ", Crypt" : "");
	return 0;
}
/*
 * On-board key generation.
 */
static int
gpk_generate_key(sc_profile_t *profile, sc_card_t *card,
                 sc_pkcs15_object_t *obj,
                 sc_pkcs15_pubkey_t *pubkey)
{
    struct sc_cardctl_gpk_genkey args;
    sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
    unsigned int    keybits;
    sc_file_t	*keyfile;
    int             r, n;

    if (card->ctx->debug >= 1) {
        char pbuf[SC_MAX_PATH_STRING_SIZE];

        r = sc_path_print(pbuf, sizeof(pbuf), &key_info->path);
        if (r != SC_SUCCESS)
            pbuf[0] = '\0';

        sc_debug(card->ctx, "path=%s, %d bits\n", pbuf,
                 key_info->modulus_length);
    }

    if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
        sc_error(card->ctx, "GPK supports generating only RSA keys.");
        return SC_ERROR_NOT_SUPPORTED;
    }

    /* The caller is supposed to have chosen a key file path for us */
    if (key_info->path.len == 0 || key_info->modulus_length == 0)
        return SC_ERROR_INVALID_ARGUMENTS;
    keybits = key_info->modulus_length;

    if ((r = sc_select_file(card, &key_info->path, &keyfile)) < 0)
        return r;

#ifndef PK_INIT_IMMEDIATELY
    r = gpk_pkfile_init_public(profile, card, keyfile, SC_ALGORITHM_RSA,
                               keybits, key_info->usage);
    if (r < 0) {
        sc_file_free(keyfile);
        return r;
    }

    if ((r = gpk_pkfile_init_private(card, keyfile, 5 * ((3 + keybits / 16 + 7) & ~7UL))) < 0) {
        sc_file_free(keyfile);
        return r;
    }
#endif
    sc_file_free(keyfile);

    memset(&args, 0, sizeof(args));
    /*args.exponent = 0x10001;*/
    n = key_info->path.len;
    args.fid = (key_info->path.value[n-2] << 8) | key_info->path.value[n-1];
    args.privlen = keybits;

    r = sc_card_ctl(card, SC_CARDCTL_GPK_GENERATE_KEY, &args);
    if (r < 0)
        return r;

    /* This is fairly weird. The GENERATE RSA KEY command returns
     * immediately, but obviously it needs more time to complete.
     * This is why we sleep here. */
    sleep(20);

    pubkey->algorithm = SC_ALGORITHM_RSA;
    return gpk_read_rsa_key(card, &pubkey->u.rsa);
}
Beispiel #11
0
static int insert_pin(
	sc_pkcs15_card_t *p15card,
	const char       *path,
	unsigned char     id,
	unsigned char     auth_id,
	unsigned char     pin_reference,
	int               min_length,
	const char       *label,
	int               pin_flags
){
	sc_card_t *card=p15card->card;
	sc_context_t *ctx=p15card->card->ctx;
	sc_file_t *f;
	struct sc_pkcs15_auth_info pin_info;
	struct sc_pkcs15_object pin_obj;
	int r;

	memset(&pin_info, 0, sizeof(pin_info));
	pin_info.auth_id.len      = 1;
	pin_info.auth_id.value[0] = id;
	pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
	pin_info.attrs.pin.reference        = pin_reference;
	pin_info.attrs.pin.flags            = pin_flags;
	pin_info.attrs.pin.type             = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
	pin_info.attrs.pin.min_length       = min_length;
	pin_info.attrs.pin.stored_length    = 16;
	pin_info.attrs.pin.max_length       = 16;
	pin_info.attrs.pin.pad_char         = '\0';
	sc_format_path(path, &pin_info.path);

	memset(&pin_obj, 0, sizeof(pin_obj));
	strlcpy(pin_obj.label, label, sizeof(pin_obj.label));
	pin_obj.flags            = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
	pin_obj.auth_id.len      = auth_id ? 0 : 1;
	pin_obj.auth_id.value[0] = auth_id;

	if(card->type==SC_CARD_TYPE_TCOS_V3){
		unsigned char buf[256];
		int i, rec_no=0;
		if(pin_info.path.len>=2) pin_info.path.len-=2;
		sc_append_file_id(&pin_info.path, 0x5049);
		if(sc_select_file(card, &pin_info.path, NULL)!=SC_SUCCESS){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
				"Select(%s) failed\n",
				sc_print_path(&pin_info.path));
			return 1;
		}
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
			"Searching for PIN-Ref %02X\n", pin_reference);
		while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){
			int found=0, fbz=-1;
			if(buf[0]!=0xA0) continue;
			for(i=2;i<buf[1]+2;i+=2+buf[i+1]){
				if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==pin_reference) ++found;
				if(buf[i]==0x90) fbz=buf[i+1+buf[i+1]];
			}
			if(found) pin_info.tries_left=fbz;
			if(found) break;
		}
		if(r<=0){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_PWDD-Record found\n");
			return 1;
		}
	} else {
		if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path);
			return 1;
		}
		pin_info.tries_left=f->prop_attr[3];
		sc_file_free(f);
	}

	r=sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
	if(r!=SC_SUCCESS){
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_pin_obj(%s) failed\n", path);
		return 4;
	}
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK, FBZ=%d\n", path, pin_info.tries_left);
	return 0;
}
/*
 * Initialize pin file
 */
static int
gpk_init_pinfile(struct sc_profile *profile, sc_card_t *card,
                 sc_file_t *file)
{
    const sc_acl_entry_t *acl;
    unsigned char	buffer[GPK_MAX_PINS * 8], *blk;
    struct sc_file	*pinfile;
    unsigned int	so_attempts[2], user_attempts[2];
    unsigned int	npins, i, j, cks;
    int		r;

    /* Set defaults */
    so_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PIN);
    so_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PUK);
    user_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PIN);
    user_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PUK);

    sc_file_dup(&pinfile, file);
    if (pinfile == NULL)
        return SC_ERROR_OUT_OF_MEMORY;

    /* Create the PIN file. */
    acl = sc_file_get_acl_entry(pinfile, SC_AC_OP_WRITE);
    if (acl->method != SC_AC_NEVER) {
        sc_error(card->ctx,
                 "PIN file most be protected by WRITE=NEVER");
        sc_file_free(pinfile);
        return SC_ERROR_INVALID_ARGUMENTS;
    }
    sc_file_add_acl_entry(pinfile, SC_AC_OP_WRITE, SC_AC_NONE, 0);

    if (pinfile->size == 0)
        pinfile->size = GPK_MAX_PINS * 8;

    /* Now create the file */
    if ((r = sc_pkcs15init_create_file(profile, card, pinfile)) < 0
            || (r = sc_select_file(card, &pinfile->path, NULL)) < 0)
        goto out;

    /* Set up the PIN file contents.
     * We assume the file will contain pairs of PINs/PUKs */
    npins = pinfile->size / 8;
    memset(buffer, 0, sizeof(buffer));
    for (i = 0, blk = buffer; i < npins; blk += 8, i += 1) {
        /* Determine the number of PIN/PUK presentation
         * attempts. If the profile defines a SO PIN,
         * it will be stored in the first PIN/PUK pair.
         */
        blk[0] = user_attempts[i & 1];
        if (i < 2 && so_attempts[0])
            blk[0] = so_attempts[i & 1];
        if ((i & 1) == 0) {
            /* This is a PIN. If there's room in the file,
             * the next will be a PUK so take note of the
             * unlock code */
            if (i + 1 < npins)
                blk[2] = GPK_PIN_SCOPE | (i + 1);
        }

        /* Compute the CKS */
        for (j = 0, cks = 0; j < 8; j++)
            cks ^= blk[j];
        blk[3] = ~cks;
    }

    r = sc_write_binary(card, 0, buffer, npins * 8, 0);
    if (r >= 0)
        r = gpk_lock_pinfile(profile, card, pinfile);

out:
    sc_file_free(pinfile);
    return r;
}
/*
 * Store a PIN
 */
static int
gpk_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
               sc_pkcs15_object_t *pin_obj,
               const u8 *pin, size_t pin_len,
               const u8 *puk, size_t puk_len)
{
    sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
    u8	nulpin[8];
    int	r, type;

    if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
        type = SC_PKCS15INIT_SO_PIN;

        /* SO PIN reference must be 0 */
        if (pin_info->reference != (GPK_PIN_SCOPE | 0))
            return SC_ERROR_INVALID_ARGUMENTS;
    } else {
        type = SC_PKCS15INIT_USER_PIN;

        /* PIN references must be even numbers
         * (the odd numbered PIN entries contain the
         * PUKs).
         * Returning SC_ERROR_INVALID_PIN_REFERENCE will
         * tell the caller to pick a different value.
         */
        if ((pin_info->reference & 1) || !(pin_info->reference & GPK_PIN_SCOPE))
            return SC_ERROR_INVALID_PIN_REFERENCE;
        if (pin_info->reference >= (GPK_PIN_SCOPE + GPK_MAX_PINS))
            return SC_ERROR_TOO_MANY_OBJECTS;
    }

    /* No PUK given, but the PIN file specifies an unblock
     * PIN for every PIN.
     * Use the same value for the PUK for now.
     * Alternatively, we could leave the unblock PIN at the default
     * value, but deliberately block it. */
    if (puk == NULL || puk_len == 0) {
        puk = pin;
        puk_len = pin_len;
    }

    r = sc_select_file(card, &df->path, NULL);
    if (r < 0)
        return r;

    /* Current PIN is 00:00:00:00:00:00:00:00 */
    memset(nulpin, 0, sizeof(nulpin));
    r = sc_change_reference_data(card, SC_AC_CHV,
                                 pin_info->reference,
                                 nulpin, sizeof(nulpin),
                                 pin, pin_len, NULL);
    if (r < 0)
        return r;

    /* Current PUK is 00:00:00:00:00:00:00:00 */
    r = sc_change_reference_data(card, SC_AC_CHV,
                                 pin_info->reference + 1,
                                 nulpin, sizeof(nulpin),
                                 puk, puk_len, NULL);
    if (r < 0)
        return r;

    sc_keycache_set_pin_name(&df->path,
                             pin_info->reference,
                             type);

    return r;
}
/*
 * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects
 *
 */
static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
{
	sc_card_t *card = p15card->card;
	sc_file_t *file = NULL;
	sc_path_t path;
	u8 filelist[MAX_EXT_APDU_LENGTH];
	int filelistlength;
	int r, i;
	sc_cvc_t devcert;
	struct sc_app_info *appinfo;
	struct sc_pkcs15_auth_info pin_info;
	struct sc_pkcs15_object pin_obj;
	u8 efbin[512];
	u8 *ptr;
	size_t len;

	LOG_FUNC_CALLED(card->ctx);

	appinfo = calloc(1, sizeof(struct sc_app_info));

	if (appinfo == NULL) {
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
	}

	appinfo->aid = sc_hsm_aid;

	appinfo->ddo.aid = sc_hsm_aid;
	p15card->app = appinfo;

	sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0);
	r = sc_select_file(card, &path, &file);
	LOG_TEST_RET(card->ctx, r, "Could not select SmartCard-HSM application");

	p15card->card->version.hw_major = 24;	/* JCOP 2.4.1r3 */
	p15card->card->version.hw_minor = 13;
	p15card->card->version.fw_major = file->prop_attr[file->prop_attr_len - 2];
	p15card->card->version.fw_minor = file->prop_attr[file->prop_attr_len - 1];

	sc_file_free(file);

	/* Read device certificate to determine serial number */
	sc_path_set(&path, SC_PATH_TYPE_FILE_ID, (u8 *) "\x2F\x02", 2, 0, 0);
	r = sc_select_file(card, &path, NULL);
	LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut");

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

	ptr = efbin;
	len = r;

	memset(&devcert, 0 ,sizeof(devcert));
	r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert);
	LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut");

	sc_pkcs15emu_sc_hsm_read_tokeninfo(p15card);

	if (p15card->tokeninfo->label == NULL) {
		p15card->tokeninfo->label = strdup("SmartCard-HSM");
		if (p15card->tokeninfo->label == NULL)
			LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
	}

	if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) {
		free(p15card->tokeninfo->manufacturer_id);
		p15card->tokeninfo->manufacturer_id = NULL;
	}

	if (p15card->tokeninfo->manufacturer_id == NULL) {
		p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de");
		if (p15card->tokeninfo->manufacturer_id == NULL)
			LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
	}

	appinfo->label = strdup(p15card->tokeninfo->label);
	if (appinfo->label == NULL)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);

	len = strnlen(devcert.chr, sizeof devcert.chr);		/* Strip last 5 digit sequence number from CHR */
	assert(len >= 8);
	len -= 5;

	p15card->tokeninfo->serial_number = calloc(len + 1, 1);
	if (p15card->tokeninfo->serial_number == NULL)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);

	memcpy(p15card->tokeninfo->serial_number, devcert.chr, len);
	*(p15card->tokeninfo->serial_number + len) = 0;

	sc_hsm_set_serialnr(card, p15card->tokeninfo->serial_number);

	sc_pkcs15emu_sc_hsm_free_cvc(&devcert);

	memset(&pin_info, 0, sizeof(pin_info));
	memset(&pin_obj, 0, sizeof(pin_obj));

	pin_info.auth_id.len = 1;
	pin_info.auth_id.value[0] = 1;
	pin_info.path.aid = sc_hsm_aid;
	pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
	pin_info.attrs.pin.reference = 0x81;
	pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA;
	pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
	pin_info.attrs.pin.min_length = 6;
	pin_info.attrs.pin.stored_length = 0;
	pin_info.attrs.pin.max_length = 15;
	pin_info.attrs.pin.pad_char = '\0';
	pin_info.tries_left = 3;
	pin_info.max_tries = 3;

	strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label));
	pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE;

	r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
	if (r < 0)
		LOG_FUNC_RETURN(card->ctx, r);


	memset(&pin_info, 0, sizeof(pin_info));
	memset(&pin_obj, 0, sizeof(pin_obj));

	pin_info.auth_id.len = 1;
	pin_info.auth_id.value[0] = 2;
	pin_info.path.aid = sc_hsm_aid;
	pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
	pin_info.attrs.pin.reference = 0x88;
	pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED|SC_PKCS15_PIN_FLAG_SO_PIN;
	pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_BCD;
	pin_info.attrs.pin.min_length = 16;
	pin_info.attrs.pin.stored_length = 0;
	pin_info.attrs.pin.max_length = 16;
	pin_info.attrs.pin.pad_char = '\0';
	pin_info.tries_left = 15;
	pin_info.max_tries = 15;

	strlcpy(pin_obj.label, "SOPIN", sizeof(pin_obj.label));
	pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;

	r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
	if (r < 0)
		LOG_FUNC_RETURN(card->ctx, r);


	filelistlength = sc_list_files(card, filelist, sizeof(filelist));
	LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier");

	for (i = 0; i < filelistlength; i += 2) {
		switch(filelist[i]) {
		case KEY_PREFIX:
			r = sc_pkcs15emu_sc_hsm_add_prkd(p15card, filelist[i + 1]);
			break;
		case DCOD_PREFIX:
			r = sc_pkcs15emu_sc_hsm_add_dcod(p15card, filelist[i + 1]);
			break;
		case CD_PREFIX:
			r = sc_pkcs15emu_sc_hsm_add_cd(p15card, filelist[i + 1]);
			break;
		}
		if (r != SC_SUCCESS) {
			sc_log(card->ctx, "Error %d adding elements to framework", r);
		}
	}

	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
Beispiel #15
0
static int
myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
		struct sc_pkcs15_object *object,
		struct sc_pkcs15_pubkey *pubkey) {
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_card *card = p15card->card;
	struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
	struct sc_cardctl_myeid_gen_store_key_info args;
	struct sc_file *file = NULL;
	int r;
	size_t keybits = key_info->modulus_length;
	unsigned char raw_pubkey[256];

	LOG_FUNC_CALLED(ctx);
	if (object->type != SC_PKCS15_TYPE_PRKEY_RSA && object->type != SC_PKCS15_TYPE_PRKEY_EC)
		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: only RSA and EC supported");

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

	sc_log(ctx, "Generate key with ID:%s and path:%s",
			sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path));

	r = sc_select_file(card, &key_info->path, &file);
	LOG_TEST_RET(ctx, r, "Cannot generate key: failed to select key file");

	r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE);
	LOG_TEST_RET(ctx, r, "No authorisation to generate private key");

	/* Fill in data structure */
	memset(&args, 0, sizeof (args));
	args.key_len_bits = keybits;
	args.op_type = OP_TYPE_GENERATE;
	if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
		args.key_type = SC_CARDCTL_MYEID_KEY_RSA;
		args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN;
		args.pubexp = MYEID_DEFAULT_PUBKEY;
	} else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) {
		args.key_type = SC_CARDCTL_MYEID_KEY_EC;
	}

	/* Generate RSA key  */
	r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args);
	LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed");

	/* Keypair generation -> collect public key info */
	if (pubkey != NULL) {
		struct sc_cardctl_myeid_data_obj data_obj;

		if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
			pubkey->algorithm = SC_ALGORITHM_RSA;
			pubkey->u.rsa.modulus.len = (keybits + 7) / 8;
			pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len);
			pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN;
			pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN);
			memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN);

			/* Get public key modulus */
			r = sc_select_file(card, &file->path, NULL);
			LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed");

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

			r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
			LOG_TEST_RET(ctx, r, "Cannot get RSA key modulus: 'MYEID_GETDATA' failed");

			if ((data_obj.DataLen * 8) != key_info->modulus_length)
				LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get RSA key modulus: invalid key-size");

			memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len);
		} 
		else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) {

			pubkey->algorithm = SC_ALGORITHM_EC;

			r = sc_select_file(card, &file->path, NULL);
			LOG_TEST_RET(ctx, r, "Cannot get public key: select key file failed");

			data_obj.P1 = 0x01;
			data_obj.P2 = 0x86; /* Get public EC key (Q) */
			data_obj.Data = raw_pubkey;
			data_obj.DataLen = sizeof (raw_pubkey);

			r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj);
			LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed");

			pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2);
			pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2;
			pubkey->data.value = malloc(data_obj.DataLen);
			pubkey->data.len = data_obj.DataLen;
			pubkey->u.ec.params.field_length = keybits;
			/* Omit the first 2 bytes (0x86??) */
			memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2);
			memcpy(pubkey->data.value, data_obj.Data, data_obj.DataLen);
		}
	}

	if (file)
		sc_file_free(file);

	LOG_FUNC_RETURN(ctx, r);
}
Beispiel #16
0
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
{
	int r, i, 				type;
	unsigned char 			*buf = NULL;
	size_t 					len;
	sc_pkcs15_tokeninfo_t 	tokeninfo;
	sc_path_t 				tmppath;
	sc_card_t 				*card = p15card->card;
	sc_context_t 			*ctx = card->ctx;

	/* Parse the TokenInfo EF */
	sc_format_path("3f004f005032", &tmppath);
	r = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
	if (r)
		goto end;
	if ( (len = p15card->file_tokeninfo->size) == 0) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EF(TokenInfo) is empty\n");
		goto end;
	}
	buf = malloc(len);
	if (buf == NULL)
		return SC_ERROR_OUT_OF_MEMORY;
	r = sc_read_binary(card, 0, buf, len, 0);
	if (r < 0)
		goto end;
	if (r <= 2) {
		r = SC_ERROR_PKCS15_APP_NOT_FOUND;
		goto end;
	}
	memset(&tokeninfo, 0, sizeof(tokeninfo));
	r = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t) r);
	if (r != SC_SUCCESS)
		goto end;

	*(p15card->tokeninfo) = tokeninfo;

	/* Card type detection */
	if (card->type == SC_CARD_TYPE_IAS_PTEID)
		type = IAS_CARD;
	else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
		type = GEMSAFE_CARD;
	else {
		r = SC_ERROR_INTERNAL;
		goto end;
	}

	p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION
				  | SC_PKCS15_TOKEN_EID_COMPLIANT
				  | SC_PKCS15_TOKEN_READONLY;

	/* TODO: Use the cardholder's name?  */
	/* TODO: Use Portuguese descriptions? */
	
	/* Add X.509 Certificates */
	for (i = 0; i < 4; i++) {
		static const char *pteid_cert_names[4] = {
				"AUTHENTICATION CERTIFICATE",
				"SIGNATURE CERTIFICATE",
				"SIGNATURE SUB CA",
				"AUTHENTICATION SUB CA"
		};
		/* X.509 Certificate Paths */
		static const char *pteid_cert_paths[4] = {
			"3f005f00ef09", /* Authentication Certificate path */
			"3f005f00ef08", /* Digital Signature Certificate path */
			"3f005f00ef0f", /* Signature sub CA path */
			"3f005f00ef10"	/* Authentication sub CA path */
		};
		/* X.509 Certificate IDs */
		static const int pteid_cert_ids[4] = {0x45, 0x46, 0x51, 0x52};
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object cert_obj;

		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj, 0, sizeof(cert_obj));

		cert_info.id.value[0] = pteid_cert_ids[i];
		cert_info.id.len = 1;
		sc_format_path(pteid_cert_paths[i], &cert_info.path);
		strlcpy(cert_obj.label, pteid_cert_names[i], sizeof(cert_obj.label));
		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		if (r < 0) {
			r = SC_ERROR_INTERNAL;
			goto end;
		}
	}
	
	/* Add PINs */
	for (i = 0; i < 3; i++) {
		static const char *pteid_pin_names[3] = {
			"Auth PIN",
			"Sign PIN",
			"Address PIN"
		};
		/* PIN References */
		static const int pteid_pin_ref[2][3] = { {1, 130, 131}, {129, 130, 131} };
		/* PIN Authentication IDs */
		static const int pteid_pin_authid[3] = {1, 2, 3};
		/* PIN Paths */
		static const char *pteid_pin_paths[2][3] = { {NULL, "3f005f00", "3f005f00"},
													 {NULL, NULL, NULL} };
		struct sc_pkcs15_auth_info pin_info;
		struct sc_pkcs15_object pin_obj;

		memset(&pin_info, 0, sizeof(pin_info));
		memset(&pin_obj, 0, sizeof(pin_obj));

		pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
		pin_info.auth_id.len = 1;
		pin_info.auth_id.value[0] = pteid_pin_authid[i];
		pin_info.attrs.pin.reference = pteid_pin_ref[type][i];
		pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_NEEDS_PADDING
						 | SC_PKCS15_PIN_FLAG_INITIALIZED
						 | SC_PKCS15_PIN_FLAG_CASE_SENSITIVE;
		pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
		pin_info.attrs.pin.min_length = 4;
		pin_info.attrs.pin.stored_length = 8;
		pin_info.attrs.pin.max_length = 8;
		pin_info.attrs.pin.pad_char = type == IAS_CARD ? 0x2F : 0xFF;
		pin_info.tries_left = -1;
		if (pteid_pin_paths[type][i] != NULL)
			sc_format_path(pteid_pin_paths[type][i], &pin_info.path);
		strlcpy(pin_obj.label, pteid_pin_names[i], sizeof(pin_obj.label));
		pin_obj.flags = 0;
		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
		if (r < 0) {
			r = SC_ERROR_INTERNAL;
			goto end;
		}
	}

	/* Add Private Keys */
	for (i = 0; i < 2; i++) {
		/* Key reference */
		static const int pteid_prkey_keyref[2][2] = { {1, 130}, {2, 1} };
		/* RSA Private Key usage */
		static int pteid_prkey_usage[2] = {
			SC_PKCS15_PRKEY_USAGE_SIGN,
			SC_PKCS15_PRKEY_USAGE_NONREPUDIATION};
		/* RSA Private Key IDs */
		static const int pteid_prkey_ids[2] = {0x45, 0x46};
		static const char *pteid_prkey_names[2] = {
				"CITIZEN AUTHENTICATION KEY",
				"CITIZEN SIGNATURE KEY"};
		/* RSA Private Key Paths */
		static const char *pteid_prkey_paths[2][2] = { {NULL, "3f005f00"}, {NULL, NULL} };
		struct sc_pkcs15_prkey_info prkey_info;
		struct sc_pkcs15_object prkey_obj;

		memset(&prkey_info, 0, sizeof(prkey_info));
		memset(&prkey_obj, 0, sizeof(prkey_obj));

		prkey_info.id.len = 1;
		prkey_info.id.value[0] = pteid_prkey_ids[i];
		prkey_info.usage = pteid_prkey_usage[i];
		prkey_info.native = 1;
		prkey_info.key_reference = pteid_prkey_keyref[type][i];
		prkey_info.modulus_length = 1024;
		if (pteid_prkey_paths[type][i] != NULL)
			sc_format_path(pteid_prkey_paths[type][i], &prkey_info.path);
		strlcpy(prkey_obj.label, pteid_prkey_names[i], sizeof(prkey_obj.label));
		prkey_obj.auth_id.len = 1;
		prkey_obj.auth_id.value[0] = i + 1;
		prkey_obj.user_consent = (i == 1) ? 1 : 0;
		prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;

		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
		if (r < 0) {
			r = SC_ERROR_INTERNAL;
			goto end;
		}
	}

	/* Add objects */
	for (i = 0; i < 3; i++) {
		static const char *object_ids[3] = {"1", "2", "3"};
		static const char *object_oids[3] = {"-1", "-1", "-1"};
		static const char *object_labels[3] = {"Citizen Data",
											   "Citizen Address Data",
											   "Citizen Notepad"};
		static const char *object_authids[3] = {NULL, "3", "1"};
		static const char *object_paths[3] = {"3f005f00ef02",
											  "3f005f00ef05",
											  "3f005f00ef07"};
		static const int object_flags[3] = {0,
											SC_PKCS15_CO_FLAG_PRIVATE,
											SC_PKCS15_CO_FLAG_MODIFIABLE};
		struct sc_pkcs15_data_info obj_info;
		struct sc_pkcs15_object obj_obj;

		memset(&obj_info, 0, sizeof(obj_info));
		memset(&obj_obj, 0, sizeof(obj_obj));

		sc_pkcs15_format_id(object_ids[i], &obj_info.id);
		sc_format_path(object_paths[i], &obj_info.path);
		r = sc_format_oid(&obj_info.app_oid, object_oids[i]);
		if (r != SC_SUCCESS)
			goto end;
		strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
		if (object_authids[i] != NULL)
			sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id);
		strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
		obj_obj.flags = object_flags[i];

		r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info);
		if (r < 0)
			goto end;
	}
end:
	if (buf != NULL) {
		free(buf);
		buf = NULL;
	}
	if (r)
		return r;

	return SC_SUCCESS;
}
Beispiel #17
0
static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card)
{
	sc_card_t *card = p15card->card;
	sc_path_t path;
	sc_pkcs15_id_t id, auth_id;
	unsigned char serial_buf[13], *serial;
	int flags;
	int r;

#ifdef ENABLE_ZLIB
	int i = 0, j = 0;
	const char *certLabel[] = {
		"User Non-repudiation Certificate",	/* "User Non-repudiation Certificate" */
		"TSA Certificate",
		"CA Certificate"
	};	
	const char *certPath[] =
	    { "3F00300060006002", "3F00300060006003", "3F00300060006004" };
#endif

	const char *keyPath = "3F00300040000008";
	const char *pinDfName = "05040200";
	
	/* const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; */
	const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN
				| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
				| SC_PKCS15_PRKEY_USAGE_ENCRYPT
				| SC_PKCS15_PRKEY_USAGE_DECRYPT;
	    
	const char *authPIN = "Authentication PIN";
	/* const char *nonrepPIN = "Non-repudiation PIN"; */

	const char *authPRKEY = "Authentication Key";
	/* const char *nonrepPRKEY = "Non repudiation Key"; */
	
	p15card->opts.use_file_cache = 1;	

	/* Get Serial number */
	sc_format_path("3F0030000001", &path);
	r = sc_select_file(card, &path, NULL);
	if (r != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;

	sc_read_binary(card, 0xC3, serial_buf, 12, 0);
	serial = serial_buf;

	/*
	 * The serial number is 8 characters long. Later versions of the
	 * card have the serial number at a different offset, after 4 more
	 * bytes.
	 */
	if (serial[0] != 'H') {
		if (serial[4] == 'H')
			serial = &serial_buf[4];
		else
			return SC_ERROR_WRONG_CARD;
	}
	serial[8] = '\0';

	/* Controllo che il serial number inizi per "H" */
	if( serial[0] != 'H' ) 
		return SC_ERROR_WRONG_CARD;
			
	set_string(&p15card->tokeninfo->label, "Actalis");
	set_string(&p15card->tokeninfo->manufacturer_id, "Actalis");
	set_string(&p15card->tokeninfo->serial_number, (char *)serial);

#ifdef ENABLE_ZLIB
	for (i = 0; i < 3; i++) {
		sc_path_t cpath;
		sc_format_path(certPath[i], &cpath);

		if (sc_select_file(card, &cpath, NULL) == SC_SUCCESS) {
			unsigned char *compCert = NULL, *cert = NULL, size[2];
			unsigned int compLen, len;

			sc_pkcs15_cert_info_t cert_info;
			sc_pkcs15_object_t cert_obj;
			memset(&cert_info, 0, sizeof(cert_info));
			memset(&cert_obj, 0, sizeof(cert_obj));

			sc_read_binary(card, 2, size, 2, 0);
			compLen = (size[0] << 8) + size[1];
			compCert = malloc(compLen * sizeof(unsigned char));
			len = 3 * compLen;	/*Approximation of the uncompressed size */
			cert = malloc(len * sizeof(unsigned char));

			sc_read_binary(card, 4, compCert, compLen, 0);

			if (uncompress(cert, (unsigned long int *) &len,
				compCert, compLen) != Z_OK)
				return SC_ERROR_INTERNAL;
			cpath.index = 0;
			cpath.count = len;

			sc_pkcs15_cache_file(p15card, &cpath, cert, len);
			id.value[0] = j + 1;
			id.len = 1;
			cert_info.id = id;
			cert_info.path = cpath;
			cert_info.authority = (j>0);

			strlcpy(cert_obj.label, certLabel[j], sizeof(cert_obj.label));

			j++;
			cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
			sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		}
	}
#endif
	
	/* adding PINs & private keys */
	flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED |
	    SC_PKCS15_PIN_FLAG_NEEDS_PADDING;	
	
	sc_format_path(pinDfName, &path);
	path.type = SC_PATH_TYPE_DF_NAME;
	
	id.value[0] = 1;
	id.len = 1;
	sc_pkcs15emu_add_pin(p15card, &id,
			     authPIN, &path, 0x81,
			     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
			     5, 8, flags, 3, 0,
			     SC_PKCS15_CO_FLAG_MODIFIABLE |
			     SC_PKCS15_CO_FLAG_PRIVATE);
	
	sc_format_path(keyPath, &path);
	id.value[0] = 1;
	id.len = 1;
	auth_id.value[0] = 1;
	auth_id.len = 1;
	sc_pkcs15emu_add_prkey(p15card, &id,
		       authPRKEY,
		       SC_PKCS15_TYPE_PRKEY_RSA,
		       1024, authprkey_usage,
		       &path, 0x08,
		       &auth_id,
		       SC_PKCS15_CO_FLAG_PRIVATE);
	
	/* return to MF */
	sc_format_path("3F00", &path);
	sc_select_file(card, &path, NULL);
	{
		/* save old signature funcs */
		set_security_env = card->ops->set_security_env;
		/* set new one             */
		card->ops->set_security_env  = set_sec_env;
		card->ops->compute_signature = do_sign;
	}
	
	return SC_SUCCESS;

}
Beispiel #18
0
/*
 * Generate a keypair
 */
static int
jcop_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
		  sc_pkcs15_object_t *obj,
		  sc_pkcs15_pubkey_t *pubkey)
{
     sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
     struct sc_cardctl_jcop_genkey args;
     sc_file_t       *temppubfile=NULL, *keyfile=NULL;
     unsigned char   *keybuf=NULL;
     size_t          mod_len, exp_len, pub_len, keybits;
     int             r,delete_ok=0;

     if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
	  sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys.");
	  return SC_ERROR_NOT_SUPPORTED;
     }

     r=sc_profile_get_file(profile, "temp-pubkey", &temppubfile);
     if (r < 0)
	  goto out;

     r = sc_select_file(p15card->card, &key_info->path, &keyfile);
     if (r < 0)
	  goto out;

     mod_len = key_info->modulus_length / 8;
     exp_len = 4;
     pub_len = 2 + mod_len + exp_len;
     temppubfile->size = pub_len;

     r = sc_pkcs15init_fixup_file(profile, p15card, temppubfile);
     if (r < 0)
	  goto out;

     r = sc_pkcs15init_create_file(profile, p15card, temppubfile);
     if (r < 0)
	  goto out;

     delete_ok=1;
     r = sc_pkcs15init_authenticate(profile, p15card, temppubfile, SC_AC_OP_UPDATE);
     if (r < 0)
	  goto out;
     r = sc_pkcs15init_authenticate(profile, p15card, keyfile, SC_AC_OP_UPDATE);
     if (r < 0)
	  goto out;

     keybits = key_info->modulus_length;

     /* generate key */
     /* keysize is _not_ passed to the card at any point. it appears to
	infer it from the file size */
     memset(&args, 0, sizeof(args));
     args.exponent = 0x10001;
     sc_append_file_id(&args.pub_file_ref, temppubfile->id);
     sc_append_file_id(&args.pri_file_ref, keyfile->id);
     keybuf = malloc(keybits / 8);
     if (!keybuf) {
	  r=SC_ERROR_OUT_OF_MEMORY;
	  goto out;
     }
     args.pubkey = keybuf;
     args.pubkey_len = keybits / 8;

     r = sc_card_ctl(p15card->card, SC_CARDCTL_JCOP_GENERATE_KEY, (void *)&args);
     if (r < 0)
	  goto out;

     /* extract public key */
     pubkey->algorithm = SC_ALGORITHM_RSA;
     pubkey->u.rsa.modulus.len   = keybits / 8;
     pubkey->u.rsa.modulus.data  = keybuf;
     pubkey->u.rsa.exponent.len  = 3;
     pubkey->u.rsa.exponent.data = malloc(3);
     if (!pubkey->u.rsa.exponent.data) {
	  pubkey->u.rsa.modulus.data = NULL;
	  r=SC_ERROR_OUT_OF_MEMORY;
	  goto out;
     }
     memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);

 out:
     if (r < 0 && keybuf)
	  free(keybuf);
     if (delete_ok)
	  sc_pkcs15init_rmdir(p15card, profile, temppubfile);
     if (keyfile)
	  sc_file_free(keyfile);
     if (temppubfile)
	  sc_file_free(temppubfile);
     return r;
}
Beispiel #19
0
static int do_get(int argc, char **argv)
{
	u8 buf[256];
	int r, err = 1;
	size_t count = 0;
	unsigned int idx = 0;
	sc_path_t path;
	sc_file_t *file = NULL;
	char *filename;
	FILE *outf = NULL;

	if (argc < 1 || argc > 2)
		return usage(do_get);
	if (arg_to_path(argv[0], &path, 0) != 0)
		return usage(do_get);

	filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_');
	outf = (strcmp(filename, "-") == 0)
		? stdout
		: fopen(filename, "wb");
	if (outf == NULL) {
		perror(filename);
		goto err;
	}
	r = sc_select_file(card, &path, &file);
	if (r) {
		check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
		goto err;
	}
	if (file->type != SC_FILE_TYPE_WORKING_EF) {
		printf("only working EFs may be read\n");
		goto err;
	}
	count = file->size;
	while (count) {
		/* FIXME sc_read_binary does this kind of fetching in a loop already */
		int c = count > sizeof(buf) ? sizeof(buf) : count;

		r = sc_read_binary(card, idx, buf, c, 0);
		if (r < 0) {
			check_ret(r, SC_AC_OP_READ, "read failed", file);
			goto err;
		}
		if ((r != c) && (card->type != SC_CARD_TYPE_BELPIC_EID)) {
			printf("expecting %d, got only %d bytes.\n", c, r);
			goto err;
		}
		if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID))
			break;
		fwrite(buf, r, 1, outf);
		idx += r;
		count -= r;
	}
	if (outf == stdout) {
		fwrite("\n", 1, 1, outf);
	}
	else {
		printf("Total of %d bytes read from %s and saved to %s.\n",
		       idx, argv[0], filename);
	}

	err = 0;
err:
	if (file)
		sc_file_free(file);
	if (outf != NULL && outf != stdout)
		fclose(outf);
	select_current_path_or_die();
	return -err;
}
Beispiel #20
0
static void do_esteid(sc_card_t *card)
{
	sc_path_t path;
	int r, i;
	unsigned char buff[512];

	if (stats) {
		int key_used[4];
		sc_format_path("3f00eeee0013", &path);
		r = sc_select_file(card, &path, NULL);
		if (r) {
			fprintf(stderr, "Failed to select key counters: %s\n", sc_strerror(r));
			goto out;
		}

		/* print the counters */
		for (i = 1; i <= 4; i++) {
			r = sc_read_record(card, i, buff, 128, SC_RECORD_BY_REC_NR);
			if (r < 0)
				goto out;
			key_used[i - 1] = 0xffffff - ((unsigned char) buff[0xc] * 65536
									+ (unsigned char) buff[0xd] * 256
									+ (unsigned char) buff[0xe]);
		}
		for (i = 0; i < 2; i++) {
			printf("Key generation #%d usage:\n\tsign: %d\n\tauth: %d\n",
					 i, key_used[i], key_used[i + 2]);
		}
		exit_status = EXIT_SUCCESS;
		goto out;
	}

	/* Or just read the datafile */
	sc_format_path("3f00eeee5044", &path);
	r = sc_select_file(card, &path, NULL);
	if (r) {
		fprintf(stderr, "Failed to select DF: %s\n", sc_strerror(r));
		goto out;
	}

	for (i = 0; esteid_data[i].recno != 0; i++) {
		r = sc_read_record(card, esteid_data[i].recno, buff, 50, SC_RECORD_BY_REC_NR);
		if (r < 0) {
			fprintf (stderr, "Failed to read record %d from card: %s\n",
						esteid_data[i].recno, sc_strerror (r));
			goto out;
		}
		buff[r] = '\0';
		if (exec_program) {
			unsigned char * cp;
			cp = malloc(strlen(esteid_data[i].env_name) +
				strlen((char *) buff) + 2);
			if (cp) {
				strcpy((char *) cp,esteid_data[i].env_name);
				strcat((char *) cp,"=");
				strcat((char *) cp,(char *) buff);
				putenv((char *) cp);
			}
		} else {
			printf("%s: %s\n", esteid_data[i].name, buff);
		}
	}

	exit_status = EXIT_SUCCESS;

out:
	return;
}
Beispiel #21
0
static int do_asn1(int argc, char **argv)
{
	int r, err = 1;
	sc_path_t path;
	sc_file_t *file = NULL;
	int not_current = 1;
	size_t len;
	unsigned char *buf = NULL;

	if (argc > 1)
		return usage(do_asn1);

	/* select file */
	if (argc) {
		if (arg_to_path(argv[0], &path, 0) != 0) {
			puts("Invalid file path");
			return -1;
		}
		r = sc_select_file(card, &path, &file);
		if (r) {
			check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
			goto err;
		}
	} else {
		path = current_path;
		file = current_file;
		not_current = 0;
	}
	if (file->type != SC_FILE_TYPE_WORKING_EF) {
		printf("only working EFs may be read\n");
		goto err;
	}

	/* read */
	if (file->ef_structure != SC_FILE_EF_TRANSPARENT) {
		printf("only transparent file type is supported at the moment\n");
		goto err;
	}
	len = file->size;
	buf = calloc(1, len);
	if (!buf) {
		goto err;
	}
	r = sc_read_binary(card, 0, buf, len, 0);
	if (r < 0) {
		check_ret(r, SC_AC_OP_READ, "read failed", file);
		goto err;
	}
	if ((size_t)r != len) {
		printf("WARNING: expecting %lu, got %d bytes.\n", (unsigned long) len, r);
		/* some cards return a bogus value for file length. As
		 * long as the actual length is not higher than the expected
		 * length, continue */
		if(r > (signed)len) {
			goto err;
		}
	}

	/* asn1 dump */
	sc_asn1_print_tags(buf, r);

	err = 0;
err:
	if (buf)
		free(buf);
	if (not_current) {
		if (file)
			sc_file_free(file);
		select_current_path_or_die();
	}
	return -err;
}
Beispiel #22
0
static int gemsafe_get_cert_len(sc_card_t *card)
{
	int r;
	u8  ibuf[GEMSAFE_MAX_OBJLEN];
	u8 *iptr;
	struct sc_path path;
	struct sc_file *file;
	size_t objlen, certlen;
	unsigned int ind, i=0;

	sc_format_path(GEMSAFE_PATH, &path);
	r = sc_select_file(card, &path, &file);
	if (r != SC_SUCCESS || !file)
		return SC_ERROR_INTERNAL;

	/* Initial read */
	r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
	if (r < 0)
		return SC_ERROR_INTERNAL;

	/* Actual stored object size is encoded in first 2 bytes
	 * (allocated EF space is much greater!)
	 */
	objlen = (((size_t) ibuf[0]) << 8) | ibuf[1];
	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		 "Stored object is of size: %d\n", objlen);
	if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) {
	    sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		     "Invalid object size: %d\n", objlen);
	    return SC_ERROR_INTERNAL;
	}

	/* It looks like the first thing in the block is a table of
	 * which keys are allocated. The table is small and is in the
	 * first 248 bytes. Example for a card with 10 key containers:
	 * 01 f0 00 03 03 b0 00 03     <=  1st key unallocated
	 * 01 f0 00 04 03 b0 00 04     <=  2nd key unallocated
	 * 01 fe 14 00 05 03 b0 00 05  <=  3rd key allocated
	 * 01 fe 14 01 06 03 b0 00 06  <=  4th key allocated
	 * 01 f0 00 07 03 b0 00 07     <=  5th key unallocated
	 * ...
	 * 01 f0 00 0c 03 b0 00 0c     <= 10th key unallocated
	 * For allocated keys, the fourth byte seems to indicate the
	 * default key and the fifth byte indicates the key_ref of
	 * the private key.
	 */
	ind = 2; /* skip length */
	while (ibuf[ind] == 0x01) {
		if (ibuf[ind+1] == 0xFE) {
			gemsafe_prkeys[i].ref = ibuf[ind+4];
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Key container %d is allocated and uses key_ref %d\n", i+1,
				 gemsafe_prkeys[i].ref);
			ind += 9;
		} else {
			gemsafe_prkeys[i].label = NULL;
			gemsafe_cert[i].label = NULL;
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Key container %d is unallocated\n", i+1);
			ind += 8;
		}
		i++;
	}

	/* Delete additional key containers from the data structures if
	 * this card can't accomodate them.
	 */
	for (; i < gemsafe_cert_max; i++) {
		gemsafe_prkeys[i].label = NULL;
		gemsafe_cert[i].label = NULL;
	}

	/* Read entire file, then dissect in memory.
	 * Gemalto ClassicClient seems to do it the same way.
	 */
	iptr = ibuf + GEMSAFE_READ_QUANTUM;
	while ((size_t)(iptr - ibuf) < objlen) {
		r = sc_read_binary(card, iptr - ibuf, iptr,
				   MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
		if (r < 0) {
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Could not read cert object\n");
			return SC_ERROR_INTERNAL;
		}
		iptr += GEMSAFE_READ_QUANTUM;
	}

	/* Search buffer for certificates, they start with 0x3082. */
	i = 0;
	while (ind < objlen - 1) {
		if (ibuf[ind] == 0x30 && ibuf[ind+1] == 0x82) {
			/* Find next allocated key container */
			while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL)
				i++;
			if (i == gemsafe_cert_max) {
				sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
					 "Warning: Found orphaned certificate at offset %d\n", ind);
				return SC_SUCCESS;
			}
			/* DER cert len is encoded this way */
			certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4;
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Found certificate of key container %d at offset %d, len %d\n",
				 i+1, ind, certlen);
			gemsafe_cert[i].index = ind;
			gemsafe_cert[i].count = certlen;
			ind += certlen;
			i++;
		} else
			ind++;
	}

	/* Delete additional key containers from the data structures if
	 * they're missing on the card.
	 */
	for (; i < gemsafe_cert_max; i++) {
		if (gemsafe_cert[i].label) {
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
				 "Warning: Certificate of key container %d is missing\n", i+1);
			gemsafe_prkeys[i].label = NULL;
			gemsafe_cert[i].label = NULL;
		}
	}

	return SC_SUCCESS;
}
Beispiel #23
0
static int do_find(int argc, char **argv)
{
	u8 fid[2], end[2];
	sc_path_t path;
	int r;

	fid[0] = 0;
	fid[1] = 0;
	end[0] = 0xFF;
	end[1] = 0xFF;
	switch (argc) {
	case 2:
		if (arg_to_fid(argv[1], end) != 0)
			return usage(do_find);
		/* fall through */
	case 1:
		if (arg_to_fid(argv[0], fid) != 0)
			return usage(do_find);
		/* fall through */
	case 0:
		break;
	default:
		return usage(do_find);
	}

	printf("FileID\tType  Size\n");
	while (1) {
		sc_file_t *file = NULL;

		printf("(%02X%02X)\r", fid[0], fid[1]);
		fflush(stdout);

		if (current_path.type != SC_PATH_TYPE_DF_NAME) {
			path = current_path;
			sc_append_path_id(&path, fid, sizeof fid);
		} else {
			if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0) != SC_SUCCESS) {
				printf("unable to set path.\n");
				die(1);
			}
		}

		r = sc_select_file(card, &path, &file);
		switch (r) {
		case SC_SUCCESS:
			file->id = (fid[0] << 8) | fid[1];
			print_file(file);
			sc_file_free(file);
			select_current_path_or_die();
			break;
		case SC_ERROR_NOT_ALLOWED:
		case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED:
			printf("(%02X%02X)\t%s\n", fid[0], fid[1], sc_strerror(r));
			break;
		}

		if (fid[0] == end[0] && fid[1] == end[1])
			break;
		fid[1] = fid[1] + 1;
		if (fid[1] == 0)
			fid[0] = fid[0] + 1;
	}
	return 0;
}
Beispiel #24
0
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_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n");

	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 numer */
	apdu.le = 0x08;
	apdu.lc = 0;
	apdu.datalen = 0;
	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)
		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_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n");
	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_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n");
	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_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n");
	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_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n");
	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;
}
Beispiel #25
0
static int do_info(int argc, char **argv)
{
	sc_file_t *file;
	sc_path_t path;
	size_t i;
	const char *st = NULL;
	int r, not_current = 1;
	const id2str_t *ac_ops = NULL;

	if (!argc) {
		path = current_path;
		file = current_file;
		not_current = 0;
	} else if (argc == 1) {
		if (arg_to_path(argv[0], &path, 0) != 0)
			return usage(do_info);

		r = sc_select_file(card, &path, &file);
		if (r) {
			printf("unable to select file: %s\n", sc_strerror(r));
			return -1;
		}
	} else
		return usage(do_info);

	if(!file->type_attr_len)
		st = "Unknown File";

	switch (file->type) {
	case SC_FILE_TYPE_WORKING_EF:
	case SC_FILE_TYPE_INTERNAL_EF:
		st = "Elementary File";
		break;
	case SC_FILE_TYPE_DF:
		st = "Dedicated File";
		break;
	}
	if (st == NULL)
		printf("\nFile type [%02x] ID %04X", *file->type_attr, file->id);
	else
		printf("\n%s  ID %04X", st, file->id);
	if (file->sid)
		printf(", SFI %02X", file->sid);
	printf("\n\n%-15s%s\n", "File path:", path_to_filename(&path, '/'));
	printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size);

	if (file->type == SC_FILE_TYPE_DF) {
		static const id2str_t ac_ops_df[] = {
			{ SC_AC_OP_SELECT,       "SELECT"       },
			{ SC_AC_OP_LOCK,         "LOCK"         },
			{ SC_AC_OP_DELETE,       "DELETE"       },
			{ SC_AC_OP_CREATE,       "CREATE"       },
			{ SC_AC_OP_REHABILITATE, "REHABILITATE" },
			{ SC_AC_OP_INVALIDATE,   "INVALIDATE"   },
			{ SC_AC_OP_LIST_FILES,   "LIST FILES"   },
			{ SC_AC_OP_CRYPTO,       "CRYPTO"       },
			{ SC_AC_OP_DELETE_SELF,  "DELETE SELF"  },
			{ 0, NULL }
		};

		if (file->namelen) {
			printf("%-15s", "DF name:");
			util_print_binary(stdout, file->name, file->namelen);
			printf("\n");
		}

		ac_ops = ac_ops_df;
	} else {
		static const id2str_t ac_ops_ef[] = {
			{ SC_AC_OP_READ,         "READ"         },
			{ SC_AC_OP_UPDATE,       "UPDATE"       },
			{ SC_AC_OP_DELETE,       "DELETE"       },
			{ SC_AC_OP_WRITE,        "WRITE"        },
			{ SC_AC_OP_REHABILITATE, "REHABILITATE" },
			{ SC_AC_OP_INVALIDATE,   "INVALIDATE"   },
			{ SC_AC_OP_LIST_FILES,   "LIST FILES"   },
			{ SC_AC_OP_CRYPTO,       "CRYPTO"       },
			{ 0, NULL }
		};
		const id2str_t ef_type_name[] = {
			{ SC_FILE_EF_TRANSPARENT,         "Transparent"                 },
			{ SC_FILE_EF_LINEAR_FIXED,        "Linear fixed"                },
			{ SC_FILE_EF_LINEAR_FIXED_TLV,    "Linear fixed, SIMPLE-TLV"    },
			{ SC_FILE_EF_LINEAR_VARIABLE,     "Linear variable"             },
			{ SC_FILE_EF_LINEAR_VARIABLE_TLV, "Linear variable, SIMPLE-TLV" },
			{ SC_FILE_EF_CYCLIC,              "Cyclic"                      },
			{ SC_FILE_EF_CYCLIC_TLV,          "Cyclic, SIMPLE-TLV"          },
			{ 0, NULL }
		};
		const char *ef_type = "Unknown";

		for (i = 0; ef_type_name[i].str != NULL; i++)
			if (file->ef_structure == ef_type_name[i].id)
				ef_type = ef_type_name[i].str;
		printf("%-15s%s\n", "EF structure:", ef_type);

		ac_ops = ac_ops_ef;
	}

	for (i = 0; ac_ops != NULL && ac_ops[i].str != NULL; i++) {
		int len = strlen(ac_ops[i].str);

		printf("ACL for %s:%*s %s\n",
			ac_ops[i].str,
			(12 > len) ? (12 - len) : 0, "",
			util_acl_to_str(sc_file_get_acl_entry(file, ac_ops[i].id)));
	}

	if (file->prop_attr_len) {
		printf("%-25s", "Proprietary attributes:");
		util_hex_dump(stdout, file->prop_attr, file->prop_attr_len, " ");
		printf("\n");
	}
	if (file->sec_attr_len) {
		printf("%-25s", "Security attributes:");
		util_hex_dump(stdout, file->sec_attr, file->sec_attr_len, " ");
		printf("\n");
	}
	printf("\n");
	if (not_current) {
		sc_file_free(file);
		select_current_path_or_die();
	}
	return 0;
}
Beispiel #26
0
int sc_enum_apps(sc_card_t *card)
{
	struct sc_context *ctx = card->ctx;
	sc_path_t path;
	int ef_structure;
	size_t file_size, jj;
	int r, ii, idx;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
	if (card->app_count < 0)
		card->app_count = 0;

	sc_format_path("3F002F00", &path);
	if (card->ef_dir != NULL) {
		sc_file_free(card->ef_dir);
		card->ef_dir = NULL;
	}
	r = sc_select_file(card, &path, &card->ef_dir);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select EF.DIR file");

	if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
		sc_file_free(card->ef_dir);
		card->ef_dir = NULL;
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD, "EF(DIR) is not a working EF.");
	}
	ef_structure = card->ef_dir->ef_structure;
	file_size = card->ef_dir->size;
	if (file_size == 0)
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 0);

	if (ef_structure == SC_FILE_EF_TRANSPARENT) {
		u8 *buf = NULL, *p;
		size_t bufsize;
		
		buf = malloc(file_size);
		if (buf == NULL)
			SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
		p = buf;
		r = sc_read_binary(card, 0, buf, file_size, 0);
		if (r < 0) {
			free(buf);
			SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_read_binary() failed");
		}
		bufsize = r;
		while (bufsize > 0) {
			if (card->app_count == SC_MAX_CARD_APPS) {
				sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card");
				break;
			}
			r = parse_dir_record(card, &p, &bufsize, -1);
			if (r)
				break;
		}
		if (buf)
			free(buf);

	} 
	else {	/* record structure */
		u8 buf[256], *p;
		unsigned int rec_nr;
		size_t       rec_size;
		
		for (rec_nr = 1; ; rec_nr++) {
			r = sc_read_record(card, rec_nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
			if (r == SC_ERROR_RECORD_NOT_FOUND)
				break;
			SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read_record() failed");
			if (card->app_count == SC_MAX_CARD_APPS) {
				sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card");
				break;
			}
			rec_size = r;
			p = buf;
			parse_dir_record(card, &p, &rec_size, (int)rec_nr);
		}
	}

	/* Move known PKCS#15 applications to the head of the list */
	for (ii=0, idx=0; ii<card->app_count; ii++)   {
		for (jj=0; jj < sizeof(apps)/sizeof(apps[0]); jj++) {
			if (apps[jj].aid_len != card->app[ii]->aid.len)
				continue;
			if (memcmp(apps[jj].aid, card->app[ii]->aid.value, apps[jj].aid_len))
				continue;
			break;
		}

		if (ii != idx && jj < sizeof(apps)/sizeof(apps[0]))   {
			struct sc_app_info *tmp = card->app[idx];

			card->app[idx] = card->app[ii];
			card->app[ii] = tmp;
			idx++;
		}
	}

	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
}
Beispiel #27
0
static int
sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
		unsigned char **out, size_t *out_len,
		int verify_pin)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_card *card = p15card->card;
	struct sc_file *file = NULL;
	struct sc_path path;
	size_t sz;
	int rv;

	LOG_FUNC_CALLED(ctx);
	if (!in_path || !out || !out_len)
		LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file");

	sc_log(ctx, "read file '%s'; verify_pin:%i", in_path, verify_pin);

	*out = NULL;
	*out_len = 0;

	sc_format_path(in_path, &path);
	rv = sc_select_file(card, &path, &file);
	LOG_TEST_RET(ctx, rv, "Cannot select oberthur file to read");

	if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
		sz = file->size;
	else
		sz = (file->record_length + 2) * file->record_count;

	*out = calloc(sz, 1);
	if (*out == NULL)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot read oberthur file");

	if (file->ef_structure == SC_FILE_EF_TRANSPARENT)   {
		rv = sc_read_binary(card, 0, *out, sz, 0);
	}
	else	{
		int rec;
		int offs = 0;
		int rec_len = file->record_length;

		for (rec = 1; ; rec++)   {
			rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR);
			if (rv == SC_ERROR_RECORD_NOT_FOUND)   {
				rv = 0;
				break;
			}
			else if (rv < 0)   {
				break;
			}

			rec_len = rv;

			*(*out + offs) = 'R';
			*(*out + offs + 1) = rv;

			offs += rv + 2;
		}

		sz = offs;
	}

	sc_log(ctx, "read oberthur file result %i", rv);
	if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   {
		struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
		const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
		int ii;

		rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
		LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error");

		for (ii=0; ii<rv; ii++)   {
			struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
			sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
					auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
			if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method)   {
				pin_obj = objs[ii];
				break;
			}
		}

		if (!pin_obj || !pin_obj->content.value)    {
			rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
		}
		else    {
			rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len);
			if (!rv)
				rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0);
		}
	};

	sc_file_free(file);

	if (rv < 0)   {
		free(*out);
		*out = NULL;
		*out_len = 0;
	}

	*out_len = sz;

	LOG_FUNC_RETURN(ctx, rv);
}
Beispiel #28
0
/*
 * Store a private key
 */
static int
myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
		struct sc_pkcs15_object *object,
		struct sc_pkcs15_prkey *prkey) {
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_card *card = p15card->card;
	struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
	struct sc_cardctl_myeid_gen_store_key_info args;
	struct sc_file *file = NULL;
	int r, keybits = key_info->modulus_length;

	LOG_FUNC_CALLED(ctx);
	
	switch (object->type) {
		case SC_PKCS15_TYPE_PRKEY_RSA:
			if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL)
				LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size");
			break;
		case SC_PKCS15_TYPE_PRKEY_EC:
			if (sc_card_find_ec_alg(p15card->card, keybits) == NULL)
				LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size");
			if(key_info->field_length != 0)
				keybits = key_info->field_length;
			else 
				key_info->field_length = keybits;
				
			break;
		default:
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type");
			break;
	}
	
	sc_log(ctx, "store MyEID key with ID:%s and path:%s",
			sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path));

	r = sc_select_file(card, &key_info->path, &file);
	LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed");

	r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
	LOG_TEST_RET(ctx, r, "No authorisation to store MyEID private key");

	if (file)
		sc_file_free(file);

	/* Fill in data structure */
	memset(&args, 0, sizeof (args));

	args.op_type = OP_TYPE_STORE;
	if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) {
		//args.key_len_bits = keybits;
		args.key_type = SC_CARDCTL_MYEID_KEY_RSA;
		args.pubexp_len = prkey->u.rsa.exponent.len;
		args.pubexp = prkey->u.rsa.exponent.data;
		args.primep_len = prkey->u.rsa.p.len;
		args.primep = prkey->u.rsa.p.data;
		args.primeq_len = prkey->u.rsa.q.len;
		args.primeq = prkey->u.rsa.q.data;

		args.dp1_len = prkey->u.rsa.dmp1.len;
		args.dp1 = prkey->u.rsa.dmp1.data;
		args.dq1_len = prkey->u.rsa.dmq1.len;
		args.dq1 = prkey->u.rsa.dmq1.data;
		args.invq_len = prkey->u.rsa.iqmp.len;
		args.invq = prkey->u.rsa.iqmp.data;

		args.key_len_bits = prkey->u.rsa.modulus.len;
		args.mod = prkey->u.rsa.modulus.data;
	}
	else {
		args.key_type = SC_CARDCTL_MYEID_KEY_EC;
		args.d = prkey->u.ec.privateD.data;
		args.d_len = prkey->u.ec.privateD.len;
		args.ecpublic_point = prkey->u.ec.ecpointQ.value;
		args.ecpublic_point_len = prkey->u.ec.ecpointQ.len;
		args.key_len_bits = prkey->u.ec.params.field_length;
	}
	/* Store RSA key  */
	r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args);
	LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed");

	LOG_FUNC_RETURN(ctx, r);
}
Beispiel #29
0
/*
 * Verify a PIN.
 *
 * If the code given to us has zero length, this means we
 * should ask the card reader to obtain the PIN from the
 * reader's PIN pad
 */
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
			 struct sc_pkcs15_object *pin_obj,
			 const unsigned char *pincode, size_t pinlen)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
	int r;
	sc_card_t *card;
	struct sc_pin_cmd_data data;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN(%p;len:%i)", pincode, pinlen);

	/* TODO: verify other authentication objects */
	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_NOT_SUPPORTED;

	r = _validate_pin(p15card, auth_info, pinlen);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "PIN value do not conforms the PIN policy");

	card = p15card->card;

	r = sc_lock(card);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed");
	/* the path in the pin object is optional */
	if (auth_info->path.len > 0) {
		r = sc_select_file(card, &auth_info->path, NULL);
		if (r)
			goto out;
	}

	/* Initialize arguments */
	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;
	data.pin_type = auth_info->auth_method;
	data.pin_reference = auth_info->attrs.pin.reference;
	data.pin1.min_length = auth_info->attrs.pin.min_length;
	data.pin1.max_length = auth_info->attrs.pin.max_length;
	data.pin1.pad_length = auth_info->attrs.pin.stored_length;
	data.pin1.pad_char = auth_info->attrs.pin.pad_char;
	data.pin1.data = pincode;
	data.pin1.len = pinlen;

	if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
		data.flags |= SC_PIN_CMD_NEED_PADDING;

	switch (auth_info->attrs.pin.type) {
	case SC_PKCS15_PIN_TYPE_BCD:
		data.pin1.encoding = SC_PIN_ENCODING_BCD;
		break;
	case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
		data.pin1.encoding = SC_PIN_ENCODING_ASCII;
		break;
	default:
		/* assume/hope the card driver knows how to encode the pin */
		data.pin1.encoding = 0;
	}

	if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
		if (!pincode && !pinlen)
			data.flags |= SC_PIN_CMD_USE_PINPAD;
		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
			data.pin1.prompt = "Please enter SO PIN";
		else
			data.pin1.prompt = "Please enter PIN";
	}

	r = sc_pin_cmd(card, &data, &auth_info->tries_left);
	if (r == SC_SUCCESS)
		sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen);
out:
	sc_unlock(card);
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}
Beispiel #30
0
static int
sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
{
	sc_card_t *card = p15card->card;
	unsigned char buff[128];
	int r, i;
	sc_path_t tmppath;

	set_string (&p15card->tokeninfo->label, "ID-kaart");
	set_string (&p15card->tokeninfo->manufacturer_id, "AS Sertifitseerimiskeskus");

	/* Select application directory */
	sc_format_path ("3f00eeee5044", &tmppath);
	r = sc_select_file (card, &tmppath, NULL);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "select esteid PD failed");

	/* read the serial (document number) */	
	r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed");
	buff[r] = '\0';
	set_string (&p15card->tokeninfo->serial_number, (const char *) buff);

	p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION
				  | SC_PKCS15_TOKEN_EID_COMPLIANT
				  | SC_PKCS15_TOKEN_READONLY;

	/* add certificates */
	for (i = 0; i < 2; i++) {
		static const char *esteid_cert_names[2] = {
			"Isikutuvastus",
			"Allkirjastamine"};
		static char const *esteid_cert_paths[2] = {
			"3f00eeeeaace",
			"3f00eeeeddce"};
		static int esteid_cert_ids[2] = {1, 2};
			
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object cert_obj;
		
		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj, 0, sizeof(cert_obj));

		cert_info.id.value[0] = esteid_cert_ids[i];
		cert_info.id.len = 1;
		sc_format_path(esteid_cert_paths[i], &cert_info.path);
		strlcpy(cert_obj.label, esteid_cert_names[i], sizeof(cert_obj.label));
		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
#ifdef ENABLE_OPENSSL
		if (i == 0) {
			BIO *mem = NULL;
			X509 *x509 = NULL;
			sc_pkcs15_cert_t *cert;
			char cardholder_name[64];
			unsigned char *tmp = NULL;
			r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert);
			if (r == SC_SUCCESS) {
				mem = BIO_new_mem_buf(cert->data.value, cert->data.len);
				if (!mem) {
					sc_pkcs15_free_certificate(cert);
					return SC_ERROR_INTERNAL;
				}
				x509 = d2i_X509_bio(mem, NULL);
				BIO_free(mem);
				sc_pkcs15_free_certificate(cert);
				if (!x509)
					return SC_ERROR_INTERNAL;
				r = X509_NAME_get_index_by_NID(X509_get_subject_name(x509), NID_commonName, -1);
				if (r >= 0) {
					X509_NAME_ENTRY *ne;
					ASN1_STRING *a_str;
					ne = X509_NAME_get_entry(X509_get_subject_name(x509), r);
					if (!ne) {
						X509_free(x509);
						return SC_ERROR_INTERNAL;
					}
					a_str = X509_NAME_ENTRY_get_data(ne);
					if (!a_str) {
						X509_free(x509);
						return SC_ERROR_INTERNAL;
					}
					r = ASN1_STRING_to_UTF8(&tmp, a_str);
					if (r > 0) {
						if ((unsigned)r > sizeof(cardholder_name) - 1)
							r = sizeof(cardholder_name) -1;
						memcpy(cardholder_name, tmp, r);
						cardholder_name[r] = '\0';
						set_string(&p15card->tokeninfo->label, cardholder_name);
						OPENSSL_free(tmp);
					}
				}
				X509_free(x509);
			}
		}
#endif
	}

	/* the file with key pin info (tries left) */
	sc_format_path ("3f000016", &tmppath);
	r = sc_select_file (card, &tmppath, NULL);
	if (r < 0)
		return SC_ERROR_INTERNAL;

	/* add pins */
	for (i = 0; i < 3; i++) {
		unsigned char tries_left;
		static const char *esteid_pin_names[3] = {
			"PIN1",
			"PIN2",
			"PUK" };
			
		static const int esteid_pin_min[3] = {4, 5, 8};
		static const int esteid_pin_ref[3] = {1, 2, 0};
		static const int esteid_pin_authid[3] = {1, 2, 3};
		static const int esteid_pin_flags[3] = {0, 0, SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN};
		
		struct sc_pkcs15_auth_info pin_info;
		struct sc_pkcs15_object pin_obj;

		memset(&pin_info, 0, sizeof(pin_info));
		memset(&pin_obj, 0, sizeof(pin_obj));
		
		/* read the number of tries left for the PIN */
		r = sc_read_record (card, i + 1, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
		if (r < 0)
			return SC_ERROR_INTERNAL;
		tries_left = buff[5];
		
		pin_info.auth_id.len = 1;
		pin_info.auth_id.value[0] = esteid_pin_authid[i];
		pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;	
		pin_info.attrs.pin.reference = esteid_pin_ref[i];
		pin_info.attrs.pin.flags = esteid_pin_flags[i];
		pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
		pin_info.attrs.pin.min_length = esteid_pin_min[i];
		pin_info.attrs.pin.stored_length = 12;
		pin_info.attrs.pin.max_length = 12;
		pin_info.attrs.pin.pad_char = '\0';
		pin_info.tries_left = (int)tries_left;
		pin_info.max_tries = 3;

		strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label));
		pin_obj.flags = esteid_pin_flags[i];

		/* Link normal PINs with PUK */
		if (i < 2) {
			pin_obj.auth_id.len = 1;
			pin_obj.auth_id.value[0] = 3;
		}

		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
	}
	
	/* add private keys */
	for (i = 0; i < 2; i++) {
		static int prkey_pin[2] = {1, 2};
		static int prkey_usage[2] = {
			SC_PKCS15_PRKEY_USAGE_ENCRYPT
			| SC_PKCS15_PRKEY_USAGE_DECRYPT
			| SC_PKCS15_PRKEY_USAGE_SIGN,
			SC_PKCS15_PRKEY_USAGE_NONREPUDIATION};
			
		static const char *prkey_name[2] = {
			"Isikutuvastus",
			"Allkirjastamine"};

		struct sc_pkcs15_prkey_info prkey_info;
		struct sc_pkcs15_object prkey_obj;

		memset(&prkey_info, 0, sizeof(prkey_info));
		memset(&prkey_obj, 0, sizeof(prkey_obj));
		
		prkey_info.id.len = 1;
		prkey_info.id.value[0] = prkey_pin[i];
		prkey_info.usage  = prkey_usage[i];
		prkey_info.native = 1;
		prkey_info.key_reference = i + 1;
		if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30)
			prkey_info.modulus_length = 2048;
		else
			prkey_info.modulus_length = 1024;	

		strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label));
		prkey_obj.auth_id.len = 1;
		prkey_obj.auth_id.value[0] = prkey_pin[i];
		prkey_obj.user_consent = 0;
		prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;

		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
	}

	return SC_SUCCESS;
}