Example #1
0
static int read_ssh_key(void)
{
	int r;
	struct sc_pkcs15_id id;
	struct sc_pkcs15_object *obj;
	sc_pkcs15_pubkey_t *pubkey = NULL;
	sc_pkcs15_cert_t *cert = NULL;
        FILE            *outf;

        if (opt_outfile != NULL) {
                outf = fopen(opt_outfile, "w");
                if (outf == NULL) {
                        fprintf(stderr, "Error opening file '%s': %s\n",
                                opt_outfile, strerror(errno));
                        goto fail2;
                }
        } else
                outf = stdout;

	id.len = SC_PKCS15_MAX_ID_SIZE;
	sc_pkcs15_hex_string_to_id(opt_pubkey, &id);

	r = sc_pkcs15_find_pubkey_by_id(p15card, &id, &obj);
	if (r >= 0) {
		if (verbose)
			fprintf(stderr,"Reading ssh key with ID '%s'\n", opt_pubkey);
		r = authenticate(obj);
		if (r >= 0)
			r = sc_pkcs15_read_pubkey(p15card, obj, &pubkey);
	} else if (r == SC_ERROR_OBJECT_NOT_FOUND) {
		/* No pubkey - try if there's a certificate */
		r = sc_pkcs15_find_cert_by_id(p15card, &id, &obj);
		if (r >= 0) {
			if (verbose)
				fprintf(stderr,"Reading certificate with ID '%s'\n", opt_pubkey);
			r = sc_pkcs15_read_certificate(p15card,
				(sc_pkcs15_cert_info_t *) obj->data,
				&cert);
		}
		if (r >= 0)
			pubkey = cert->key;
	}

	if (r == SC_ERROR_OBJECT_NOT_FOUND) {
		fprintf(stderr, "Public key with ID '%s' not found.\n", opt_pubkey);
		return 2;
	}
	if (r < 0) {
		fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
		return 1;
	}

	/* rsa1 keys */
	if (pubkey->algorithm == SC_ALGORITHM_RSA) {
		int bits;
		BIGNUM *bn;
		char *exp,*mod;

		bn = BN_new();
		BN_bin2bn((unsigned char*)pubkey->u.rsa.modulus.data,
				pubkey->u.rsa.modulus.len, bn);
		bits = BN_num_bits(bn);
		exp =  BN_bn2dec(bn);
		BN_free(bn);

		bn = BN_new();
		BN_bin2bn((unsigned char*)pubkey->u.rsa.exponent.data,
				pubkey->u.rsa.exponent.len, bn);
		mod = BN_bn2dec(bn);
		BN_free(bn);

		if (bits && exp && mod) {
			fprintf(outf, "%u %s %s\n", bits,mod,exp);
		} else {
			fprintf(stderr, "decoding rsa key failed!\n");
		}
		OPENSSL_free(exp);
		OPENSSL_free(mod);
	}
	
	/* rsa and des keys - ssh2 */
	/* key_to_blob */

	if (pubkey->algorithm == SC_ALGORITHM_RSA) {
		unsigned char buf[2048];
		unsigned char *uu;
		uint32_t len;
		uint32_t n;

		buf[0]=0;
		buf[1]=0;
		buf[2]=0;
		buf[3]=7;

		len = sprintf((char *) buf+4,"ssh-rsa");
		len+=4;

		if (sizeof(buf)-len < 4+pubkey->u.rsa.exponent.len) 
			goto fail;
		n = pubkey->u.rsa.exponent.len;
		if (pubkey->u.rsa.exponent.data[0] & 0x80) n++;
		buf[len++]=(n >>24) & 0xff;
		buf[len++]=(n >>16) & 0xff;
		buf[len++]=(n >>8) & 0xff;
		buf[len++]=(n) & 0xff;
		if (pubkey->u.rsa.exponent.data[0] & 0x80) 
			buf[len++]= 0;

		memcpy(buf+len,pubkey->u.rsa.exponent.data,
			pubkey->u.rsa.exponent.len);
		len += pubkey->u.rsa.exponent.len;

		if (sizeof(buf)-len < 5+pubkey->u.rsa.modulus.len) 
			goto fail;
		n = pubkey->u.rsa.modulus.len;
		if (pubkey->u.rsa.modulus.data[0] & 0x80) n++;
		buf[len++]=(n >>24) & 0xff;
		buf[len++]=(n >>16) & 0xff;
		buf[len++]=(n >>8) & 0xff;
		buf[len++]=(n) & 0xff;
		if (pubkey->u.rsa.modulus.data[0] & 0x80) 
			buf[len++]= 0;

		memcpy(buf+len,pubkey->u.rsa.modulus.data,
			pubkey->u.rsa.modulus.len);
		len += pubkey->u.rsa.modulus.len;

		uu = malloc(len*2);
		r = sc_base64_encode(buf, len, uu, 2*len, 2*len);

		fprintf(outf,"ssh-rsa %s", uu);
		free(uu);

	}
Example #2
0
static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
{
	int i, r;
	int modulus_length = 0, usage = 0;
	char buf[256];
	sc_card_t *card = p15card->card;
	sc_context_t *ctx = card->ctx;
	sc_serial_number_t serial;
	sc_path_t path;
	sc_file_t *file = NULL;
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, &file);
	if (r)
		goto out;
	if (file)
		sc_file_free(file);
	file = NULL;
	if (p15card->label != NULL)
		free(p15card->label);
	p15card->label = strdup("westcos");
	if (p15card->manufacturer_id != NULL)
		free(p15card->manufacturer_id);
	p15card->manufacturer_id = strdup("CEV");

	/* get serial number */
	r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
	r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
	if (r)
		goto out;
	if (p15card->serial_number != NULL)
		free(p15card->serial_number);
	p15card->serial_number = strdup(buf);
	p15card->version = buf[6];
	p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED;
	sc_format_path("AAAA", &path);
	r = sc_select_file(card, &path, &file);
	if (!r) {
		for (i = 0; i < 1; i++) {
			unsigned int flags;
			struct sc_pkcs15_pin_info pin_info;
			struct sc_pkcs15_object pin_obj;
			memset(&pin_info, 0, sizeof(pin_info));
			memset(&pin_obj, 0, sizeof(pin_obj));
			flags = SC_PKCS15_PIN_FLAG_INITIALIZED;
			if (i == 1) {
				flags |=
				    SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED |
				    SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN;
			}
			pin_info.auth_id.len = 1;
			pin_info.auth_id.value[0] = i + 1;
			pin_info.reference = i;
			pin_info.flags = flags;
			pin_info.type = SC_PKCS15_PIN_TYPE_BCD;
			pin_info.min_length = 4;
			pin_info.stored_length = 8;
			pin_info.max_length = 8;
			pin_info.pad_char = 0xff;
			pin_info.path = path;
			pin_info.tries_left = -1;
			if (i == 1)
				strlcpy(pin_obj.label, "Unblock",
					sizeof(pin_obj.label));

			else
				strlcpy(pin_obj.label, "User",
					sizeof(pin_obj.label));
			pin_obj.flags =
			    SC_PKCS15_CO_FLAG_MODIFIABLE |
			    SC_PKCS15_CO_FLAG_PRIVATE;
			r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj,
						     &pin_info);
			if (r)
				goto out;
		}
	}
	if (file)
		sc_file_free(file);
	file = NULL;
	sc_format_path("0002", &path);
	r = sc_select_file(card, &path, &file);
	if (!r) {
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object cert_obj;
		struct sc_pkcs15_pubkey_info pubkey_info;
		struct sc_pkcs15_object pubkey_obj;
		struct sc_pkcs15_pubkey *pkey = NULL;
		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj, 0, sizeof(cert_obj));
		cert_info.id.len = 1;
		cert_info.id.value[0] = 0x45;
		cert_info.authority = 0;
		cert_info.path = path;
		r = sc_pkcs15_read_certificate(p15card, &cert_info,
					       (sc_pkcs15_cert_t
						**) (&cert_obj.data));
		if (!r) {
			sc_pkcs15_cert_t *cert =
			    (sc_pkcs15_cert_t *) (cert_obj.data);
			strlcpy(cert_obj.label, "User certificat",
				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)
				goto out;
			pkey = &cert->key;
		}
		memset(&pubkey_info, 0, sizeof(pubkey_info));
		memset(&pubkey_obj, 0, sizeof(pubkey_obj));
		pubkey_info.id.len = 1;
		pubkey_info.id.value[0] = 0x45;
		pubkey_info.modulus_length = modulus_length;
		pubkey_info.key_reference = 1;
		pubkey_info.native = 1;
		pubkey_info.usage =
		    SC_PKCS15_PRKEY_USAGE_VERIFY |
		    SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
		    SC_PKCS15_PRKEY_USAGE_ENCRYPT |
		    SC_PKCS15_PRKEY_USAGE_WRAP;
		pubkey_info.path = path;
		strlcpy(pubkey_obj.label, "Public Key",
			sizeof(pubkey_obj.label));
		pubkey_obj.auth_id.len = 1;
		pubkey_obj.auth_id.value[0] = 1;
		pubkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
		pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
		if (pkey == NULL) {
			pubkey_obj.data = &pubkey_info;
			r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &pkey);
			if (r)
				goto out;

			//force rechargement clef et maj infos lors de sc_pkcs15emu_add_rsa_pubkey (sinon modulus = 0)
			pubkey_obj.flags = 0;
		}
		if (pkey->algorithm == SC_ALGORITHM_RSA) {
			modulus_length = (int)(pkey->u.rsa.modulus.len * 8);
		}
		pubkey_info.modulus_length = modulus_length;
		pubkey_obj.data = pkey;
		r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj,
						&pubkey_info);
		if (r < 0)
			goto out;
	}
	if (!usage) {
		usage =
		    SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT |
		    SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	}
	if (file)
		sc_file_free(file);
	file = NULL;
	sc_format_path("0001", &path);
	r = sc_select_file(card, &path, &file);
	if (!r) {
		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] = 0x45;
		prkey_info.usage =
		    SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT
		    | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
		prkey_info.native = 1;
		prkey_info.key_reference = 1;
		prkey_info.modulus_length = modulus_length;
		prkey_info.path = path;
		strlcpy(prkey_obj.label, "Private Key",
			sizeof(prkey_obj.label));
		prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
		prkey_obj.auth_id.len = 1;
		prkey_obj.auth_id.value[0] = 1;
		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj,
					       &prkey_info);
		if (r < 0)
			goto out;
	}
	r = 0;
      out:if (file)
		sc_file_free(file);
	return r;
}
Example #3
0
static int read_public_key(void)
{
	int r;
	struct sc_pkcs15_id id;
	struct sc_pkcs15_object *obj;
	sc_pkcs15_pubkey_t *pubkey = NULL;
	sc_pkcs15_cert_t *cert = NULL;
	sc_pkcs15_der_t pem_key;

	id.len = SC_PKCS15_MAX_ID_SIZE;
	sc_pkcs15_hex_string_to_id(opt_pubkey, &id);

	r = sc_pkcs15_find_pubkey_by_id(p15card, &id, &obj);
	if (r >= 0) {
		if (verbose)
			printf("Reading public key with ID '%s'\n", opt_pubkey);
		r = authenticate(obj);
		if (r >= 0)
			r = sc_pkcs15_read_pubkey(p15card, obj, &pubkey);
	} else if (r == SC_ERROR_OBJECT_NOT_FOUND) {
		/* No pubkey - try if there's a certificate */
		r = sc_pkcs15_find_cert_by_id(p15card, &id, &obj);
		if (r >= 0) {
			if (verbose)
				printf("Reading certificate with ID '%s'\n", opt_pubkey);
			r = sc_pkcs15_read_certificate(p15card,
				(sc_pkcs15_cert_info_t *) obj->data,
				&cert);
		}
		if (r >= 0)
			pubkey = cert->key;
	}

	if (r == SC_ERROR_OBJECT_NOT_FOUND) {
		fprintf(stderr, "Public key with ID '%s' not found.\n", opt_pubkey);
		return 2;
	}
	if (r < 0) {
		fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
		return 1;
	}
	if (!pubkey) {
		fprintf(stderr, "Public key not available\n");
		return 1;
	}

	r = pubkey_pem_encode(pubkey, &pubkey->data, &pem_key);
	if (r < 0) {
		fprintf(stderr, "Error encoding PEM key: %s\n", sc_strerror(r));
		r = 1;
	} else {
		r = print_pem_object("PUBLIC KEY", pem_key.value, pem_key.len);
		free(pem_key.value);
	}

	if (cert)
		sc_pkcs15_free_certificate(cert);
	else if (pubkey)
		sc_pkcs15_free_pubkey(pubkey);

	return r;
}
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{

	/* The cert objects will return all the data */
const objdata objects[] = {
	{"1", "Card Capability Container", 
			"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
	{"2", "Card Holder Unique Identifier",
			"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
	{"3", "Unsigned Card Holder Unique Identifier",
			"2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0},
	{"4", "X.509 Certificate for PIV Authentication",
			"2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0},
	{"5", "Card Holder Fingerprints",
			"2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
	{"6", "Printed Information",
			"2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
	{"7", "Card Holder Facial Image", 
			"2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
	{"8", "X.509 Certificate for Digital Signature",
			"2.16.840.1.101.3.7.2.1.0",  NULL, "0100", 0},
	{"9", "X.509 Certificate for Key Management", 
			"2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
	{"10","X.509 Certificate for Card Authentication",
			"2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
	{"11", "Security Object",
			"2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0},
	{NULL, NULL, NULL, NULL, NULL, 0}
};
	/* 
	 * NIST 800-73-1 is proposing to lift the restriction on 
	 * requering pin protected certs. Thus the default will be to 
	 * not require this. But there are a number of test cards 
	 * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
	 * to be set. 
	 */
	/* certs will be pulled out from the cert objects */
	cdata certs[] = {
		{"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0},

		{"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0},
		{"3", "Certificate for Key Management", 0, "0102cece", 0, 0},
		{"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0},
		{NULL, NULL, 0, NULL, 0, 0}
	};

	const pindata pins[] = {
		{ "1", "PIV Card Holder pin", "", 0x80,
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  8, 4, 8, 
		  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL, 
		  -1, 0xFF,
		  SC_PKCS15_CO_FLAG_PRIVATE },
		{ "2", "PIV PUK", "", 0x81, 
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  8, 4, 8, 
		  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
		  SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, 
		  -1, 0xFF, 
		  SC_PKCS15_CO_FLAG_PRIVATE },
		/* there are some more key, but dont need for now */
		/* The admin 9b might fall in here */
		{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	};


	/*
	 * The size of the key or the algid is not really known
	 * but can be derived from the certificates. 
	 * the cert, pubkey and privkey are a set. 
	 * Key usages bits taken from pkcs15v1_1 Table 2
	 */
	pubdata pubkeys[] = {

		{ "1", "PIV AUTH pubkey", 0000, 
			 	SC_PKCS15_PRKEY_USAGE_ENCRYPT |
			 	SC_PKCS15_PRKEY_USAGE_WRAP |
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
			"9A06", 0x9A, "1", 0, 0},
		{ "2", "SIGN pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_ENCRYPT |
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
				SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
			"9C06", 0x9C, "1", 0, 0},
		{ "3", "KEY MAN pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_WRAP,
			"9D06", 0x9D, "1", 0, 0},
		{ "4", "CARD AUTH pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, 
			"9E06", 0x9E, "0", 0, 0},  /* no pin, and avail in contactless */
		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0}
		
	};

	prdata prkeys[] = {
		{ "1", "PIV AUTH key", 0000, 
				SC_PKCS15_PRKEY_USAGE_DECRYPT |
				SC_PKCS15_PRKEY_USAGE_UNWRAP |
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
			"", 0x9A, "1", 0},
		{ "2", "SIGN key", 0000, 
				SC_PKCS15_PRKEY_USAGE_DECRYPT |
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
				SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
			"", 0x9C, "1", 0},
		{ "3", "KEY MAN key", 0000, 
				SC_PKCS15_PRKEY_USAGE_UNWRAP,
			"", 0x9D, "1", 0},
		{ "4", "CARD AUTH key", 0000, 
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
			"", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */
		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
	};

	int    r, i;
	sc_card_t *card = p15card->card;
	sc_file_t *file_out = NULL;
	int exposed_cert[4] = {1, 0, 0, 0};
	sc_serial_number_t serial;
	char buf[SC_MAX_SERIALNR * 2 + 1];

	SC_FUNC_CALLED(card->ctx, 1);

	/* could read this off card if needed */

	/* CSP does not like a - in the name */
	p15card->label = strdup("PIV_II");
	p15card->manufacturer_id = strdup(MANU_ID);

	/*
	 * get serial number 
	 * We will use the FASC-N from the CHUID
	 * Note we are not verifying CHUID, belongs to this card
	 * but need serial number for Mac tokend 
	 */

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
	sc_ctx_suppress_errors_off(card->ctx);
	if (r < 0) {
		sc_debug(card->ctx,"sc_card_ctl rc=%d",r);
		p15card->serial_number = strdup("00000000");
	} else {
		sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
		p15card->serial_number = strdup(buf);
	}

	sc_debug(card->ctx, "PIV-II adding objects...");

	/* set other objects */
	for (i = 0; objects[i].label; i++) {
		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(objects[i].id, &obj_info.id);
		sc_format_path(objects[i].path, &obj_info.path);

		/* We could make sure the object is on the card */
		/* But really don't need to do this now */
//		sc_ctx_suppress_errors_on(card->ctx);
//		r = sc_select_file(card, &obj_info.path, NULL);
//		sc_ctx_suppress_errors_off(card->ctx);
//		if (r == SC_ERROR_FILE_NOT_FOUND)
//			continue; 
			
		strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
		if (r != SC_SUCCESS)
			return r;

		if (objects[i].auth_id)
			sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id);

		strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		obj_obj.flags = objects[i].obj_flags;
		
		r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, 
			&obj_obj, &obj_info); 
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r);
	}

	/*
	 * certs, pubkeys and priv keys are related and we assume
	 * they are in order 
	 * We need to read the cert, get modulus and keylen 
	 * We use those for the pubkey, and priv key objects. 
	 * If no cert, then see if pubkey (i.e. we are initilizing,
	 * and the pubkey is in a file,) then add pubkey and privkey
	 * If no cert and no pubkey, skip adding them. 
 
	 */
	/* set certs */
	sc_debug(card->ctx, "PIV-II adding certs...");
	for (i = 0; certs[i].label; i++) {
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object    cert_obj;
		sc_pkcs15_der_t   cert_der;
		sc_pkcs15_cert_t *cert_out;
		
		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj,  0, sizeof(cert_obj));
	
		sc_pkcs15_format_id(certs[i].id, &cert_info.id);
		cert_info.authority = certs[i].authority;
		sc_format_path(certs[i].path, &cert_info.path);

		strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		cert_obj.flags = certs[i].obj_flags;

		/* see if we have a cert */

		/* use a &file_out so card-piv will read cert if present */
		sc_ctx_suppress_errors_on(card->ctx);
		r = sc_pkcs15_read_file(p15card, &cert_info.path, 
				&cert_der.value, &cert_der.len, &file_out);
		sc_ctx_suppress_errors_off(card->ctx);
		if (file_out) {
			sc_file_free(file_out);
			file_out = NULL;
		}

		if (r) { 
			sc_debug(card->ctx, "No cert found,i=%d", i);
			continue;
		}

		certs[i].found = 1;
		/* cache it using the PKCS15 emulation objects */
		/* as it does not change */
               	if (cert_der.value) {
               	 	cert_info.value.value = cert_der.value;
                       	cert_info.value.len = cert_der.len;
                       	cert_info.path.len = 0; /* use in mem cert from now on */
               	}
		/* following will find the cached cert in cert_info */
		r =  sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out);
		if (r < 0) {
			sc_debug(card->ctx, "Failed to read/parse the certificate r=%d",r);
			continue;
		}
		/* TODO support DSA keys */
		if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
			/* save modulus_len in pub and priv */
			pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
			prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
		}
		sc_pkcs15_free_certificate(cert_out);

		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		if (r < 0) {
			sc_error(card->ctx, " Failed to add cert obj r=%d",r);
			continue;
		}
	}

	/* set pins */
	sc_debug(card->ctx, "PIV-II adding pins...");
	for (i = 0; pins[i].label; i++) {
		struct sc_pkcs15_pin_info pin_info;
		struct sc_pkcs15_object   pin_obj;

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

		sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
		pin_info.reference     = pins[i].ref;
		pin_info.flags         = pins[i].flags;
		pin_info.type          = pins[i].type;
		pin_info.min_length    = pins[i].minlen;
		pin_info.stored_length = pins[i].storedlen;
		pin_info.max_length    = pins[i].maxlen;
		pin_info.pad_char      = pins[i].pad_char;
		sc_format_path(pins[i].path, &pin_info.path);
		pin_info.tries_left    = -1;

		strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		pin_obj.flags = pins[i].obj_flags;

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



	/* set public keys */
	/* We may only need this during initialzation when genkey
	 * gets the pubkey, but it can not be read from the card 
	 * at a later time. The piv-tool can stach in file 
	 */ 
	sc_debug(card->ctx, "PIV-II adding pub keys...");
	for (i = 0; pubkeys[i].label; i++) {
		struct sc_pkcs15_pubkey_info pubkey_info;
		struct sc_pkcs15_object     pubkey_obj;
		struct sc_pkcs15_pubkey *p15_key;

		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

		memset(&pubkey_info, 0, sizeof(pubkey_info));
		memset(&pubkey_obj,  0, sizeof(pubkey_obj));


		sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id);
		pubkey_info.usage         = pubkeys[i].usage;
		pubkey_info.native        = 1;
		pubkey_info.key_reference = pubkeys[i].ref;

		sc_format_path(pubkeys[i].path, &pubkey_info.path);

		strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		pubkey_obj.flags = pubkeys[i].obj_flags;
		

		if (pubkeys[i].auth_id)
			sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);

		if (certs[i].found == 0) { /*  no cert found */
			sc_debug(card->ctx,"No cert for this pub key i=%d",i);
			/* TODO DSA */
			pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
			pubkey_obj.data = &pubkey_info;
			sc_ctx_suppress_errors_on(card->ctx);
			r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
			sc_ctx_suppress_errors_off(card->ctx);
				pubkey_obj.data = NULL;
				sc_debug(card->ctx," READING PUB KEY r=%d",r);
			if (r < 0 ) {
				continue;
			}
			/* Only get here if no cert, and the card-piv.c found 
			 * there is a pub key file. This only happens when trying
			 * initializing a card and have set env to point at file  
			 */
			if (p15_key->algorithm == SC_ALGORITHM_RSA) {
			/* save modulus_len in pub and priv */
			pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
			prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
			pubkeys[i].found = 1;
			}

		}
		pubkey_info.modulus_length = pubkeys[i].modulus_len;
		strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		/* TODO DSA keys */
		r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r); /* should not fail */

		pubkeys[i].found = 1;
	}


	/* set private keys */
	sc_debug(card->ctx, "PIV-II adding private keys...");
	for (i = 0; prkeys[i].label; i++) {
		struct sc_pkcs15_prkey_info prkey_info;
		struct sc_pkcs15_object     prkey_obj;

		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

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

		if (certs[i].found == 0 && pubkeys[i].found == 0)
			continue; /* i.e. no cert or pubkey */
		
		sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
		prkey_info.usage         = prkeys[i].usage;
		prkey_info.native        = 1;
		prkey_info.key_reference = prkeys[i].ref;
		prkey_info.modulus_length= prkeys[i].modulus_len;
		/* The cert or pubkey should have filled modulus_len */
		/* TODO DSA keys */
		sc_format_path(prkeys[i].path, &prkey_info.path);

		strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		prkey_obj.flags = prkeys[i].obj_flags;

		if (prkeys[i].auth_id)
			sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);

		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r);
	}

	SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
}