I would like to ask Russell and Thomas to took these over before
I submit this as a bug report.

Attached are changes against the svn to card-piv.c and pkcs15-piv.c
that should meet all the changes provided by Russel Laner's
libopensc.patch.gz from 5/17/2007. (They do not address
the opensc.tokend.patch.gz which needs to be addressed separately)


These and other changes include:

  o Keeps the PIV card code change confined to these two modules.

  o The code to call the sc_pkcs15emu routines is now back in
    pkcs15-piv.c and the p15card-helper.c is not used. The p15card-helper
    was to generic, and added too much extra code.

  o pkcs15 and pkcs11 will now only show certs, pubkeys and prvkeys that
    actually exist on the card. The cert will be read and if found, the
    matching cert, pubkey and prvkey objects will be emulated. If no cert
    is found on the card but there is a pubkey file (i.e. getenv(keyfilename))
    then the pubkey and prvkey objects will be emulated. (This pubkey file is
    only used when tryint to initialize for some testing  when
    the pubkey is saved to a file after a keygen  operation and openssl engine
    is used to generate a request.)

  o When the cert (or pubkey) is read the modulus_len is saved to use in the
    pubkey and privkey emulated objects. This allows 1024, 2048and 3072 bit
    keys to be used, and reported correctly to PKCS#11. (The cards I have only
    do 1024 and 2048 so 3072 was not tested.)

  o There are no additional routines to process the cert to find the RSA
    key and its length, instead the sc_pkcs15_read_certificate is used which
    calls the parse_x509_cert internally.

  o The sc_pkcs15_cert_info.value is used to cache a certificate, such that it
    only need to be read once.

  o The cache in the card-piv.c is turned off, as it was not clear if it was
    working correctly, and may not be needed, because the cert is cached above.
    (It has a #if 1 ... return NULL; to not use it. If not really needed the 
cache
    code could also be removed.

  o The FASC-N from the CHUID is uses as a serial number, which
    should make the Mac tokend happy.

  o When the cert (or pubkey) isreadthe modulus_len is saved to use in the
    pubkey and privkey emulated objects.

  o When one of the non-cert PIV objects is read, like the CHUID, CCC or
    a Fingerprint, the whole object including the 0x53 starting tag is returned.
    The 0.11.2 code the would return the first tagged item, which meant
    the full object was not accessible.

  o If the get_data reads zero bytes, a zero length is now returned. New cards
    with no certs at all look like this.


--

 Douglas E. Engert  <[EMAIL PROTECTED]>
 Argonne National Laboratory
 9700 South Cass Avenue
 Argonne, Illinois  60439
 (630) 252-5444


Index: card-piv.c
===================================================================
--- card-piv.c	(revision 3173)
+++ card-piv.c	(working copy)
@@ -5,6 +5,7 @@
  * Copyright (C) 2001, 2002  Juha Yrjölä <[EMAIL PROTECTED]>
  * Copyright (C) 2005, Douglas E. Engert <[EMAIL PROTECTED]>
  * Copyright (C) 2006, Identity Alliance, Thomas Harning <[EMAIL PROTECTED]>
+ * Copyright (C) 2007, EMC, Russell Larner <[EMAIL PROTECTED]>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -79,6 +80,16 @@
 static piv_cache_item* get_cache_item(piv_private_data_t* priv, int enumtag) {
 	int idx, len = priv->cacheLen;
 	piv_cache_item* cache = priv->cache;
+#if 1
+/* DEE some thing not right with the cache,
+ * when used with the pkcs15-tool -C it cant find the CCC, but finds the
+ * CHUI ( as it was read for the serial) and finds part of a cert for the 
+ * CHFingerprints
+ * So turn it off for now. 6/1/2007
+ */
+return NULL; 
+#endif
+
 	for(idx = 0; idx < len; idx++) {
 		if(cache[idx].enumtag == enumtag)
 			return &cache[idx];
@@ -127,6 +138,9 @@
 	PIV_OBJ_SEC_OBJ,
 	PIV_OBJ_9B03,
 	PIV_OBJ_9A06,
+	PIV_OBJ_9C06,
+	PIV_OBJ_9D06,
+	PIV_OBJ_9E06,
 	PIV_CACHE_SIZE
 };
 
@@ -165,9 +179,19 @@
 /* following not standard , to be used by piv-tool only for testing */
 	{ PIV_OBJ_9B03, "3DES-ECB ADM", 
 			"2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 24},
-	{ PIV_OBJ_9A06, "Pub key from last genkey",
-			"2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", 255},
-	/* need other RSA types */
+	/* Only used when signing a cert req, usually from engine
+	 * after piv-tool generated the key and saved the pub key 
+	 * to a file. Note RSA key can be 1024, 2048 or 3072 
+	 * but still use the "9x06" name.
+	 */
+	{ PIV_OBJ_9A06, "RSA 9A Pub key from last genkey",
+			"2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", 512},
+	{ PIV_OBJ_9C06, "Pub 9C key from last genkey",
+			"2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", 512},
+	{ PIV_OBJ_9D06, "Pub 9D key from last genkey",
+			"2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", 512},
+	{ PIV_OBJ_9E06, "Pub 9E key from last genkey",
+			"2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", 512},
 	{ 0, "", "", 0, "", "", 0}
 };
 	
@@ -259,7 +283,7 @@
 
 	r = sc_lock(card);
 	if (r != SC_SUCCESS)
-		return r;
+		SC_FUNC_RETURN(card->ctx, 1, r);
 		
 	sc_format_apdu(card, &apdu, 
 			recvbuf ? SC_APDU_CASE_4_SHORT: SC_APDU_CASE_3_SHORT, 
@@ -304,11 +328,12 @@
 	}
 
 	/*
-	 * See how much we read and if we need to read more 
-	 * We should have read a tag, which will tell up how big of 
-	 * a buffer we need. We will then read more in to the allocated buffer 
+	 * See how much we read and make sure it is asn1 
+	 * if not, return 0 indicating no data found
 	 */  
 
+	
+	rbuflen = 0;  /* in case rseplen < 3  i.e. no parseable */
 	if ( recvbuflen && recvbuf && apdu.resplen > 3) {
 		*recvbuflen = 0;
 		/* we should have all the tag data, so we have to tell sc_asn1_find_tag 
@@ -441,6 +466,30 @@
 }
 
 
+static int piv_select_aid(sc_card_t* card, u8* aid, size_t aidlen, u8* response, size_t *responselen)
+{
+	sc_apdu_t apdu;
+	int r;
+
+	SC_FUNC_CALLED(card->ctx,4);
+	if (card->ctx->debug >= 5)
+		sc_debug(card->ctx, "Got args: aid=%x, aidlen=%d, response=%x, responselen=%d\n", aid, aidlen, response, *responselen);
+
+	sc_format_apdu(card, &apdu, 
+		response == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
+	apdu.lc = aidlen;
+	apdu.data = aid;
+	apdu.datalen = aidlen;
+	apdu.resp = response;
+	apdu.resplen = *responselen;
+	apdu.le = response == NULL ? 0 : 256; /* could be 21  for fci */
+
+	r = sc_transmit_apdu(card, &apdu);
+	*responselen = apdu.resplen;
+	SC_TEST_RET(card->ctx, 4,  r);
+	SC_FUNC_RETURN(card->ctx, 4,  sc_check_sw(card, apdu.sw1, apdu.sw2));
+}
+
 /* find the PIV AID on the card. If card->type already filled in,
  * then look for specific AID only
  * Assumes that priv may not be present
@@ -455,6 +504,7 @@
 	size_t taglen;
 	u8 *pix;
 	size_t pixlen;
+	size_t resplen = sizeof(rbuf);
 
 	SC_FUNC_CALLED(card->ctx,1);
 
@@ -465,19 +515,9 @@
 	if (card->type == SC_CARD_TYPE_PIV_II_GENERIC) 
 		SC_FUNC_RETURN(card->ctx, 1, 0);
 
-	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
-	apdu.lc = piv_aids[0].len_short;
-	apdu.data = piv_aids[0].value;
-	apdu.datalen = piv_aids[0].len_short;
-	apdu.resp = rbuf;
-	apdu.resplen = sizeof(rbuf);
-	apdu.le = 256; /* could be 21  for fci */
-
-	r = sc_transmit_apdu(card, &apdu);
-	SC_TEST_RET(card->ctx, r, "APDU transmit failed");
-	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
-	if (r >= 0 && apdu.resplen > 2 ) {
-		tag = (u8 *) sc_asn1_find_tag(card->ctx, rbuf, apdu.resplen, 0x61, &taglen);
+	r = piv_select_aid(card, piv_aids[0].value, piv_aids[0].len_short, rbuf, &resplen);
+	if (r >= 0 && resplen > 2 ) {
+		tag = (u8 *) sc_asn1_find_tag(card->ctx, rbuf, resplen, 0x61, &taglen);
 		if (tag != NULL) {
 			pix = (u8 *) sc_asn1_find_tag(card->ctx, tag, taglen, 0x4F, &pixlen);
 			if (pix != NULL ) { 
@@ -561,6 +601,7 @@
 	int r = 0;
 	u8 tagbuf[8];
 	size_t tag_len;
+	char * keyenvname = NULL;
 	
 	SC_FUNC_CALLED(card->ctx,1);
 	sc_debug(card->ctx, "get_data: tag=%d \n", enumtag);
@@ -579,11 +620,26 @@
 	 * as an OpenSSL EVP_KEY PEM using the -o parameter
 	 * we will look to see there as a file and load it
 	 * this is ugly, and maybe the pkcs15 cache would work
-	 * but we only need it  to get the OpenSSL req with engine to work.
+	 * but we only need it to get the OpenSSL req with engine to work.
+	 * Each of the 3 keys with certs has its own file. 
 	 */
 
+	switch (piv_objects[enumtag].enumtag) {
+		case PIV_OBJ_9A06:
+			keyenvname = "PIV_9A06_KEY";
+			break;
+		case PIV_OBJ_9C06:
+			keyenvname = "PIV_9C06_KEY";
+			break;
+		case PIV_OBJ_9D06:
+			keyenvname = "PIV_9D06_KEY";
+			break;
+		case PIV_OBJ_9E06:
+			keyenvname = "PIV_9E06_KEY";
+			break;
+	}
 
-	if (piv_objects[enumtag].enumtag == PIV_OBJ_9A06)  {
+	if (keyenvname)  {
 		BIO * bp = NULL;
 		RSA * rsa = NULL;
 		u8 *q;
@@ -591,7 +647,7 @@
 		size_t taglen;
 		char * keyfilename = NULL;
 
-		keyfilename = getenv("PIV_9A06_KEY");
+		keyfilename = getenv(keyenvname);
 
 		if (keyfilename == NULL) {
 			r = SC_ERROR_FILE_NOT_FOUND;
@@ -684,14 +740,14 @@
 			if(len < count + idx)
 				count = len - idx;
 			if(count <= 0)
-				return 0;
+				SC_FUNC_RETURN(card->ctx, 1, 0);
 			memcpy(buf, newBuf + idx, count);
 			if(0 != add_cache_item(priv, enumtag, newBuf, len)) {
 				/* Failed to cache item */
 				free(newBuf);
 			}
 		}
-		return count;
+		SC_FUNC_RETURN(card->ctx, 1, count);
 #else
 		sc_error(card->ctx,"PIV compression not supported, no zlib");
 		return SC_ERROR_NOT_SUPPORTED;
@@ -718,28 +774,35 @@
 
 static int piv_handle_data(sc_card_t *card, int enumtag, 
 		unsigned idx, u8* buf, size_t count, u8* data, size_t length) {
-	/* For now get the first tag, and return the data */
+	/* We need to return the whole not just first tag */
 	piv_private_data_t * priv = PIV_DATA(card);
 	u8* tag;
 	size_t taglen;
+	size_t reallen;
 	piv_cache_item* item;
+	
+	SC_FUNC_CALLED(card->ctx,1);
 
 	tag = (u8 *) sc_asn1_find_tag(card->ctx, data,  length, *data, &taglen);
 	if (tag == NULL) {
-		return SC_ERROR_OBJECT_NOT_VALID;
+		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
 	}
-	if(taglen < count + idx)
-		count = taglen - idx;
+	reallen = tag - data + taglen;
+	if (reallen > length)
+		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OBJECT_NOT_VALID);
+
+	if(reallen < count + idx)
+		count = reallen - idx;
 	if(count <= 0)
 		return 0;
-	memcpy(buf, tag + idx, count);
+	memcpy(buf, data + idx, count);
 	if(0 == add_cache_item(priv, enumtag, NULL, 0)) {
 		item = get_cache_item(priv, enumtag);
 		if(item) {
-			item->data = malloc(taglen);
+			item->data = malloc(reallen);
 			if(item->data) {
-				item->length = taglen;
-				memcpy(item->data, tag, taglen);
+				item->length = reallen;
+				memcpy(item->data, data, reallen);
 			}
 		}
 	}
@@ -760,6 +823,8 @@
 	int r;
 	u8 *rbuf = NULL;
 	size_t rbuflen = 0;
+	u8 *tag;
+	size_t taglen;
 	u8 *body;
 	size_t bodylen;
 
@@ -768,20 +833,23 @@
 		 SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
 	enumtag = piv_objects[priv->selected_obj].enumtag;
 
+	if (priv->eof == 1)
+		return 0;
+
 	/* Hit the cache */
 	if(priv->current_item) {
 		item = priv->current_item;
 		if(idx + count > item->length) {
 			count = item->length - idx;
 		}
-		if(count <= 0)
+		if(count <= 0) {
+			priv->eof = 1;
 			return 0;
+		}
 		memcpy(buf, item->data + idx, count);
 		return count;
 	}
 
-	if (priv->eof == 1)
-		return 0;
 
 	r = piv_get_data(card, priv->selected_obj, &rbuf, &rbuflen);
 	
@@ -800,6 +868,12 @@
 			r = SC_ERROR_INVALID_DATA;
 			goto err;
 		}
+		if (bodylen > body - rbuf + rbuflen) {
+			sc_debug(card->ctx," ***** tag length > then data: %d>%d+%d",
+				bodylen , body - rbuf, rbuflen);
+			r = SC_ERROR_INVALID_DATA;
+			goto err;
+		}
 		switch (enumtag) {
 			case PIV_OBJ_X509_PIV_AUTH:
 			case PIV_OBJ_X509_DS:
@@ -807,8 +881,23 @@
 			case PIV_OBJ_X509_CARD_AUTH:
 				r = piv_handle_certificate_data(card, enumtag, idx, buf, count, body, bodylen);
 				break;
+			case PIV_OBJ_9A06:
+			case PIV_OBJ_9C06:
+			case PIV_OBJ_9D06:
+			case PIV_OBJ_9E06:
+				tag = (u8 *) sc_asn1_find_tag(card->ctx, body,  bodylen,
+						*body, &taglen);
+				if (tag == NULL) {
+					r = SC_ERROR_OBJECT_NOT_VALID;
+					break;
+				}
+				memcpy(buf, tag, taglen); /*DEE should check lengths */
+				r = taglen;
+				break;
+			
 			default:
-				r = piv_handle_data(card, enumtag, idx, buf, count, body, bodylen);
+				/* send whole object, tags and all */
+				r = piv_handle_data(card, enumtag, idx, buf, count, rbuf, rbuflen);
 				break;
 		}
 	}
@@ -838,7 +927,7 @@
 	tag_len = piv_objects[tag].tag_len;
 	sbuflen = put_tag_and_len(0x5c, tag_len, NULL) + buf_len;
 	if (!(sbuf = (u8 *) malloc(sbuflen))) 
-		return SC_ERROR_OUT_OF_MEMORY;
+		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
 
 	p = sbuf;
 	put_tag_and_len(0x5c, tag_len, &p);
@@ -892,7 +981,7 @@
 	if (sbuf)
 		free(sbuf);
 
-	return r;
+	SC_FUNC_RETURN(card->ctx, 1, r);
 }
 /* 
  * We need to add the 0x53 tag and other specific tags, 
@@ -1151,10 +1240,6 @@
 	}	
 	p += *(rbuf + 3);
 	
-	switch (priv-> enumtag) {
-		default:
-			alg_id = 0x00;
-	}
 	r = piv_general_io(card, 0x87, alg_id, key_ref, sbuf, p - sbuf, NULL, NULL);
 
 	sc_unlock(card);
@@ -1168,7 +1253,43 @@
 	SC_FUNC_RETURN(card->ctx, 1, r);
 }
 
+static int piv_get_serial_nr_from_CHUI(sc_card_t* card, sc_serial_number_t* serial)
+{
+	int r;
+	u8 *rbuf = NULL;
+	u8 *body, *fascn;
+	size_t rbuflen = 0, bodylen, fascnlen;
+	u8 temp[2000];
+	size_t templen = sizeof(temp);
 
+	SC_FUNC_CALLED(card->ctx, 1);
+
+	/* ensure we've got the PIV selected, and nothing else is in process */
+	/* This fixes several problems due to previous incomplete APDUs during card detection */
+	/* Note: We need the temp because (some?) Oberthur cards don't like selecting an applet without response data */
+	piv_select_aid(card, piv_aids[0].value, piv_aids[0].len_short, temp, &templen);
+
+	r = piv_get_data(card, PIV_OBJ_CHUI-1, &rbuf, &rbuflen);
+	SC_TEST_RET(card->ctx, r, "Failure retrieving CHUI");
+
+	r = SC_ERROR_INTERNAL;
+	if (rbuflen != 0) {
+		body = (u8 *)sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x53, &bodylen); /* Pass the outer wrapper asn1 */
+		if (body != NULL && bodylen != 0) {
+			fascn = (u8 *)sc_asn1_find_tag(card->ctx, body, bodylen, 0x30, &fascnlen); /* Find the FASC-N data */
+			if (fascn != NULL && fascnlen != 0) {
+				serial->len = fascnlen < SC_MAX_SERIALNR ? fascnlen : SC_MAX_SERIALNR;
+				memcpy (serial->value, fascn, serial->len);
+				r = SC_SUCCESS;
+			}
+		}
+	}
+      
+	if (rbuf != NULL)
+		free (rbuf);
+	SC_FUNC_RETURN(card->ctx, 1, r);
+}
+
 static int piv_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
 {
 	u8 * opts; /*  A or M, key_ref, alg_id */
@@ -1192,6 +1313,9 @@
 			return piv_generate_key(card, 
 				(struct sc_cardctl_cryptoflex_genkey_info *) ptr);
 			break;
+		case SC_CARDCTL_GET_SERIALNR:
+			return piv_get_serial_nr_from_CHUI(card, (sc_serial_number_t *) ptr);
+			break;
 	}
 
 	return SC_ERROR_NOT_SUPPORTED;
@@ -1224,14 +1348,17 @@
 
 		r = piv_general_io(card, 0x87, 0x00, 0x00, sbuf, p - sbuf, 
 				&rbuf, &rbuflen); 
- 		if (r < 0) 
+ 		if (r < 0) { 
+			sc_unlock(card);
 			SC_FUNC_RETURN(card->ctx, 1, r);
+		}
 		q = rbuf;
 		if ( (*q++ != 0x7C)
 			|| (*q++ != rbuflen - 2)
 			|| (*q++ != 0x81)
 			|| (*q++ != rbuflen - 4)) {
 			r =  SC_ERROR_INVALID_DATA;
+			sc_unlock(card);
 			SC_FUNC_RETURN(card->ctx, 1, r);
 		}
 		memcpy(rnd, q, n);
@@ -1259,13 +1386,13 @@
 			env->flags, env->operation, env->algorithm, env->algorithm_flags, 
 			env->algorithm_ref, env->key_ref[0], env->key_ref_len);
 
-	if (env->algorithm == 0) 
-		priv->alg_id = 0x06; /* 1024 RSA for now only */
+	if (env->algorithm == SC_ALGORITHM_RSA) 
+		priv->alg_id = 0x06; /* Say it is RSA, set 5, 6, 7 later */
 	else
 		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NO_CARD_SUPPORT);
 	priv->key_ref = env->key_ref[0];
 
-	return 0;
+	SC_FUNC_RETURN(card->ctx, 2, 0);
 }
 
 
@@ -1273,7 +1400,7 @@
 {
 	SC_FUNC_CALLED(card->ctx,1);
 
-	return 0;
+	SC_FUNC_RETURN(card->ctx, 1, 0);
 }
 
 
@@ -1288,8 +1415,9 @@
 	size_t taglen;
 	u8 *body;
 	size_t bodylen;
+	unsigned int real_alg_id;
 
-	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
+	u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */
 	u8 *rbuf = NULL;
 	size_t rbuflen;
 	
@@ -1304,7 +1432,25 @@
 	memcpy(p, data, datalen);
 	p += datalen;
 
-	r = piv_general_io(card, 0x87, priv->alg_id, priv->key_ref, 
+	/* 
+	 * alg_id=06 is a place holder for all RSA keys. 
+ 	 * Derive the real alg_id based on the size of the
+	 * the data, as we are always using raw mode. 
+	 * Non RSA keys needs some work in thia area. 
+	 */
+
+	real_alg_id = priv->alg_id;
+	if (priv->alg_id == 0x06) {
+		switch  (datalen) {
+			case 128: real_alg_id = 0x06; break;
+			case 256: real_alg_id = 0x07; break;
+			case 384: real_alg_id = 0x05; break;
+			default:
+				SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NO_CARD_SUPPORT);
+		}
+	} 
+
+	r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref, 
 			sbuf, p - sbuf, &rbuf, &rbuflen);  
 
 	if ( r >= 0) {
@@ -1331,7 +1477,7 @@
 					u8 * out, size_t outlen)
 {
 	SC_FUNC_CALLED(card->ctx,4);
-	return piv_validate_general_authentication(card, data, datalen, out, outlen);
+	SC_FUNC_RETURN(card->ctx, 4, piv_validate_general_authentication(card, data, datalen, out, outlen));
 }
 
 static int piv_decipher(sc_card_t *card,
@@ -1340,7 +1486,7 @@
 {
 	SC_FUNC_CALLED(card->ctx,4);
 
-	return piv_validate_general_authentication(card, data, datalen, out, outlen);
+	SC_FUNC_RETURN(card->ctx, 4, piv_validate_general_authentication(card, data, datalen, out, outlen));
 }
 
 
@@ -1389,7 +1535,7 @@
 		pathlen -= 2;
 	}
 	if (pathlen != 2)
-			return SC_ERROR_INVALID_ARGUMENTS;
+		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
 	 
 	i = piv_find_obj_by_containerid(card, path);
 
@@ -1399,6 +1545,7 @@
 	priv->eof = 0;
 
 	/* check out the cache */
+	priv->current_item = NULL;
 	item = get_cache_item(priv, i);
 	if(item) {
 		priv->current_item = item;
@@ -1431,7 +1578,6 @@
 
 }
 
-
 static int piv_finish(sc_card_t *card)
 {
  	piv_private_data_t * priv = PIV_DATA(card);
@@ -1477,7 +1623,7 @@
 	priv = (piv_private_data_t *) calloc(1, sizeof(piv_private_data_t));
 
 	if (!priv)
-		return SC_ERROR_OUT_OF_MEMORY;
+		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
 	priv->aid_file = sc_file_new();
 	priv->selected_obj = -1;
 	priv->max_recv_size = 256;
@@ -1517,6 +1663,29 @@
 }
 
 
+static int piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, 
+                       int *tries_left)
+{
+	/* Extra validation of (new) PIN during a PIN change request, to
+	 * ensure it's not outside the FIPS 201 4.1.6.1 (numeric only) and
+	 * FIPS 140-2 (6 character minimum) requirements.
+	 */
+	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
+	if (data->cmd == SC_PIN_CMD_CHANGE) {
+		int i = 0;
+		if (data->pin2.len < 6) {
+			return SC_ERROR_INVALID_PIN_LENGTH;
+		}
+		for(i=0; i < data->pin2.len; ++i) {
+			if (!isdigit(data->pin2.data[i])) {
+				return SC_ERROR_INVALID_DATA;
+			}
+		}
+	}
+	return iso_drv->ops->pin_cmd(card, data, tries_left);
+}
+
+
 static struct sc_card_driver * sc_get_driver(void)
 {
 	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
@@ -1535,6 +1704,7 @@
 	piv_ops.compute_signature = piv_compute_signature;
 	piv_ops.decipher =  piv_decipher;
 	piv_ops.card_ctl = piv_card_ctl;
+	piv_ops.pin_cmd = piv_pin_cmd;
 
 	return &piv_drv;
 }
Index: pkcs15-piv.c
===================================================================
--- pkcs15-piv.c	(revision 3173)
+++ pkcs15-piv.c	(working copy)
@@ -4,9 +4,9 @@
  *
  * Copyright (C) 2005, Douglas E. Engert <[EMAIL PROTECTED]> 
  *               2004, Nils Larsch <[EMAIL PROTECTED]>
- *
  * Copyright (C) 2006, Identity Alliance, 
  *               Thomas Harning <[EMAIL PROTECTED]>
+ * Copyright (C) 2007, EMC, Russell Larner <[EMAIL PROTECTED]>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,13 +34,80 @@
 #include <openssl/bio.h>
 #include <openssl/rsa.h>
 #include <openssl/pem.h>
-#include "strlcpy.h"
-#include "p15card-helper.h"
 
 #define MANU_ID		"piv_II "
 
 int sc_pkcs15emu_piv_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
 
+
+typedef struct objdata_st {
+	const char *id;
+	const char *label;
+	const char *aoid;
+	int     authority;
+	const char *path;
+	int         obj_flags;
+} objdata;
+
+typedef struct cdata_st {
+	const char *id;
+	const char *label;
+	int	    authority;
+	const char *path;
+	int         obj_flags;
+	int         found;
+} cdata;
+
+typedef struct pdata_st {
+	const char *id;
+	const char *label;
+	const char *path;
+	int         ref;
+	int         type;
+	unsigned int maxlen;
+	unsigned int minlen;
+	unsigned int storedlen;
+	int         flags;	
+	int         tries_left;
+	const char  pad_char;
+	int         obj_flags;
+} pindata; 
+
+typedef struct pubdata_st {
+	const char *id;
+	const char *label;
+	unsigned int modulus_len;
+	int         usage;
+	const char *path;
+	int         ref;
+	const char *auth_id;
+	int         obj_flags;
+	int	    found;
+} pubdata;
+
+typedef struct prdata_st {
+	const char *id;
+	const char *label;
+	unsigned int modulus_len;
+	int         usage;
+	const char *path;
+	int         ref;
+	const char *auth_id;
+	int         obj_flags;
+} prdata;
+
+#define USAGE_NONREP	SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
+#define USAGE_KE	SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
+			SC_PKCS15_PRKEY_USAGE_DECRYPT | \
+			SC_PKCS15_PRKEY_USAGE_WRAP    | \
+			SC_PKCS15_PRKEY_USAGE_UNWRAP
+#define USAGE_AUT	SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
+			SC_PKCS15_PRKEY_USAGE_DECRYPT | \
+			SC_PKCS15_PRKEY_USAGE_WRAP    | \
+			SC_PKCS15_PRKEY_USAGE_UNWRAP  | \
+			SC_PKCS15_PRKEY_USAGE_SIGN
+
+
 static int piv_detect_card(sc_pkcs15_card_t *p15card)
 {
 	sc_card_t *card = p15card->card;
@@ -52,6 +119,9 @@
 	return SC_SUCCESS;
 }
 
+static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
+{
+
 const objdata objects[] = {
 	{"1", "Card Capability Container", 
 			"2.16.840.1.101.3.7.1.219.0", 0, "DB00", 0},
@@ -67,122 +137,79 @@
 			"2.16.840.1.101.3.7.2.144.0", 0, "9000", 0},
 	{NULL, NULL, NULL, 0, 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. 
+	 */
+	cdata certs[] = {
+		{"1", "Certificate for PIV Authentication", 0, "0101", 0, 0},
+		{"2", "Certificate for Digital Signature", 0, "0100", 0, 0},
+		{"3", "Certificate for Key Management", 0, "0102", 0, 0},
+		{"4", "Certificate for Card Authentication", 0, "0500", 0, 0},
+		{NULL, NULL, 0, NULL, 0, 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. 
- */
-const cdata certs[] = {
-	{"1", "Certificate for PIV Authentication", 0, "0101", 0},
-	{"2", "Certificate for Digital Signature", 0, "0100", 0},
-	{"3", "Certificate for Key Management", 0, "0102", 0},
-#if 0 /* Strange break */
-	{"4", "Certificate for Card Authentication", 0, "0500", 0},
-#endif
-	{NULL, NULL, 0, NULL, 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}
+	};
 
-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. 
+	 */
+	pubdata pubkeys[] = {
 
-/*
- * The size of the key or the algid is not really known
- * but can be derived from the certificates. 
- * DEE need to fix - We will still refer to the "key files" as 06 even of not.
- * 07 is 2048, 05 is 3072. 
- */
-const pubdata pubkeys[] = {
+		{ "1", "AUTH pubkey", 0000, USAGE_AUT, "9A06", 
+		  0x9A, "1", 0, 0},
+		{ "2", "SIGN pubkey", 0000, USAGE_AUT, "9C06", 
+		  0x9C, "1", 0, 0},
+		{ "3", "KEY MAN pubkey", 0000, USAGE_AUT, "9D06", 
+		  0x9D, "1", 0, 0},
+		{ "4", "CARD auth pubkey", 0000, USAGE_AUT, "9E06", 
+		  0x9E, "1", 0, 0},
+		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0}
+		
+	};
 
-	{ "1", "AUTH pubkey", 1024, USAGE_AUT, "9A06", 
-	  0x9A, "1", 0},
-	{ "2", "SIGN pubkey", 1024, USAGE_AUT, "9C06", 
-	  0x9C, "1", 0},
-	{ "3", "KEY MAN pubkey", 1024, USAGE_AUT, "9D06", 
-	  0x9E, "1", 0},
-	{ "4", "ADMIN pubkey", 1024, USAGE_AUT, "9B06", 
-	  0x9B, "1", 0},
-	{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
-	
-};
+	prdata prkeys[] = {
+		{ "1", "AUTH key", 0000, USAGE_AUT, "",
+		  0x9A, "1", 0},
+		{ "2", "SIGN key", 0000, USAGE_AUT, "",
+		  0x9C, "1", 0},
+		{ "3", "KEY MAN key", 0000, USAGE_AUT, "",
+		  0x9D, "1", 0},
+		{ "4", "CARD key", 0000, USAGE_AUT, "",
+		  0x9E, "1", 0},
+		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
+	};
 
-const prdata prkeys[] = {
-	{ "1", "AUTH key", 1024, USAGE_AUT, "",
-	  0x9A, "1", 0},
-	{ "2", "SIGN key", 1024, USAGE_AUT, "",
-	  0x9C, "1", 0},
-	{ "3", "KEY MAN key", 1024, USAGE_AUT, "",
-	  0x9E, "1", 0},
-	{ "4", "ADMIN key", 1024, USAGE_AUT, "",
-	  0x9B, "1", 0},
-	{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
-};
-
-/* TEMPORARY: Should hook into card-piv ... */
-static int piv_load_cached_cert(sc_card_t *card, u8** buf, size_t* count, int* should_free) {
-	/* File already selected.. just read... */
-	int r;
-	u8* out = malloc(4096*2);
-	r = sc_read_binary(card, 0, out, 4096*2, 0);
-	if(r < 0) {
-		free(out);
-		*buf = NULL;
-		*count = 0;
-		return r;
-	}
-	*count = r;
-	*buf = out;
-	*should_free = 1;
-	return SC_SUCCESS;
-}
-
-#define CHECK_CERTIFICATES 1
-static p15data_items items = {
-	objects,
-	certs,
-	pins,
-	NULL,
-	prkeys,
-#ifdef CHECK_CERTIFICATES
-	piv_load_cached_cert,
-#else
-	NULL,
-#endif
-	default_cert_handle,
-	1,
-#ifdef CHECK_CERTIFICATES
-	0,
-#else
-	1,
-#endif
-	0
-};
-
-static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
-{
-	int    r;
+	int    r, i;
 	sc_card_t *card = p15card->card;
+	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);
 
@@ -191,21 +218,251 @@
 	/* CSP does not like a - in the name */
 	p15card->label = strdup("PIV_II");
 	p15card->manufacturer_id = strdup(MANU_ID);
-	/* get serial number */
-	/* We could also use the CCC or CHUID info here */
-#if 0
+
+	/*
+	 * 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 
+	 */
+
 	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 != SC_SUCCESS)
-		return SC_ERROR_INTERNAL;
-	p15card->serial_number = strdup(buf);
-#endif
-        p15card->serial_number = strdup("9876543210");
+	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);
+		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;
+
+		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));
 	
-	r = sc_pkcs15emu_initialize_all(p15card, &items);
+		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 */
+
+		r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len,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_error(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;
+			r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
+				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);
 }
 
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to