0c9295
From 6dc118e1c3b89c50cda1998de1d62fa6fa666e60 Mon Sep 17 00:00:00 2001
0c9295
From: Jakub Jelen <jjelen@redhat.com>
0c9295
Date: Fri, 3 Nov 2017 10:55:35 +0100
0c9295
Subject: [PATCH 1/3] Enable CAC ALT token card operations
0c9295
0c9295
---
0c9295
 src/libopensc/card-cac.c | 33 +++++++++++++++++++++++++++++++++
0c9295
 1 file changed, 33 insertions(+)
0c9295
0c9295
diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c
0c9295
index 82f5c7869..bc0a754a5 100644
0c9295
--- a/src/libopensc/card-cac.c
0c9295
+++ b/src/libopensc/card-cac.c
0c9295
@@ -229,6 +229,12 @@ static int cac_add_object_to_list(list_t *list, const cac_object_t *object)
0c9295
 #define CAC_1_RID "\xA0\x00\x00\x00\x79"
0c9295
 #define CAC_1_CM_AID "\xA0\x00\x00\x00\x30\x00\00"
0c9295
 
0c9295
+static const sc_path_t cac_ACA_Path = {
0c9295
+	"", 0,
0c9295
+	0,0,SC_PATH_TYPE_DF_NAME,
0c9295
+	{ CAC_TO_AID(CAC_1_RID "\x10\x00") }
0c9295
+};
0c9295
+
0c9295
 static const sc_path_t cac_CCC_Path = {
0c9295
 	"", 0,
0c9295
 	0,0,SC_PATH_TYPE_DF_NAME,
0c9295
@@ -284,6 +290,8 @@ static const cac_object_t cac_1_objects[] = {
0c9295
 static const int cac_1_object_count = sizeof(cac_1_objects)/sizeof(cac_1_objects[0]);
0c9295
 
0c9295
 
0c9295
+static int cac_select_ACA(sc_card_t *card);
0c9295
+
0c9295
 /*
0c9295
  * use the object id to find our object info on the object in our CAC-1 list
0c9295
  */
0c9295
@@ -815,6 +823,8 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
0c9295
 		case SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS:
0c9295
 			return cac_final_iterator(&priv->general_list);
0c9295
 		case SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS:
0c9295
+			/* select ACA to be able to verify PIN */
0c9295
+			cac_select_ACA(card);
0c9295
 			return cac_final_iterator(&priv->pki_list);
0c9295
 	}
0c9295
 
0c9295
@@ -1157,6 +1167,12 @@ static int cac_select_CCC(sc_card_t *card)
0c9295
 	return cac_select_file_by_type(card, &cac_CCC_Path, NULL, SC_CARD_TYPE_CAC_II);
0c9295
 }
0c9295
 
0c9295
+/* Select ACA in non-standard location */
0c9295
+static int cac_select_ACA(sc_card_t *card)
0c9295
+{
0c9295
+	return cac_select_file_by_type(card, &cac_ACA_Path, NULL, SC_CARD_TYPE_CAC_II);
0c9295
+}
0c9295
+
0c9295
 static int cac_path_from_cardurl(sc_card_t *card, sc_path_t *path, cac_card_url_t *val, int len)
0c9295
 {
0c9295
 	if (len < 10) {
0c9295
@@ -1476,6 +1492,23 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize)
0c9295
 		}
0c9295
 	}
0c9295
 
0c9295
+	/* Even some ALT tokens can be missing CCC so we should try with ACA */
0c9295
+	r = cac_select_ACA(card);
0c9295
+	if (r == SC_SUCCESS) {
0c9295
+		r = cac_find_first_pki_applet(card, &index);
0c9295
+	        if (r == SC_SUCCESS) {
0c9295
+			priv = cac_new_private_data();
0c9295
+			if (!priv)
0c9295
+				return SC_ERROR_OUT_OF_MEMORY;
0c9295
+			r = cac_populate_cac_1(card, index, priv);
0c9295
+			if (r == SC_SUCCESS) {
0c9295
+				card->type = SC_CARD_TYPE_CAC_II;
0c9295
+				card->drv_data = priv;
0c9295
+				return r;
0c9295
+			}
0c9295
+		}
0c9295
+	}
0c9295
+
0c9295
 	/* is this a CAC-1 specified in DoD "CAC Applet Developer Guide" version 1.0 September 2002 */
0c9295
 	r = cac_find_first_pki_applet(card, &index);
0c9295
 	if (r == SC_SUCCESS) {
0c9295
0c9295
From 68c52640a3eff078243fd2db627cf2d12fdd37de Mon Sep 17 00:00:00 2001
0c9295
From: Jakub Jelen <jjelen@redhat.com>
0c9295
Date: Mon, 6 Nov 2017 12:37:40 +0100
0c9295
Subject: [PATCH 2/3] Add the ACA path to the PIN structure if we have one
0c9295
0c9295
---
0c9295
 src/libopensc/card-cac.c   | 25 +++++++++++++++++++------
0c9295
 src/libopensc/cardctl.h    |  1 +
0c9295
 src/libopensc/pkcs15-cac.c |  6 ++++++
0c9295
 3 files changed, 26 insertions(+), 6 deletions(-)
0c9295
0c9295
diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c
0c9295
index bc0a754a5..178150d35 100644
0c9295
--- a/src/libopensc/card-cac.c
0c9295
+++ b/src/libopensc/card-cac.c
0c9295
@@ -169,6 +169,7 @@ typedef struct cac_private_data {
0c9295
 	cac_object_t *pki_current;      /* current pki object _ctl function */
0c9295
 	list_t general_list;            /* list of general containers */
0c9295
 	cac_object_t *general_current;  /* current object for _ctl function */
0c9295
+	sc_path_t *aca_path;		/* ACA path to be selected before pin verification */
0c9295
 } cac_private_data_t;
0c9295
 
0c9295
 #define CAC_DATA(card) ((cac_private_data_t*)card->drv_data)
0c9295
@@ -207,6 +208,7 @@ static void cac_free_private_data(cac_private_data_t *priv)
0c9295
 {
0c9295
 	free(priv->cac_id);
0c9295
 	free(priv->cache_buf);
0c9295
+	free(priv->aca_path);
0c9295
 	list_destroy(&priv->pki_list);
0c9295
 	list_destroy(&priv->general_list);
0c9295
 	free(priv);
0c9295
@@ -289,9 +291,6 @@ static const cac_object_t cac_1_objects[] = {
0c9295
 
0c9295
 static const int cac_1_object_count = sizeof(cac_1_objects)/sizeof(cac_1_objects[0]);
0c9295
 
0c9295
-
0c9295
-static int cac_select_ACA(sc_card_t *card);
0c9295
-
0c9295
 /*
0c9295
  * use the object id to find our object info on the object in our CAC-1 list
0c9295
  */
0c9295
@@ -793,11 +792,21 @@ static int cac_get_serial_nr_from_CUID(sc_card_t* card, sc_serial_number_t* seri
0c9295
 	if (priv->cac_id_len) {
0c9295
 		serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
0c9295
 		memcpy(serial->value, priv->cac_id, priv->cac_id_len);
0c9295
-                SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
0c9295
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
0c9295
 	}
0c9295
 	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND);
0c9295
 }
0c9295
 
0c9295
+static int cac_get_ACA_path(sc_card_t *card, sc_path_t *path)
0c9295
+{
0c9295
+	cac_private_data_t * priv = CAC_DATA(card);
0c9295
+
0c9295
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
0c9295
+	if (priv->aca_path) {
0c9295
+		*path = *priv->aca_path;
0c9295
+	}
0c9295
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
0c9295
+}
0c9295
 
0c9295
 static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
0c9295
 {
0c9295
@@ -810,6 +819,8 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
0c9295
 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
0c9295
 	}
0c9295
 	switch(cmd) {
0c9295
+		case SC_CARDCTL_CAC_GET_ACA_PATH:
0c9295
+			return cac_get_ACA_path(card, (sc_path_t *) ptr);
0c9295
 		case SC_CARDCTL_GET_SERIALNR:
0c9295
 			return cac_get_serial_nr_from_CUID(card, (sc_serial_number_t *) ptr);
0c9295
 		case SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS:
0c9295
@@ -823,8 +834,6 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
0c9295
 		case SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS:
0c9295
 			return cac_final_iterator(&priv->general_list);
0c9295
 		case SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS:
0c9295
-			/* select ACA to be able to verify PIN */
0c9295
-			cac_select_ACA(card);
0c9295
 			return cac_final_iterator(&priv->pki_list);
0c9295
 	}
0c9295
 
0c9295
@@ -1502,6 +1511,10 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize)
0c9295
 				return SC_ERROR_OUT_OF_MEMORY;
0c9295
 			r = cac_populate_cac_1(card, index, priv);
0c9295
 			if (r == SC_SUCCESS) {
0c9295
+				priv->aca_path = malloc(sizeof(sc_path_t));
0c9295
+				if (!priv->aca_path)
0c9295
+					return SC_ERROR_OUT_OF_MEMORY;
0c9295
+				memcpy(priv->aca_path, &cac_ACA_Path, sizeof(sc_path_t));
0c9295
 				card->type = SC_CARD_TYPE_CAC_II;
0c9295
 				card->drv_data = priv;
0c9295
 				return r;
0c9295
diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h
0c9295
index b647b0537..b610eacc7 100644
0c9295
--- a/src/libopensc/cardctl.h
0c9295
+++ b/src/libopensc/cardctl.h
0c9295
@@ -220,6 +220,7 @@ enum {
0c9295
 	SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS,
0c9295
 	SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT,
0c9295
 	SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS,
0c9295
+	SC_CARDCTL_CAC_GET_ACA_PATH,
0c9295
 
0c9295
         /*
0c9295
 	 * AuthentIC v3
0c9295
diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c
0c9295
index fd463a9b4..ff87a2345 100644
0c9295
--- a/src/libopensc/pkcs15-cac.c
0c9295
+++ b/src/libopensc/pkcs15-cac.c
0c9295
@@ -250,6 +250,12 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card)
0c9295
 		strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1);
0c9295
 		pin_obj.flags = pins[i].obj_flags;
0c9295
 
0c9295
+		/* get the ACA path in case it needs to be selected before PIN verify */
0c9295
+		r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path);
0c9295
+		if (r < 0) {
0c9295
+			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
0c9295
+		}
0c9295
+
0c9295
 		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
0c9295
 		if (r < 0)
0c9295
 			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);