static int infocamere_1400_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[16];
	int flags;
	int r;
	int hasAuthCert = 0;

	const char *certLabel[] = { "User Non-repudiation Certificate",
		"User Authentication Certificate",
		"CA Certificate"
	};

	const char *certPath[] =
	    { "300060000000", "300060000001", "300060000002" };

	const char *pinLabel[] =
	    { "Non-repudiation PIN", "Authentication PIN" };
	int retries[] = { 3, -1 };

	const char *keyPath[] = { "30004000001", "30004000002" };
	const char *keyLabel[] =
	    { "Non repudiation Key", "Authentication Key" };
	static int usage[] = { SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
		SC_PKCS15_PRKEY_USAGE_SIGN
		    | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
		    | SC_PKCS15_PRKEY_USAGE_ENCRYPT
		    | SC_PKCS15_PRKEY_USAGE_DECRYPT
	};

	auth_id.len = 1;
	id.len = 1;

	/* OpenSC doesn't define constants to identify BSOs for
	 * restoring security environment, so we overload
	 * the set_security_env function to support restore_sec_env */
	set_security_env = card->ops->set_security_env;
	card->ops->set_security_env = infocamere_1400_set_sec_env;
	card->ops->compute_signature = do_sign;
	p15card->opts.use_cache = 1;

	sc_format_path("30000001", &path);

	r = sc_select_file(card, &path, NULL);
	
	if (r != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;

	sc_read_binary(card, 15, serial, 15, 0);
	serial[15] = '\0';

	set_string(&p15card->serial_number, (char *)serial);
	set_string(&p15card->label, "Infocamere 1400 Card");
	set_string(&p15card->manufacturer_id, "Infocamere");

	if ((r = loadCertificate(p15card, 0, certPath[0], certLabel[0])) !=
	    SC_SUCCESS) {
		sc_error(p15card->card->ctx, "%s", sc_strerror(r));
		return SC_ERROR_WRONG_CARD;
	}

	hasAuthCert =
	    loadCertificate(p15card, 1, certPath[1],
			    certLabel[1]) == SC_SUCCESS;
	loadCertificate(p15card, 2, certPath[2], certLabel[2]);

	flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED |
	    SC_PKCS15_PIN_FLAG_NEEDS_PADDING;

	/* adding PINs & private keys */

	sc_format_path("30004000", &path);
	id.value[0] = 1;

	sc_pkcs15emu_add_pin(p15card, &id,
			     pinLabel[0], &path, 1,
			     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
			     5, 8, flags, retries[0], 0,
			     SC_PKCS15_CO_FLAG_MODIFIABLE |
			     SC_PKCS15_CO_FLAG_PRIVATE);

	sc_format_path(keyPath[0], &path);
	auth_id.value[0] = 1;
	sc_pkcs15emu_add_prkey(p15card, &id,
			       keyLabel[0],
			       SC_PKCS15_TYPE_PRKEY_RSA,
			       1024, usage[0],
			       &path, 1,
			       &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);


	if (hasAuthCert) {
		sc_format_path("30004000", &path);
		id.value[0] = 2;

		sc_pkcs15emu_add_pin(p15card, &id,
				     pinLabel[1], &path, 2,
				     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
				     5, 8, flags, retries[1], 0,
				     SC_PKCS15_CO_FLAG_MODIFIABLE |
				     SC_PKCS15_CO_FLAG_PRIVATE);

		sc_format_path(keyPath[1], &path);
		auth_id.value[0] = 2;
		sc_pkcs15emu_add_prkey(p15card, &id,
				       keyLabel[1],
				       SC_PKCS15_TYPE_PRKEY_RSA,
				       1024, usage[1],
				       &path, 2,
				       &auth_id,
				       SC_PKCS15_CO_FLAG_PRIVATE);
	}

	/* return to MF */
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, NULL);
	return r;
	}
static int infocamere_1600_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[17];
	int flags;
	int r;
	int hasAuthCert = 0;

	const char *certLabel[] = { "User Non-repudiation Certificate",
		"User Authentication Certificate"
	};

	const char *certPath[] = { "200020010008", "20002001000E" };

	const char *pinLabel[] =
	    { "Non-repudiation PIN", "Authentication PIN" };
	int retries[] = { 3, -1 };

	const char *keyPath[] = { "200020010004", "20002001000A" };
	const char *keyLabel[] =
	    { "Non repudiation Key", "Authentication Key" };
	static int usage[] = { SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
		SC_PKCS15_PRKEY_USAGE_SIGN
		    | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
		    | SC_PKCS15_PRKEY_USAGE_ENCRYPT
		    | SC_PKCS15_PRKEY_USAGE_DECRYPT
	};

	auth_id.len = 1;
	id.len = 1;

	/* OpenSC doesn't define constants to identify BSOs for
	 * restoring security environment, so we overload
	 * the set_security_env function to support restore_sec_env */
	set_security_env = card->ops->set_security_env;
	card->ops->set_security_env = infocamere_1400_set_sec_env;
	card->ops->compute_signature = do_sign;

	sc_format_path("200020012002", &path);

	r = sc_select_file(card, &path, NULL);

	if (r != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;

	sc_read_binary(card, 30, serial, 16, 0);
	serial[16] = '\0';

	set_string(&p15card->serial_number, (char *) serial);
	set_string(&p15card->label, "Infocamere 1600 Card");
	set_string(&p15card->manufacturer_id, "Infocamere");

	/* Adding certificates.
	 * Certificates are stored in a ZLib compressed form with
	 * a 4 byte header, so we extract, decompress and cache
	 * them.
	 */
	sc_format_path(certPath[0], &path);
	if (sc_select_file(card, &path, NULL) != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;

	id.value[0] = 1;

	sc_pkcs15emu_add_cert(p15card,
			      SC_PKCS15_TYPE_CERT_X509, 0,
			      &path, &id, certLabel[0],
			      SC_PKCS15_CO_FLAG_MODIFIABLE);

	sc_format_path(certPath[1], &path);
	if (sc_select_file(card, &path, NULL) == SC_SUCCESS) {
		hasAuthCert = 1;

		id.value[0] = 2;

		sc_pkcs15emu_add_cert(p15card,
				      SC_PKCS15_TYPE_CERT_X509, 1,
				      &path, &id, certLabel[1],
				      SC_PKCS15_CO_FLAG_MODIFIABLE);
	}

	flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED |
	    SC_PKCS15_PIN_FLAG_NEEDS_PADDING;

	/* adding PINs & private keys */
	sc_format_path("2000", &path);
	id.value[0] = 1;

	sc_pkcs15emu_add_pin(p15card, &id,
			     pinLabel[0], &path, 1,
			     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
			     5, 8, flags, retries[0], 0,
			     SC_PKCS15_CO_FLAG_MODIFIABLE |
			     SC_PKCS15_CO_FLAG_PRIVATE);

	sc_format_path(keyPath[0], &path);
	auth_id.value[0] = 1;
	sc_pkcs15emu_add_prkey(p15card, &id,
			       keyLabel[0],
			       SC_PKCS15_TYPE_PRKEY_RSA,
			       1024, usage[0],
			       &path, 1,
			       &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);

	if (hasAuthCert) {
		id.value[0] = 2;

		sc_pkcs15emu_add_pin(p15card, &id,
				     pinLabel[1], &path, 2,
				     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
				     5, 8, flags, retries[1], 0,
				     SC_PKCS15_CO_FLAG_MODIFIABLE |
				     SC_PKCS15_CO_FLAG_PRIVATE);

		sc_format_path(keyPath[1], &path);
		auth_id.value[0] = 2;
		sc_pkcs15emu_add_prkey(p15card, &id,
				       keyLabel[1],
				       SC_PKCS15_TYPE_PRKEY_RSA,
				       1024, usage[1],
				       &path, 2,
				       &auth_id,
				       SC_PKCS15_CO_FLAG_PRIVATE);
	}

	/* return to MF */
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, NULL);

	return SC_SUCCESS;
}
static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
{
	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;

	sc_card_t *card = p15card->card;
	sc_path_t path;
	sc_file_t *file;
	sc_pkcs15_id_t id, auth_id;
	unsigned char buffer[256];
	unsigned char ef_gdo[256];
	char serial[256];
	unsigned char certlen[2];
	int authority, change_sign = 0;
	struct sc_pkcs15_cert_info cert_info;
        struct sc_pkcs15_object    cert_obj;

	const char *label = "User Non-repudiation Certificate";
	const char *calabel = "CA Certificate";
	const char *authlabel = "User Authentication Certificate";

	const char *infocamere_cert_path[2] = {
		"DF01C000",
		"3F00000011111A02"
	};

	const char *infocamere_auth_certpath[2] = {
		"11111A02",
		"000011111B02"
	};

	const char *infocamere_cacert_path[2] = {
		"DF01C008",
		"000011114101"
	};

	const char *infocamere_auth_path[2] = {
		"3F001111",
		"3F0000001111"
	};

	const char *infocamere_nrepud_path[2] = {
		"3F00DF01",
		"3F0000001111"
	};

	const int infocamere_idpin_auth_obj[2] = {
		0x95,
		0x81
	};

	const int infocamere_idpin_nrepud_obj[2] = {
		0x99,
		0x81
	};

	const int infocamere_idprkey_auth_obj[2] = {
		0x9B,
		0x01
	};

	const int infocamere_idprkey_nrepud_obj[2] = {
		0x84,
		0x01
	};

	const char *authPIN = "Authentication PIN";
	const char *nonrepPIN = "Non-repudiation PIN";

	const char *authPRKEY = "Authentication Key";
	const char *nonrepPRKEY = "Non repudiation Key";

	const int flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED |
	    SC_PKCS15_PIN_FLAG_NEEDS_PADDING;

	int r, len_iccsn, len_chn;

	sc_format_path("3F002F02", &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, &file);
	sc_ctx_suppress_errors_off(card->ctx);
	
	if (r != SC_SUCCESS || file->size > 255) {
		/* Not EF.GDO */
		return SC_ERROR_WRONG_CARD;
	}

	sc_read_binary(card, 0, ef_gdo, file->size, 0);

	if (ef_gdo[0] != 0x5A || file->size < 3) {
		/* Not EF.GDO */
		return SC_ERROR_WRONG_CARD;
	}

	len_iccsn = ef_gdo[1];

	memcpy(buffer, ef_gdo + 2, len_iccsn);

	sc_bin_to_hex(buffer, len_iccsn, serial, sizeof(serial), 0);

	if (file->size < (size_t) (len_iccsn + 5)) {
		/* Not CHN */
		return SC_ERROR_WRONG_CARD;
	}

	if (!
	    (ef_gdo[len_iccsn + 2] == 0x5F
	     && ef_gdo[len_iccsn + 3] == 0x20)) {
		/* Not CHN */
		return SC_ERROR_WRONG_CARD;
	}

	len_chn = ef_gdo[len_iccsn + 4];

	if (len_chn < 2 || len_chn > 8) {
		/* Length CHN incorrect */
		return SC_ERROR_WRONG_CARD;
	}

	if (!
	    (ef_gdo[len_iccsn + 5] == 0x12
	     && (ef_gdo[len_iccsn + 6] == 0x02
		 || ef_gdo[len_iccsn + 6] == 0x03))) {
		/* Not Infocamere Card */
		return SC_ERROR_WRONG_CARD;
	}

	set_string(&p15card->serial_number, serial);

	if (ef_gdo[len_iccsn + 6] == 0x02)
		set_string(&p15card->label, "Infocamere 1202 Card");
	else {
		set_string(&p15card->label, "Infocamere 1203 Card");
		change_sign = 1;
	}

	set_string(&p15card->manufacturer_id, "Infocamere");

	authority = 0;

	/* Get the authentication certificate length */

	sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);

	if (r >= 0) {

		sc_read_binary(card, 0, certlen, 2, 0);

		/* Now set the certificate offset/len */

		path.index = 2;
		path.count = (certlen[1] << 8) + certlen[0];

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

		sc_pkcs15_format_id("1", &cert_info.id);
        	cert_info.authority = authority;
        	cert_info.path = path;
		strlcpy(cert_obj.label, authlabel, sizeof(cert_obj.label));
	        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        	if (r < 0)
        		return SC_ERROR_INTERNAL;

		/* XXX: the IDs for the key/pin in case of the 1203 type 
		 * are wrong, therefore I disable them for now -- Nils */
		if (!change_sign) {    
		/* add authentication PIN */

                sc_format_path(infocamere_auth_path[ef_gdo[len_iccsn+6]-2], &path);
                
		sc_pkcs15_format_id("1", &id);
		sc_pkcs15emu_add_pin(p15card, &id,
                                authPIN, &path, infocamere_idpin_auth_obj[ef_gdo[len_iccsn+6]-2],
                                SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
                                5, 8, flags, 3, 0, 
				SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);

		/* add authentication private key */

		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, infocamere_idprkey_auth_obj[ef_gdo[len_iccsn+6]-2],
				&auth_id, SC_PKCS15_CO_FLAG_PRIVATE);
		}

	}

	/* Get the non-repudiation certificate length */

	sc_format_path(infocamere_cert_path[ef_gdo[len_iccsn+6]-2], &path);

	if (sc_select_file(card, &path, NULL) < 0)
		{
		return SC_ERROR_INTERNAL;
		}

	sc_read_binary(card, 0, certlen, 2, 0);

	/* Now set the certificate offset/len */
	path.index = 2;
	path.count = (certlen[1] << 8) + certlen[0];
	
        memset(&cert_info, 0, sizeof(cert_info));
        memset(&cert_obj,  0, sizeof(cert_obj));

	sc_pkcs15_format_id("2", &cert_info.id);

        cert_info.authority = authority;
        cert_info.path = path;
        strlcpy(cert_obj.label, label, sizeof(cert_obj.label));
        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

	r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        if (r < 0)
        	return SC_ERROR_INTERNAL;

	/* Get the CA certificate length */

	authority = 1;

	sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);

	if (r >= 0) {
		size_t len;

		sc_read_binary(card, 0, certlen, 2, 0);

		len = (certlen[1] << 8) + certlen[0];

		if (len != 0) {
			/* Now set the certificate offset/len */
			path.index = 2;
			path.count = len;

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

			sc_pkcs15_format_id("3", &cert_info.id);
	        	cert_info.authority = authority;
	        	cert_info.path = path;
	        	strlcpy(cert_obj.label, calabel, sizeof(cert_obj.label));
		        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

			r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        		if (r < 0)
        		return SC_ERROR_INTERNAL;
		}
	}

        /* add non repudiation PIN */

	sc_format_path(infocamere_nrepud_path[ef_gdo[len_iccsn+6]-2], &path);

	sc_pkcs15_format_id("2", &id);
	sc_pkcs15emu_add_pin(p15card, &id,
		nonrepPIN, &path, infocamere_idpin_nrepud_obj[ef_gdo[len_iccsn+6]-2],
		SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0,
		SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);


	/* add non repudiation private key */

	auth_id.value[0] = 2;
	auth_id.len = 1;

	sc_pkcs15emu_add_prkey(p15card, &id, nonrepPRKEY,
			       SC_PKCS15_TYPE_PRKEY_RSA, 
                               1024, prkey_usage,
                               &path, infocamere_idprkey_nrepud_obj[ef_gdo[len_iccsn+6]-2],
                               &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);


	/* return to MF */
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, NULL);
	if (r != SC_SUCCESS)
		return r;

	if (change_sign) {
		/* 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;
}
static int sc_pkcs15emu_postecert_init(sc_pkcs15_card_t * p15card)
{
	static int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	static int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN
	    | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
	    | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT;

	sc_card_t *card = p15card->card;
	sc_path_t path;
	sc_pkcs15_id_t id, auth_id;
	unsigned char certlen[2];
	unsigned char *certi = NULL;
	int index_cert[4];
	int count_cert[4];
	int flags;
	int authority;
	size_t i, count;
	int r;
	int o = 0;

	const char *label = "User Non-repudiation Certificate";
	const char *calabel = "CA Certificate";
	const char *catmslabel = "CA TimeStamper Certificate";
	const char *authlabel = "User Authentication Certificate";

	const char *postecert_auth_cert_path = "504B0001";

	const char *authPIN = "Authentication PIN";
	const char *nonrepPIN = "Non-repudiation PIN";

	const char *authPRKEY = "Authentication Key";
	const char *nonrepPRKEY = "Non repudiation Key";

	/* Get the non-repudiation certificate length */
	sc_format_path(postecert_auth_cert_path, &path);

	if (sc_select_file(card, &path, NULL) < 0) {
		r = SC_ERROR_WRONG_CARD;
		goto failed;
	}

	set_string(&p15card->label, "Postecert & Cnipa Card");
	set_string(&p15card->manufacturer_id, "Postecert");
	set_string(&p15card->serial_number, "0000");

	sc_read_binary(card, 0, certlen, 2, 0);

	/* Now set the certificate offset/len */
	count = (certlen[0] << 8) + certlen[1];
	if (count < 256)
		return SC_ERROR_INTERNAL;

	certi = (unsigned char *) malloc(count);

	if (!certi)
		return SC_ERROR_OUT_OF_MEMORY;

	sc_read_binary(card, 0, certi, count - 500, 0);

	for (i = 2; i < (count - 256); i++) {
		/* this file contain more than one certificate */
		if (*(certi + i) == 0x30 && *(certi + i + 1) == 0x82
		    && *(certi + i + 4) == 0x30 && *(certi + i + 5) == 0x82
		    && *(certi + i + 2) > 1 && *(certi + i + 2) < 8
		    && *(certi + i + 6) <= *(certi + i + 2)) {
			index_cert[o] = i;
			count_cert[o] =
			    (*(certi + i + 2) << 8) + *(certi + i + 3) + 4;
			o++;
			if (o > 4)
				break;
			i += (*(certi + i + 2) << 8) + *(certi + i + 3);
		}
	}

	free(certi);

	path.index = index_cert[0];
	path.count = count_cert[0];

	id.value[0] = 1;
	id.len = 1;

	authority = 1;

	sc_pkcs15emu_add_cert(p15card,
			      SC_PKCS15_TYPE_CERT_X509, authority,
			      &path, &id, calabel, SC_PKCS15_CO_FLAG_MODIFIABLE);

	path.index = index_cert[1];
	path.count = count_cert[1];

	id.value[0] = 2;
	id.len = 1;

	authority = 1;

	sc_pkcs15emu_add_cert(p15card,
			      SC_PKCS15_TYPE_CERT_X509, authority,
			      &path, &id, catmslabel, SC_PKCS15_CO_FLAG_MODIFIABLE);

	path.index = index_cert[2];
	path.count = count_cert[2];

	id.value[0] = 3;
	id.len = 1;

	authority = 0;

	sc_pkcs15emu_add_cert(p15card,
			      SC_PKCS15_TYPE_CERT_X509, authority,
			      &path, &id, label, SC_PKCS15_CO_FLAG_MODIFIABLE);

	path.index = index_cert[3];
	path.count = count_cert[3];

	id.value[0] = 4;
	id.len = 1;

	sc_pkcs15emu_add_cert(p15card,
			      SC_PKCS15_TYPE_CERT_X509, authority,
			      &path, &id, authlabel, SC_PKCS15_CO_FLAG_MODIFIABLE);


	flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING;

	/* add authentication PIN */
	sc_format_path("3F00504B", &path);
	id.value[0] = 1;
	sc_pkcs15emu_add_pin(p15card, &id,
			     authPIN, &path, 0x82,
			     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
			     6, 14, flags, 3, 0,
			     SC_PKCS15_CO_FLAG_MODIFIABLE |
			     SC_PKCS15_CO_FLAG_PRIVATE);

	/* add authentication private key */
	id.value[0] = 4;
	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, 0x06, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);

	/* add non repudiation PIN */
	sc_format_path("3F00504B", &path);
	id.value[0] = 2;
	sc_pkcs15emu_add_pin(p15card, &id,
			     nonrepPIN, &path, 0x82,
			     SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
			     6, 14, flags, 3, 0,
			     SC_PKCS15_CO_FLAG_MODIFIABLE |
			     SC_PKCS15_CO_FLAG_PRIVATE);


	/* add non repudiation private key */
	id.value[0] = 3;
	auth_id.value[0] = 2;
	sc_pkcs15emu_add_prkey(p15card, &id,
			       nonrepPRKEY,
			       SC_PKCS15_TYPE_PRKEY_RSA,
			       1024, prkey_usage,
			       &path, 0x01, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);

	/* return to MF */
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, NULL);
	if (r != SC_SUCCESS)
		return r;

	{
		/* 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 0;

failed:
	sc_error(card->ctx,
		 "Failed to initialize Postecert and Cnipa emulation: %s\n",
		 sc_strerror(r));
	return r;
}
Beispiel #5
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 #6
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;
}
static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
{
    const char *fn_name = "sc_pkcs15emu_gemsafe_init";

    int    r, i;
	int	   key_ref = 0x03; 
    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];
    char * endptr;
    float version=0.0;

    sc_debug(p15card->card->ctx, "%s: Setting pkcs15 parameters\n", fn_name);

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

    if (p15card->serial_number)
	    free(p15card->serial_number);
    p15card->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1);
    if (!p15card->serial_number)
	    return SC_ERROR_INTERNAL;
    strcpy(p15card->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, r, "APDU transmit failed");
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
	    return SC_ERROR_INTERNAL;
    if (r != SC_SUCCESS)
	    return SC_ERROR_INTERNAL;
    endptr = (char *)(apdu.resp + apdu.resplen);
    version = strtod( (const char *)(apdu.resp + 4), &endptr);
    sc_debug(p15card->card->ctx, "%s: version (float): %f, version (int): %d\n",
    	    fn_name, version, (int)version);
    p15card->version = (int)version;

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

    /* set certs */
    sc_debug(p15card->card->ctx, "%s: Setting certificate\n", fn_name);
    for (i = 0; gemsafe_cert[i].label; i++) {
	    struct sc_pkcs15_id  p15Id;

	    sc_format_path(gemsafe_cert[i].path, &path);
	    if (!gemsafe_get_cert_len(card, &path, &key_ref))
		    /* skip errors */
		    continue;
	    sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id);
	    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, "%s: Setting PIN\n", fn_name);
    for (i = 0; gemsafe_pin[i].label; i++) {
	    struct sc_pkcs15_id  p15Id;

	    sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id);
	    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);
    }
    /* set private keys */
    sc_debug(p15card->card->ctx, "%s: Setting private key\n", fn_name);
    for (i = 0; gemsafe_prkeys[i].label; i++) {
	    struct sc_pkcs15_id p15Id,
				authId, *pauthId;
	    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;
			/*
			 * 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,
					"Overriding key_ref  with %d\n", key_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,"%s: Selecting application DF\n", fn_name);
    sc_format_path("3F001600", &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;

}