Blame SOURCES/opensc-0.19.0-cac1.patch

5831fa
commit a2efcb184fcb0302bfadeb97b5cf8953cb77d0fb
5831fa
Author: Jakub Jelen <jjelen@redhat.com>
5831fa
Date:   Tue Oct 9 16:03:19 2018 +0200
5831fa
5831fa
    WIP: Add minimal CAC1 driver for legacy cards.
5831fa
    
5831fa
    It is using the same pkcs15 backend as the CAC2 cards as well as some of
5831fa
    the CAC2 driver methods.
5831fa
    
5831fa
    The separation is made mostly for easier card matching.
5831fa
5831fa
diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am
5831fa
index a99b0c57..5a17df2b 100644
5831fa
--- a/src/libopensc/Makefile.am
5831fa
+++ b/src/libopensc/Makefile.am
5831fa
@@ -40,7 +40,8 @@ libopensc_la_SOURCES_BASE = \
5831fa
 	card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \
5831fa
 	card-oberthur.c card-belpic.c card-atrust-acos.c \
5831fa
 	card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \
5831fa
-	card-piv.c card-cac.c card-muscle.c card-acos5.c \
5831fa
+	card-piv.c card-cac-common.c card-cac.c card-cac1.c \
5831fa
+	card-muscle.c card-acos5.c \
5831fa
 	card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
5831fa
 	card-rtecp.c card-westcos.c card-myeid.c \
5831fa
 	card-itacns.c card-authentic.c \
5831fa
diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak
5831fa
index 10a3b0a9..7ef642b6 100644
5831fa
--- a/src/libopensc/Makefile.mak
5831fa
+++ b/src/libopensc/Makefile.mak
5831fa
@@ -19,7 +19,7 @@ OBJECTS			= \
5831fa
 	card-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \
5831fa
 	card-oberthur.obj card-belpic.obj card-atrust-acos.obj \
5831fa
 	card-entersafe.obj card-epass2003.obj card-coolkey.obj \
5831fa
-	card-incrypto34.obj card-cac.obj card-piv.obj card-muscle.obj \
5831fa
+	card-incrypto34.obj card-cac.obj card-cac1.obj card-piv.obj card-muscle.obj \
5831fa
 	card-acos5.obj \
5831fa
 	card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
5831fa
 	card-rtecp.obj card-westcos.obj card-myeid.obj \
5831fa
diff --git a/src/libopensc/card-cac-common.c b/src/libopensc/card-cac-common.c
5831fa
new file mode 100644
5831fa
index 00000000..6c338bf9
5831fa
--- /dev/null
5831fa
+++ b/src/libopensc/card-cac-common.c
5831fa
@@ -0,0 +1,116 @@
5831fa
+/*
5831fa
+ * card-cac-common.c: Code shared among CAC1 and CAC2 drivers
5831fa
+ *
5831fa
+ * Copyright (C) 2018, Red Hat, Inc.
5831fa
+ *
5831fa
+ * Author: Jakub Jelen <jjelen@redhat.com>
5831fa
+ *
5831fa
+ * This library is free software; you can redistribute it and/or
5831fa
+ * modify it under the terms of the GNU Lesser General Public
5831fa
+ * License as published by the Free Software Foundation; either
5831fa
+ * version 2.1 of the License, or (at your option) any later version.
5831fa
+ *
5831fa
+ * This library is distributed in the hope that it will be useful,
5831fa
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5831fa
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5831fa
+ * Lesser General Public License for more details.
5831fa
+ *
5831fa
+ * You should have received a copy of the GNU Lesser General Public
5831fa
+ * License along with this library; if not, write to the Free Software
5831fa
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5831fa
+ */
5831fa
+
5831fa
+#if HAVE_CONFIG_H
5831fa
+#include "config.h"
5831fa
+#endif
5831fa
+
5831fa
+#include <ctype.h>
5831fa
+#include <string.h>
5831fa
+#include <stdlib.h>
5831fa
+
5831fa
+#ifdef _WIN32
5831fa
+#include <io.h>
5831fa
+#else
5831fa
+#include <unistd.h>
5831fa
+#endif
5831fa
+
5831fa
+#include "internal.h"
5831fa
+#include "iso7816.h"
5831fa
+#include "card-cac-common.h"
5831fa
+
5831fa
+/* default certificate labels for the CAC card */
5831fa
+const char *cac_labels[MAX_CAC_SLOTS] = {
5831fa
+	"CAC ID Certificate",
5831fa
+	"CAC Email Signature Certificate",
5831fa
+	"CAC Email Encryption Certificate",
5831fa
+	"CAC Cert 4",
5831fa
+	"CAC Cert 5",
5831fa
+	"CAC Cert 6",
5831fa
+	"CAC Cert 7",
5831fa
+	"CAC Cert 8",
5831fa
+	"CAC Cert 9",
5831fa
+	"CAC Cert 10",
5831fa
+	"CAC Cert 11",
5831fa
+	"CAC Cert 12",
5831fa
+	"CAC Cert 13",
5831fa
+	"CAC Cert 14",
5831fa
+	"CAC Cert 15",
5831fa
+	"CAC Cert 16"
5831fa
+};
5831fa
+
5831fa
+const char *get_cac_label(int index)
5831fa
+{
5831fa
+	if (index < 0 || index >= MAX_CAC_SLOTS)
5831fa
+		return NULL;
5831fa
+
5831fa
+	return cac_labels[index];
5831fa
+}
5831fa
+
5831fa
+static int cac_list_compare_path(const void *a, const void *b)
5831fa
+{
5831fa
+	if (a == NULL || b == NULL)
5831fa
+		return 1;
5831fa
+	return memcmp( &((cac_object_t *) a)->path,
5831fa
+		&((cac_object_t *) b)->path, sizeof(sc_path_t));
5831fa
+}
5831fa
+
5831fa
+/* For SimCList autocopy, we need to know the size of the data elements */
5831fa
+static size_t cac_list_meter(const void *el) {
5831fa
+	return sizeof(cac_object_t);
5831fa
+}
5831fa
+
5831fa
+cac_private_data_t *cac_new_private_data(void)
5831fa
+{
5831fa
+	cac_private_data_t *priv;
5831fa
+	priv = calloc(1, sizeof(cac_private_data_t));
5831fa
+	if (!priv)
5831fa
+		return NULL;
5831fa
+	list_init(&priv->pki_list);
5831fa
+	list_attributes_comparator(&priv->pki_list, cac_list_compare_path);
5831fa
+	list_attributes_copy(&priv->pki_list, cac_list_meter, 1);
5831fa
+	list_init(&priv->general_list);
5831fa
+	list_attributes_comparator(&priv->general_list, cac_list_compare_path);
5831fa
+	list_attributes_copy(&priv->general_list, cac_list_meter, 1);
5831fa
+	/* set other fields as appropriate */
5831fa
+
5831fa
+	return priv;
5831fa
+}
5831fa
+
5831fa
+void cac_free_private_data(cac_private_data_t *priv)
5831fa
+{
5831fa
+	free(priv->cac_id);
5831fa
+	free(priv->cache_buf);
5831fa
+	free(priv->aca_path);
5831fa
+	list_destroy(&priv->pki_list);
5831fa
+	list_destroy(&priv->general_list);
5831fa
+	free(priv);
5831fa
+	return;
5831fa
+}
5831fa
+
5831fa
+int cac_add_object_to_list(list_t *list, const cac_object_t *object)
5831fa
+{
5831fa
+	if (list_append(list, object) < 0)
5831fa
+		return SC_ERROR_UNKNOWN;
5831fa
+	return SC_SUCCESS;
5831fa
+}
5831fa
+
5831fa
diff --git a/src/libopensc/card-cac-common.h b/src/libopensc/card-cac-common.h
5831fa
new file mode 100644
5831fa
index 00000000..77f14761
5831fa
--- /dev/null
5831fa
+++ b/src/libopensc/card-cac-common.h
5831fa
@@ -0,0 +1,89 @@
5831fa
+/*
5831fa
+ * card-cac-common.h: Code shared among CAC1 and CAC2 drivers
5831fa
+ *
5831fa
+ * Copyright (C) 2018, Red Hat, Inc.
5831fa
+ *
5831fa
+ * Author: Jakub Jelen <jjelen@redhat.com>
5831fa
+ *
5831fa
+ * This library is free software; you can redistribute it and/or
5831fa
+ * modify it under the terms of the GNU Lesser General Public
5831fa
+ * License as published by the Free Software Foundation; either
5831fa
+ * version 2.1 of the License, or (at your option) any later version.
5831fa
+ *
5831fa
+ * This library is distributed in the hope that it will be useful,
5831fa
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5831fa
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5831fa
+ * Lesser General Public License for more details.
5831fa
+ *
5831fa
+ * You should have received a copy of the GNU Lesser General Public
5831fa
+ * License along with this library; if not, write to the Free Software
5831fa
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5831fa
+ */
5831fa
+
5831fa
+#ifndef HAVE_CARD_CAC_COMMON_H
5831fa
+#define HAVE_CARD_CAC_COMMON_H
5831fa
+
5831fa
+#define CAC_MAX_SIZE 4096		/* arbitrary, just needs to be 'large enough' */
5831fa
+
5831fa
+typedef struct cac_cuid {
5831fa
+	u8 gsc_rid[5];
5831fa
+	u8 manufacturer_id;
5831fa
+	u8 card_type;
5831fa
+	u8 card_id;
5831fa
+} cac_cuid_t;
5831fa
+
5831fa
+/* data structures to store meta data about CAC objects */
5831fa
+typedef struct cac_object {
5831fa
+	const char *name;
5831fa
+	int fd;
5831fa
+	sc_path_t path;
5831fa
+} cac_object_t;
5831fa
+
5831fa
+/*
5831fa
+ * CAC private data per card state
5831fa
+ */
5831fa
+typedef struct cac_private_data {
5831fa
+	int object_type;		/* select set this so we know how to read the file */
5831fa
+	int cert_next;			/* index number for the next certificate found in the list */
5831fa
+	u8 *cache_buf;			/* cached version of the currently selected file */
5831fa
+	size_t cache_buf_len;		/* length of the cached selected file */
5831fa
+	int cached;			/* is the cached selected file valid */
5831fa
+	cac_cuid_t cuid;                /* card unique ID from the CCC */
5831fa
+	u8 *cac_id;                     /* card serial number */
5831fa
+	size_t cac_id_len;              /* card serial number len */
5831fa
+	list_t pki_list;                /* list of pki containers */
5831fa
+	cac_object_t *pki_current;      /* current pki object _ctl function */
5831fa
+	list_t general_list;            /* list of general containers */
5831fa
+	cac_object_t *general_current;  /* current object for _ctl function */
5831fa
+	sc_path_t *aca_path;		/* ACA path to be selected before pin verification */
5831fa
+} cac_private_data_t;
5831fa
+
5831fa
+#define CAC_DATA(card) ((cac_private_data_t*)card->drv_data)
5831fa
+
5831fa
+/*
5831fa
+ * Set up the normal CAC paths
5831fa
+ */
5831fa
+#define CAC_1_RID "\xA0\x00\x00\x00\x79"
5831fa
+#define CAC_TO_AID(x) x, sizeof(x)-1
5831fa
+
5831fa
+
5831fa
+#define MAX_CAC_SLOTS 16		/* Maximum number of slots is 16 now */
5831fa
+
5831fa
+/* template for a CAC pki object */
5831fa
+static const cac_object_t cac_cac_pki_obj = {
5831fa
+	"CAC Certificate", 0x0, { { 0 }, 0, 0, 0, SC_PATH_TYPE_DF_NAME,
5831fa
+	{ CAC_TO_AID(CAC_1_RID "\x01\x00") } }
5831fa
+};
5831fa
+
5831fa
+/* template for emulated cuid */
5831fa
+static const cac_cuid_t cac_cac_cuid = {
5831fa
+	{ 0xa0, 0x00, 0x00, 0x00, 0x79 },
5831fa
+	2, 2, 0
5831fa
+};
5831fa
+
5831fa
+cac_private_data_t *cac_new_private_data(void);
5831fa
+void cac_free_private_data(cac_private_data_t *priv);
5831fa
+int cac_add_object_to_list(list_t *list, const cac_object_t *object);
5831fa
+const char *get_cac_label(int index);
5831fa
+
5831fa
+#endif /* HAVE_CARD_CAC_COMMON_H */
5831fa
diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c
5831fa
index bd4e0336..f9620009 100644
5831fa
--- a/src/libopensc/card-cac.c
5831fa
+++ b/src/libopensc/card-cac.c
5831fa
@@ -58,8 +58,8 @@
5831fa
 #include "compression.h"
5831fa
 #endif
5831fa
 #include "iso7816.h"
5831fa
+#include "card-cac-common.h"
5831fa
 
5831fa
-#define CAC_MAX_SIZE 4096		/* arbitrary, just needs to be 'large enough' */
5831fa
 /*
5831fa
  *  CAC hardware and APDU constants
5831fa
  */
5831fa
@@ -147,20 +147,6 @@ typedef struct cac_card_url {
5831fa
 	u8 keyCryptoAlgorithm;               /* not used for VM cards */
5831fa
 } cac_card_url_t;
5831fa
 
5831fa
-typedef struct cac_cuid {
5831fa
-	u8 gsc_rid[5];
5831fa
-	u8 manufacturer_id;
5831fa
-	u8 card_type;
5831fa
-	u8 card_id;
5831fa
-} cac_cuid_t;
5831fa
-
5831fa
-/* data structures to store meta data about CAC objects */
5831fa
-typedef struct cac_object {
5831fa
-	const char *name;
5831fa
-	int fd;
5831fa
-	sc_path_t path;
5831fa
-} cac_object_t;
5831fa
-
5831fa
 #define CAC_MAX_OBJECTS 16
5831fa
 
5831fa
 typedef struct {
5831fa
@@ -190,82 +176,10 @@ typedef struct {
5831fa
 #define CAC_OBJECT_TYPE_TLV_FILE	4
5831fa
 #define CAC_OBJECT_TYPE_GENERIC		5
5831fa
 
5831fa
-/*
5831fa
- * CAC private data per card state
5831fa
- */
5831fa
-typedef struct cac_private_data {
5831fa
-	int object_type;		/* select set this so we know how to read the file */
5831fa
-	int cert_next;			/* index number for the next certificate found in the list */
5831fa
-	u8 *cache_buf;			/* cached version of the currently selected file */
5831fa
-	size_t cache_buf_len;		/* length of the cached selected file */
5831fa
-	int cached;			/* is the cached selected file valid */
5831fa
-	cac_cuid_t cuid;                /* card unique ID from the CCC */
5831fa
-	u8 *cac_id;                     /* card serial number */
5831fa
-	size_t cac_id_len;              /* card serial number len */
5831fa
-	list_t pki_list;                /* list of pki containers */
5831fa
-	cac_object_t *pki_current;      /* current pki object _ctl function */
5831fa
-	list_t general_list;            /* list of general containers */
5831fa
-	cac_object_t *general_current;  /* current object for _ctl function */
5831fa
-	sc_path_t *aca_path;		/* ACA path to be selected before pin verification */
5831fa
-} cac_private_data_t;
5831fa
-
5831fa
-#define CAC_DATA(card) ((cac_private_data_t*)card->drv_data)
5831fa
-
5831fa
-static int cac_list_compare_path(const void *a, const void *b)
5831fa
-{
5831fa
-	if (a == NULL || b == NULL)
5831fa
-		return 1;
5831fa
-	return memcmp( &((cac_object_t *) a)->path,
5831fa
-		&((cac_object_t *) b)->path, sizeof(sc_path_t));
5831fa
-}
5831fa
-
5831fa
-/* For SimCList autocopy, we need to know the size of the data elements */
5831fa
-static size_t cac_list_meter(const void *el) {
5831fa
-	return sizeof(cac_object_t);
5831fa
-}
5831fa
-
5831fa
-static cac_private_data_t *cac_new_private_data(void)
5831fa
-{
5831fa
-	cac_private_data_t *priv;
5831fa
-	priv = calloc(1, sizeof(cac_private_data_t));
5831fa
-	if (!priv)
5831fa
-		return NULL;
5831fa
-	list_init(&priv->pki_list);
5831fa
-	list_attributes_comparator(&priv->pki_list, cac_list_compare_path);
5831fa
-	list_attributes_copy(&priv->pki_list, cac_list_meter, 1);
5831fa
-	list_init(&priv->general_list);
5831fa
-	list_attributes_comparator(&priv->general_list, cac_list_compare_path);
5831fa
-	list_attributes_copy(&priv->general_list, cac_list_meter, 1);
5831fa
-	/* set other fields as appropriate */
5831fa
-
5831fa
-	return priv;
5831fa
-}
5831fa
-
5831fa
-static void cac_free_private_data(cac_private_data_t *priv)
5831fa
-{
5831fa
-	free(priv->cac_id);
5831fa
-	free(priv->cache_buf);
5831fa
-	free(priv->aca_path);
5831fa
-	list_destroy(&priv->pki_list);
5831fa
-	list_destroy(&priv->general_list);
5831fa
-	free(priv);
5831fa
-	return;
5831fa
-}
5831fa
-
5831fa
-static int cac_add_object_to_list(list_t *list, const cac_object_t *object)
5831fa
-{
5831fa
-	if (list_append(list, object) < 0)
5831fa
-		return SC_ERROR_UNKNOWN;
5831fa
-	return SC_SUCCESS;
5831fa
-}
5831fa
-
5831fa
 /*
5831fa
  * Set up the normal CAC paths
5831fa
  */
5831fa
-#define CAC_TO_AID(x) x, sizeof(x)-1
5831fa
-
5831fa
 #define CAC_2_RID "\xA0\x00\x00\x01\x16"
5831fa
-#define CAC_1_RID "\xA0\x00\x00\x00\x79"
5831fa
 
5831fa
 static const sc_path_t cac_ACA_Path = {
5831fa
 	"", 0,
5831fa
@@ -279,39 +193,6 @@ static const sc_path_t cac_CCC_Path = {
5831fa
 	{ CAC_TO_AID(CAC_2_RID "\xDB\x00") }
5831fa
 };
5831fa
 
5831fa
-#define MAX_CAC_SLOTS 16		/* Maximum number of slots is 16 now */
5831fa
-/* default certificate labels for the CAC card */
5831fa
-static const char *cac_labels[MAX_CAC_SLOTS] = {
5831fa
-	"CAC ID Certificate",
5831fa
-	"CAC Email Signature Certificate",
5831fa
-	"CAC Email Encryption Certificate",
5831fa
-	"CAC Cert 4",
5831fa
-	"CAC Cert 5",
5831fa
-	"CAC Cert 6",
5831fa
-	"CAC Cert 7",
5831fa
-	"CAC Cert 8",
5831fa
-	"CAC Cert 9",
5831fa
-	"CAC Cert 10",
5831fa
-	"CAC Cert 11",
5831fa
-	"CAC Cert 12",
5831fa
-	"CAC Cert 13",
5831fa
-	"CAC Cert 14",
5831fa
-	"CAC Cert 15",
5831fa
-	"CAC Cert 16"
5831fa
-};
5831fa
-
5831fa
-/* template for a CAC pki object */
5831fa
-static const cac_object_t cac_cac_pki_obj = {
5831fa
-	"CAC Certificate", 0x0, { { 0 }, 0, 0, 0, SC_PATH_TYPE_DF_NAME,
5831fa
-	{ CAC_TO_AID(CAC_1_RID "\x01\x00") } }
5831fa
-};
5831fa
-
5831fa
-/* template for emulated cuid */
5831fa
-static const cac_cuid_t cac_cac_cuid = {
5831fa
-	{ 0xa0, 0x00, 0x00, 0x00, 0x79 },
5831fa
-	2, 2, 0
5831fa
-};
5831fa
-
5831fa
 /*
5831fa
  *  CAC general objects defined in 4.3.1.2 of CAC Applet Developer Guide Version 1.0.
5831fa
  *   doubles as a source for CAC-2 labels.
5831fa
@@ -1178,7 +1059,7 @@ static int cac_get_properties(sc_card_t *card, cac_properties_t *prop)
5831fa
  *
5831fa
  * The rest is just copied from iso7816_select_file
5831fa
  */
5831fa
-static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out, int type)
5831fa
+static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
5831fa
 {
5831fa
 	struct sc_context *ctx;
5831fa
 	struct sc_apdu apdu;
5831fa
@@ -1356,7 +1237,7 @@ static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc
5831fa
 
5831fa
 static int cac_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
5831fa
 {
5831fa
-	return cac_select_file_by_type(card, in_path, file_out, card->type);
5831fa
+	return cac_select_file_by_type(card, in_path, file_out);
5831fa
 }
5831fa
 
5831fa
 static int cac_finish(sc_card_t *card)
5831fa
@@ -1374,13 +1255,13 @@ static int cac_finish(sc_card_t *card)
5831fa
 /* select the Card Capabilities Container on CAC-2 */
5831fa
 static int cac_select_CCC(sc_card_t *card)
5831fa
 {
5831fa
-	return cac_select_file_by_type(card, &cac_CCC_Path, NULL, SC_CARD_TYPE_CAC_II);
5831fa
+	return cac_select_file_by_type(card, &cac_CCC_Path, NULL);
5831fa
 }
5831fa
 
5831fa
 /* Select ACA in non-standard location */
5831fa
 static int cac_select_ACA(sc_card_t *card)
5831fa
 {
5831fa
-	return cac_select_file_by_type(card, &cac_ACA_Path, NULL, SC_CARD_TYPE_CAC_II);
5831fa
+	return cac_select_file_by_type(card, &cac_ACA_Path, NULL);
5831fa
 }
5831fa
 
5831fa
 static int cac_path_from_cardurl(sc_card_t *card, sc_path_t *path, cac_card_url_t *val, int len)
5831fa
@@ -1432,7 +1313,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int
5831fa
 	/* Call without OID set will just select the AID without subseqent
5831fa
 	 * OID selection, which we need to figure out just now
5831fa
 	 */
5831fa
-	cac_select_file_by_type(card, &new_object.path, NULL, SC_CARD_TYPE_CAC_II);
5831fa
+	cac_select_file_by_type(card, &new_object.path, NULL);
5831fa
 	r = cac_get_properties(card, &prop);
5831fa
 	if (r < 0)
5831fa
 		return SC_ERROR_INTERNAL;
5831fa
@@ -1444,7 +1325,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int
5831fa
 
5831fa
 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
 		    "ACA: pki_object found, cert_next=%d (%s), privkey=%d",
5831fa
-		    priv->cert_next, cac_labels[priv->cert_next],
5831fa
+		    priv->cert_next, get_cac_label(priv->cert_next),
5831fa
 		    prop.objects[i].privatekey);
5831fa
 
5831fa
 		/* If the private key is not initialized, we can safely
5831fa
@@ -1460,7 +1341,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int
5831fa
 		memcpy(new_object.path.value, &prop.objects[i].oid, 2);
5831fa
 		new_object.path.len = 2;
5831fa
 		new_object.path.type = SC_PATH_TYPE_FILE_ID;
5831fa
-		new_object.name = cac_labels[priv->cert_next];
5831fa
+		new_object.name = get_cac_label(priv->cert_next);
5831fa
 		new_object.fd = priv->cert_next+1;
5831fa
 		cac_add_object_to_list(&priv->pki_list, &new_object);
5831fa
 		priv->cert_next++;
5831fa
@@ -1488,7 +1369,7 @@ static int cac_parse_cardurl(sc_card_t *card, cac_private_data_t *priv, cac_card
5831fa
 		 */
5831fa
 		if (priv->cert_next >= MAX_CAC_SLOTS)
5831fa
 			break; /* don't fail just because we have more certs than we can support */
5831fa
-		new_object.name = cac_labels[priv->cert_next];
5831fa
+		new_object.name = get_cac_label(priv->cert_next);
5831fa
 		new_object.fd = priv->cert_next+1;
5831fa
 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: pki_object found, cert_next=%d (%s),", priv->cert_next, new_object.name);
5831fa
 		cac_add_object_to_list(&priv->pki_list, &new_object);
5831fa
@@ -1629,7 +1510,7 @@ static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, u8 *tl,
5831fa
 			if (r < 0)
5831fa
 				return r;
5831fa
 
5831fa
-			r = cac_select_file_by_type(card, &new_path, NULL, SC_CARD_TYPE_CAC_II);
5831fa
+			r = cac_select_file_by_type(card, &new_path, NULL);
5831fa
 			if (r < 0)
5831fa
 				return r;
5831fa
 
5831fa
@@ -1740,7 +1621,7 @@ static int cac_select_pki_applet(sc_card_t *card, int index)
5831fa
 {
5831fa
 	sc_path_t applet_path = cac_cac_pki_obj.path;
5831fa
 	applet_path.aid.value[applet_path.aid.len-1] = index;
5831fa
-	return cac_select_file_by_type(card, &applet_path, NULL, SC_CARD_TYPE_CAC_II);
5831fa
+	return cac_select_file_by_type(card, &applet_path, NULL);
5831fa
 }
5831fa
 
5831fa
 /*
5831fa
@@ -1785,7 +1666,7 @@ static int cac_populate_cac_alt(sc_card_t *card, int index, cac_private_data_t *
5831fa
 	for (i = index; i < MAX_CAC_SLOTS; i++) {
5831fa
 		r = cac_select_pki_applet(card, i);
5831fa
 		if (r == SC_SUCCESS) {
5831fa
-			pki_obj.name = cac_labels[i];
5831fa
+			pki_obj.name = get_cac_label(i);
5831fa
 			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
 			    "CAC: pki_object found, cert_next=%d (%s),", i, pki_obj.name);
5831fa
 			pki_obj.path.aid.value[pki_obj.path.aid.len-1] = i;
5831fa
@@ -1796,8 +1677,7 @@ static int cac_populate_cac_alt(sc_card_t *card, int index, cac_private_data_t *
5831fa
 
5831fa
 	/* populate non-PKI objects */
5831fa
 	for (i=0; i < cac_object_count; i++) {
5831fa
-		r = cac_select_file_by_type(card, &cac_objects[i].path, NULL,
5831fa
-		    SC_CARD_TYPE_CAC_II);
5831fa
+		r = cac_select_file_by_type(card, &cac_objects[i].path, NULL);
5831fa
 		if (r == SC_SUCCESS) {
5831fa
 			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
 			    "CAC: obj_object found, cert_next=%d (%s),",
5831fa
diff --git a/src/libopensc/card-cac1.c b/src/libopensc/card-cac1.c
5831fa
new file mode 100644
5831fa
index 00000000..f3a16547
5831fa
--- /dev/null
5831fa
+++ b/src/libopensc/card-cac1.c
5831fa
@@ -0,0 +1,563 @@
5831fa
+/*
5831fa
+ * card-cac1.c: Support for legacy CAC-1
5831fa
+ * card-default.c: Support for cards with no driver
5831fa
+ *
5831fa
+ * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5831fa
+ * Copyright (C) 2005,2006,2007,2008,2009,2010 Douglas E. Engert <deengert@anl.gov>
5831fa
+ * Copyright (C) 2006, Identity Alliance, Thomas Harning <thomas.harning@identityalliance.com>
5831fa
+ * Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
5831fa
+ * Copyright (C) 2016 - 2018, Red Hat, Inc.
5831fa
+ *
5831fa
+ * CAC driver author: Robert Relyea <rrelyea@redhat.com>
5831fa
+ * Further work: Jakub Jelen <jjelen@redhat.com>
5831fa
+ *
5831fa
+ * This library is free software; you can redistribute it and/or
5831fa
+ * modify it under the terms of the GNU Lesser General Public
5831fa
+ * License as published by the Free Software Foundation; either
5831fa
+ * version 2.1 of the License, or (at your option) any later version.
5831fa
+ *
5831fa
+ * This library is distributed in the hope that it will be useful,
5831fa
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5831fa
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5831fa
+ * Lesser General Public License for more details.
5831fa
+ *
5831fa
+ * You should have received a copy of the GNU Lesser General Public
5831fa
+ * License along with this library; if not, write to the Free Software
5831fa
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5831fa
+ */
5831fa
+
5831fa
+#if HAVE_CONFIG_H
5831fa
+#include "config.h"
5831fa
+#endif
5831fa
+
5831fa
+#include <ctype.h>
5831fa
+#include <fcntl.h>
5831fa
+#include <limits.h>
5831fa
+#include <stdlib.h>
5831fa
+#include <string.h>
5831fa
+
5831fa
+#ifdef _WIN32
5831fa
+#include <io.h>
5831fa
+#else
5831fa
+#include <unistd.h>
5831fa
+#endif
5831fa
+
5831fa
+#ifdef ENABLE_OPENSSL
5831fa
+	/* openssl only needed for card administration */
5831fa
+#include <openssl/evp.h>
5831fa
+#include <openssl/bio.h>
5831fa
+#include <openssl/pem.h>
5831fa
+#include <openssl/rand.h>
5831fa
+#include <openssl/rsa.h>
5831fa
+#endif /* ENABLE_OPENSSL */
5831fa
+
5831fa
+#include "internal.h"
5831fa
+#include "simpletlv.h"
5831fa
+#include "cardctl.h"
5831fa
+#ifdef ENABLE_ZLIB
5831fa
+#include "compression.h"
5831fa
+#endif
5831fa
+#include "iso7816.h"
5831fa
+#include "card-cac-common.h"
5831fa
+
5831fa
+/*
5831fa
+ *  CAC hardware and APDU constants
5831fa
+ */
5831fa
+#define CAC_INS_GET_CERTIFICATE       0x36  /* CAC1 command to read a certificate */
5831fa
+
5831fa
+/*
5831fa
+ * OLD cac read certificate, only use with CAC-1 card.
5831fa
+ */
5831fa
+static int cac_cac1_get_certificate(sc_card_t *card, u8 **out_buf, size_t *out_len)
5831fa
+{
5831fa
+	u8 buf[CAC_MAX_SIZE];
5831fa
+	u8 *out_ptr;
5831fa
+	size_t size = 0;
5831fa
+	size_t left = 0;
5831fa
+	size_t len, next_len;
5831fa
+	sc_apdu_t apdu;
5831fa
+	int r = SC_SUCCESS;
5831fa
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+	/* get the size */
5831fa
+	size = left = *out_buf ? *out_len : sizeof(buf);
5831fa
+	out_ptr = *out_buf ? *out_buf : buf;
5831fa
+	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, CAC_INS_GET_CERTIFICATE, 0, 0 );
5831fa
+	next_len = MIN(left, 100);
5831fa
+	for (; left > 0; left -= len, out_ptr += len) {
5831fa
+		len = next_len;
5831fa
+		apdu.resp = out_ptr;
5831fa
+		apdu.le = len;
5831fa
+		apdu.resplen = left;
5831fa
+		r = sc_transmit_apdu(card, &apdu);
5831fa
+		if (r < 0) {
5831fa
+			break;
5831fa
+		}
5831fa
+		if (apdu.resplen == 0) {
5831fa
+			r = SC_ERROR_INTERNAL;
5831fa
+			break;
5831fa
+		}
5831fa
+		/* in the old CAC-1, 0x63 means 'more data' in addition to 'pin failed' */
5831fa
+		if (apdu.sw1 != 0x63)  {
5831fa
+			/* we've either finished reading, or hit an error, break */
5831fa
+			r = sc_check_sw(card, apdu.sw1, apdu.sw2);
5831fa
+			left -= len;
5831fa
+			break;
5831fa
+		}
5831fa
+		next_len = MIN(left, apdu.sw2);
5831fa
+	}
5831fa
+	if (r < 0) {
5831fa
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
5831fa
+	}
5831fa
+	r = size - left;
5831fa
+	if (*out_buf == NULL) {
5831fa
+		*out_buf = malloc(r);
5831fa
+		if (*out_buf == NULL) {
5831fa
+			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
+			    SC_ERROR_OUT_OF_MEMORY);
5831fa
+		}
5831fa
+		memcpy(*out_buf, buf, r);
5831fa
+	}
5831fa
+	*out_len = r;
5831fa
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
5831fa
+}
5831fa
+
5831fa
+/*
5831fa
+ * Callers of this may be expecting a certificate,
5831fa
+ * select file will have saved the object type for us
5831fa
+ * as well as set that we want the cert from the object.
5831fa
+ */
5831fa
+static int cac_read_binary(sc_card_t *card, unsigned int idx,
5831fa
+		unsigned char *buf, size_t count, unsigned long flags)
5831fa
+{
5831fa
+	cac_private_data_t * priv = CAC_DATA(card);
5831fa
+	int r = 0;
5831fa
+	u8 *val = NULL;
5831fa
+	u8 *cert_ptr;
5831fa
+	size_t val_len;
5831fa
+	size_t len, cert_len;
5831fa
+	u8 cert_type;
5831fa
+
5831fa
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+
5831fa
+	/* if we didn't return it all last time, return the remainder */
5831fa
+	if (priv->cached) {
5831fa
+		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
5831fa
+			 "returning cached value idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u",
5831fa
+			 idx, count);
5831fa
+		if (idx > priv->cache_buf_len) {
5831fa
+			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_END_REACHED);
5831fa
+		}
5831fa
+		len = MIN(count, priv->cache_buf_len-idx);
5831fa
+		memcpy(buf, &priv->cache_buf[idx], len);
5831fa
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, len);
5831fa
+	}
5831fa
+
5831fa
+	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
5831fa
+		 "clearing cache idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u",
5831fa
+		 idx, count);
5831fa
+	if (priv->cache_buf) {
5831fa
+		free(priv->cache_buf);
5831fa
+		priv->cache_buf = NULL;
5831fa
+		priv->cache_buf_len = 0;
5831fa
+	}
5831fa
+
5831fa
+	r = cac_cac1_get_certificate(card, &val, &val_len);
5831fa
+	if (r < 0)
5831fa
+		goto done;
5831fa
+
5831fa
+	cert_type = val[0];
5831fa
+	cert_ptr = val + 1;
5831fa
+	cert_len = val_len - 1;
5831fa
+
5831fa
+	/* if the info byte is 1, then the cert is compressed, decompress it */
5831fa
+	if ((cert_type & 0x3) == 1) {
5831fa
+#ifdef ENABLE_ZLIB
5831fa
+		r = sc_decompress_alloc(&priv->cache_buf, &priv->cache_buf_len,
5831fa
+			cert_ptr, cert_len, COMPRESSION_AUTO);
5831fa
+#else
5831fa
+		sc_log(card->ctx, "CAC compression not supported, no zlib");
5831fa
+		r = SC_ERROR_NOT_SUPPORTED;
5831fa
+#endif
5831fa
+		if (r)
5831fa
+			goto done;
5831fa
+		cert_ptr = val;
5831fa
+	} else if (cert_len > 0) {
5831fa
+		priv->cache_buf = malloc(cert_len);
5831fa
+		if (priv->cache_buf == NULL) {
5831fa
+			r = SC_ERROR_OUT_OF_MEMORY;
5831fa
+			goto done;
5831fa
+		}
5831fa
+		priv->cache_buf_len = cert_len;
5831fa
+		memcpy(priv->cache_buf, cert_ptr, cert_len);
5831fa
+	}
5831fa
+
5831fa
+	/* OK we've read the data, now copy the required portion out to the callers buffer */
5831fa
+	priv->cached = 1;
5831fa
+	len = MIN(count, priv->cache_buf_len-idx);
5831fa
+	memcpy(buf, &priv->cache_buf[idx], len);
5831fa
+	r = len;
5831fa
+done:
5831fa
+	if (val)
5831fa
+		free(val);
5831fa
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
5831fa
+}
5831fa
+
5831fa
+/*
5831fa
+ * CAC cards use SC_PATH_SELECT_OBJECT_ID rather than SC_PATH_SELECT_FILE_ID. In order to use more
5831fa
+ * of the PKCS #15 structure, we call the selection SC_PATH_SELECT_FILE_ID, but we set p1 to 2 instead
5831fa
+ * of 0. Also cac1 does not do any FCI, but it doesn't understand not selecting it. It returns invalid INS
5831fa
+ * if it doesn't like anything about the select, so we always 'request' FCI for CAC1
5831fa
+ *
5831fa
+ * The rest is just copied from iso7816_select_file
5831fa
+ */
5831fa
+static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
5831fa
+{
5831fa
+	struct sc_context *ctx;
5831fa
+	struct sc_apdu apdu;
5831fa
+	unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
5831fa
+	unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
5831fa
+	int r, pathlen, pathtype;
5831fa
+	struct sc_file *file = NULL;
5831fa
+	cac_private_data_t * priv = CAC_DATA(card);
5831fa
+
5831fa
+	assert(card != NULL && in_path != NULL);
5831fa
+	ctx = card->ctx;
5831fa
+
5831fa
+	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+
5831fa
+	memcpy(path, in_path->value, in_path->len);
5831fa
+	pathlen = in_path->len;
5831fa
+	pathtype = in_path->type;
5831fa
+
5831fa
+	sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
+		 "path->aid=%x %x %x %x %x %x %x  len=%"SC_FORMAT_LEN_SIZE_T"u, path->value = %x %x %x %x len=%"SC_FORMAT_LEN_SIZE_T"u path->type=%d (%x)",
5831fa
+		 in_path->aid.value[0], in_path->aid.value[1],
5831fa
+		 in_path->aid.value[2], in_path->aid.value[3],
5831fa
+		 in_path->aid.value[4], in_path->aid.value[5],
5831fa
+		 in_path->aid.value[6], in_path->aid.len, in_path->value[0],
5831fa
+		 in_path->value[1], in_path->value[2], in_path->value[3],
5831fa
+		 in_path->len, in_path->type, in_path->type);
5831fa
+	sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "file_out=%p index=%d count=%d\n",
5831fa
+		 file_out, in_path->index, in_path->count);
5831fa
+
5831fa
+	/* Sigh, sc_key_select expects paths to keys to have specific formats. There is no override.
5831fa
+	 * we have to add some bytes to the path to make it happy. A better fix would be to give sc_key_file
5831fa
+	 * a flag that says 'no, really this path is fine'.  We only need to do this for private keys */
5831fa
+	if ((pathlen > 2) && (pathlen <= 4) && memcmp(path, "\x3F\x00", 2) == 0) {
5831fa
+		if (pathlen > 2) {
5831fa
+			path += 2;
5831fa
+			pathlen -= 2;
5831fa
+		}
5831fa
+	}
5831fa
+
5831fa
+
5831fa
+	/* CAC has multiple different type of objects that aren't PKCS #15. When we read
5831fa
+	 * them we need convert them to something PKCS #15 would understand. Find the object
5831fa
+	 * and object type here:
5831fa
+	 */
5831fa
+	if (priv) { /* don't record anything if we haven't been initialized yet */
5831fa
+		/* forget any old cached values */
5831fa
+		if (priv->cache_buf) {
5831fa
+			free(priv->cache_buf);
5831fa
+			priv->cache_buf = NULL;
5831fa
+		}
5831fa
+		priv->cache_buf_len = 0;
5831fa
+		priv->cached = 0;
5831fa
+	}
5831fa
+
5831fa
+	if (in_path->aid.len) {
5831fa
+		if (!pathlen) {
5831fa
+			memcpy(path, in_path->aid.value, in_path->aid.len);
5831fa
+			pathlen = in_path->aid.len;
5831fa
+			pathtype = SC_PATH_TYPE_DF_NAME;
5831fa
+		} else {
5831fa
+			/* First, select the application */
5831fa
+			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"select application" );
5831fa
+			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
5831fa
+			apdu.data = in_path->aid.value;
5831fa
+			apdu.datalen = in_path->aid.len;
5831fa
+			apdu.lc = in_path->aid.len;
5831fa
+
5831fa
+			r = sc_transmit_apdu(card, &apdu);
5831fa
+			LOG_TEST_RET(ctx, r, "APDU transmit failed");
5831fa
+			r = sc_check_sw(card, apdu.sw1, apdu.sw2);
5831fa
+			if (r)
5831fa
+				LOG_FUNC_RETURN(ctx, r);
5831fa
+
5831fa
+		}
5831fa
+	}
5831fa
+
5831fa
+	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
5831fa
+
5831fa
+	switch (pathtype) {
5831fa
+	/* ideally we would had SC_PATH_TYPE_OBJECT_ID and add code to the iso7816 select.
5831fa
+	 * Unfortunately we'd also need to update the caching code as well. For now just
5831fa
+	 * use FILE_ID and change p1 here */
5831fa
+	case SC_PATH_TYPE_FILE_ID:
5831fa
+		apdu.p1 = 2;
5831fa
+		if (pathlen != 2)
5831fa
+			return SC_ERROR_INVALID_ARGUMENTS;
5831fa
+		break;
5831fa
+	case SC_PATH_TYPE_DF_NAME:
5831fa
+		apdu.p1 = 4;
5831fa
+		break;
5831fa
+	default:
5831fa
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
5831fa
+	}
5831fa
+	apdu.lc = pathlen;
5831fa
+	apdu.data = path;
5831fa
+	apdu.datalen = pathlen;
5831fa
+	apdu.resp = buf;
5831fa
+	apdu.resplen = sizeof(buf);
5831fa
+	apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
5831fa
+	apdu.p2 = 0x00;
5831fa
+
5831fa
+	r = sc_transmit_apdu(card, &apdu);
5831fa
+	LOG_TEST_RET(ctx, r, "APDU transmit failed");
5831fa
+
5831fa
+	if (file_out == NULL) {
5831fa
+		/* For some cards 'SELECT' can be only with request to return FCI/FCP. */
5831fa
+		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
5831fa
+		if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
5831fa
+			apdu.p2 = 0x00;
5831fa
+			apdu.resplen = sizeof(buf);
5831fa
+			if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
5831fa
+				r = sc_check_sw(card, apdu.sw1, apdu.sw2);
5831fa
+		}
5831fa
+		if (apdu.sw1 == 0x61)
5831fa
+			LOG_FUNC_RETURN(ctx, SC_SUCCESS);
5831fa
+		LOG_FUNC_RETURN(ctx, r);
5831fa
+	}
5831fa
+
5831fa
+	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
5831fa
+	if (r)
5831fa
+		LOG_FUNC_RETURN(ctx, r);
5831fa
+
5831fa
+	/* CAC cards never return FCI, fake one */
5831fa
+	file = sc_file_new();
5831fa
+	if (file == NULL)
5831fa
+			LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
5831fa
+	file->path = *in_path;
5831fa
+	file->size = CAC_MAX_SIZE; /* we don't know how big, just give a large size until we can read the file */
5831fa
+
5831fa
+	*file_out = file;
5831fa
+	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
5831fa
+
5831fa
+}
5831fa
+
5831fa
+static int cac_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
5831fa
+{
5831fa
+	return cac_select_file_by_type(card, in_path, file_out);
5831fa
+}
5831fa
+
5831fa
+static int cac_finish(sc_card_t *card)
5831fa
+{
5831fa
+	cac_private_data_t * priv = CAC_DATA(card);
5831fa
+
5831fa
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+	if (priv) {
5831fa
+		cac_free_private_data(priv);
5831fa
+	}
5831fa
+	return SC_SUCCESS;
5831fa
+}
5831fa
+
5831fa
+
5831fa
+/* select a CAC pki applet by index */
5831fa
+static int cac_select_pki_applet(sc_card_t *card, int index)
5831fa
+{
5831fa
+	sc_path_t applet_path = cac_cac_pki_obj.path;
5831fa
+	applet_path.aid.value[applet_path.aid.len-1] = index;
5831fa
+	return cac_select_file_by_type(card, &applet_path, NULL);
5831fa
+}
5831fa
+
5831fa
+/*
5831fa
+ *  Find the first existing CAC applet. If none found, then this isn't a CAC
5831fa
+ */
5831fa
+static int cac_find_first_pki_applet(sc_card_t *card, int *index_out)
5831fa
+{
5831fa
+	int r, i;
5831fa
+
5831fa
+	for (i = 0; i < MAX_CAC_SLOTS; i++) {
5831fa
+		r = cac_select_pki_applet(card, i);
5831fa
+		if (r == SC_SUCCESS) {
5831fa
+			u8 data[2];
5831fa
+			sc_apdu_t apdu;
5831fa
+
5831fa
+			/* Try to read first two bytes of the buffer to
5831fa
+			 * make sure it is not just malfunctioning card
5831fa
+			 */
5831fa
+			sc_format_apdu(card, &apdu, SC_APDU_CASE_2,
5831fa
+			    CAC_INS_GET_CERTIFICATE, 0x00, 0x00);
5831fa
+			apdu.le = 0x02;
5831fa
+			apdu.resplen = 2;
5831fa
+			apdu.resp = data;
5831fa
+			r = sc_transmit_apdu(card, &apdu);
5831fa
+			/* SW1 = 0x63 means more data in CAC1 */
5831fa
+			if (r == SC_SUCCESS && apdu.sw1 != 0x63)
5831fa
+				continue;
5831fa
+
5831fa
+			*index_out = i;
5831fa
+			return SC_SUCCESS;
5831fa
+		}
5831fa
+	}
5831fa
+	return SC_ERROR_OBJECT_NOT_FOUND;
5831fa
+}
5831fa
+
5831fa
+static int cac_populate_cac1(sc_card_t *card, int index, cac_private_data_t *priv)
5831fa
+{
5831fa
+	int r, i;
5831fa
+	cac_object_t pki_obj = cac_cac_pki_obj;
5831fa
+	u8 buf[100];
5831fa
+	u8 *val;
5831fa
+	size_t val_len;
5831fa
+
5831fa
+	/* populate PKI objects */
5831fa
+	for (i = index; i < MAX_CAC_SLOTS; i++) {
5831fa
+		r = cac_select_pki_applet(card, i);
5831fa
+		if (r == SC_SUCCESS) {
5831fa
+			pki_obj.name = get_cac_label(i);
5831fa
+			sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
+			    "CAC: pki_object found, cert_next=%d (%s),", i, pki_obj.name);
5831fa
+			pki_obj.path.aid.value[pki_obj.path.aid.len-1] = i;
5831fa
+			pki_obj.fd = i+1; /* don't use id of zero */
5831fa
+			cac_add_object_to_list(&priv->pki_list, &pki_obj);
5831fa
+		}
5831fa
+	}
5831fa
+
5831fa
+	/*
5831fa
+	 * create a cuid to simulate the cac 2 cuid.
5831fa
+	 */
5831fa
+	priv->cuid = cac_cac_cuid;
5831fa
+	/* create a serial number by hashing the first 100 bytes of the
5831fa
+	 * first certificate on the card */
5831fa
+	r = cac_select_pki_applet(card, index);
5831fa
+	if (r < 0) {
5831fa
+		return r; /* shouldn't happen unless the card has been removed or is malfunctioning */
5831fa
+	}
5831fa
+	val = buf;
5831fa
+	val_len = sizeof(buf);
5831fa
+	r = cac_cac1_get_certificate(card, &val, &val_len);
5831fa
+	if (r >= 0) {
5831fa
+		priv->cac_id = malloc(20);
5831fa
+		if (priv->cac_id == NULL) {
5831fa
+			return SC_ERROR_OUT_OF_MEMORY;
5831fa
+		}
5831fa
+#ifdef ENABLE_OPENSSL
5831fa
+		SHA1(val, val_len, priv->cac_id);
5831fa
+		priv->cac_id_len = 20;
5831fa
+		sc_debug_hex(card->ctx, SC_LOG_DEBUG_VERBOSE,
5831fa
+		    "cuid", priv->cac_id, priv->cac_id_len);
5831fa
+#else
5831fa
+		sc_log(card->ctx, "OpenSSL Required");
5831fa
+		return SC_ERROR_NOT_SUPPORTED;
5831fa
+#endif /* ENABLE_OPENSSL */
5831fa
+	}
5831fa
+	return SC_SUCCESS;
5831fa
+}
5831fa
+
5831fa
+/*
5831fa
+ * Look for a CAC card. If it exists, initialize our data structures
5831fa
+ */
5831fa
+static int cac_find_and_initialize(sc_card_t *card, int initialize)
5831fa
+{
5831fa
+	int r, index;
5831fa
+	cac_private_data_t *priv = NULL;
5831fa
+
5831fa
+	/* already initialized? */
5831fa
+	if (card->drv_data) {
5831fa
+		return SC_SUCCESS;
5831fa
+	}
5831fa
+
5831fa
+	/* is this a CAC Alt token without any accompanying structures */
5831fa
+	r = cac_find_first_pki_applet(card, &index);
5831fa
+	if (r == SC_SUCCESS) {
5831fa
+		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "PKI applet found, is bare CAC-1");
5831fa
+		if (!initialize) /* match card only */
5831fa
+			return r;
5831fa
+
5831fa
+		if (!priv) {
5831fa
+			priv = cac_new_private_data();
5831fa
+			if (!priv)
5831fa
+				return SC_ERROR_OUT_OF_MEMORY;
5831fa
+		}
5831fa
+		card->drv_data = priv; /* needed for the read_binary() */
5831fa
+		r = cac_populate_cac1(card, index, priv);
5831fa
+		if (r == SC_SUCCESS) {
5831fa
+			card->type = SC_CARD_TYPE_CAC_I;
5831fa
+			return r;
5831fa
+		}
5831fa
+		card->drv_data = NULL; /* reset on failure */
5831fa
+	}
5831fa
+	if (priv) {
5831fa
+		cac_free_private_data(priv);
5831fa
+	}
5831fa
+	return r;
5831fa
+}
5831fa
+
5831fa
+
5831fa
+/* NOTE: returns a bool, 1 card matches, 0 it does not */
5831fa
+static int cac_match_card(sc_card_t *card)
5831fa
+{
5831fa
+	int r;
5831fa
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+	/* Since we send an APDU, the card's logout function may be called...
5831fa
+	 * however it may be in dirty memory */
5831fa
+	card->ops->logout = NULL;
5831fa
+
5831fa
+	r = cac_find_and_initialize(card, 0);
5831fa
+	return (r == SC_SUCCESS); /* never match */
5831fa
+}
5831fa
+
5831fa
+
5831fa
+static int cac_init(sc_card_t *card)
5831fa
+{
5831fa
+	int r;
5831fa
+	unsigned long flags;
5831fa
+
5831fa
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
5831fa
+
5831fa
+	r = cac_find_and_initialize(card, 1);
5831fa
+	if (r < 0) {
5831fa
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD);
5831fa
+	}
5831fa
+	flags = SC_ALGORITHM_RSA_RAW;
5831fa
+
5831fa
+	_sc_card_add_rsa_alg(card, 1024, flags, 0); /* mandatory */
5831fa
+	_sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */
5831fa
+	_sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */
5831fa
+
5831fa
+	card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;
5831fa
+
5831fa
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
5831fa
+}
5831fa
+
5831fa
+static struct sc_card_operations cac_ops;
5831fa
+
5831fa
+static struct sc_card_driver cac1_drv = {
5831fa
+	"Common Access Card (CAC 1)",
5831fa
+	"cac1",
5831fa
+	&cac_ops,
5831fa
+	NULL, 0, NULL
5831fa
+};
5831fa
+
5831fa
+static struct sc_card_driver * sc_get_driver(void)
5831fa
+{
5831fa
+	/* Inherit most of the things from the CAC driver */
5831fa
+	struct sc_card_driver *cac_drv = sc_get_cac_driver();
5831fa
+
5831fa
+	cac_ops = *cac_drv->ops;
5831fa
+	cac_ops.match_card = cac_match_card;
5831fa
+	cac_ops.init = cac_init;
5831fa
+	cac_ops.finish = cac_finish;
5831fa
+
5831fa
+	cac_ops.select_file =  cac_select_file; /* need to record object type */
5831fa
+	cac_ops.read_binary = cac_read_binary;
5831fa
+
5831fa
+	return &cac1_drv;
5831fa
+}
5831fa
+
5831fa
+
5831fa
+struct sc_card_driver * sc_get_cac1_driver(void)
5831fa
+{
5831fa
+	return sc_get_driver();
5831fa
+}
5831fa
diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
5831fa
index 5d545b35..f4df17fb 100644
5831fa
--- a/src/libopensc/cards.h
5831fa
+++ b/src/libopensc/cards.h
5831fa
@@ -286,6 +286,7 @@ extern sc_card_driver_t *sc_get_gids_driver(void);
5831fa
 extern sc_card_driver_t *sc_get_jpki_driver(void);
5831fa
 extern sc_card_driver_t *sc_get_coolkey_driver(void);
5831fa
 extern sc_card_driver_t *sc_get_cac_driver(void);
5831fa
+extern sc_card_driver_t *sc_get_cac1_driver(void);
5831fa
 extern sc_card_driver_t *sc_get_npa_driver(void);
5831fa
 
5831fa
 #ifdef __cplusplus
5831fa
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
5831fa
index 98e6038a..5b5d4996 100644
5831fa
--- a/src/libopensc/ctx.c
5831fa
+++ b/src/libopensc/ctx.c
5831fa
@@ -146,6 +146,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
5831fa
 	{ "openpgp",	(void *(*)(void)) sc_get_openpgp_driver },
5831fa
 	{ "jpki",	(void *(*)(void)) sc_get_jpki_driver },
5831fa
 	{ "npa",	(void *(*)(void)) sc_get_npa_driver },
5831fa
+	{ "cac1",	(void *(*)(void)) sc_get_cac1_driver },
5831fa
 	/* The default driver should be last, as it handles all the
5831fa
 	 * unrecognized cards. */
5831fa
 	{ "default",	(void *(*)(void)) sc_get_default_driver },