Blame SOURCES/opensc-0.20.0-cac-pin-change.patch

176fa0
diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c
176fa0
index 099923e5..61e69c88 100644
176fa0
--- a/src/libopensc/card-cac.c
176fa0
+++ b/src/libopensc/card-cac.c
176fa0
@@ -1793,7 +1793,7 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize)
176fa0
 		}
176fa0
 		r = cac_process_ACA(card, priv);
176fa0
 		if (r == SC_SUCCESS) {
176fa0
-			card->type = SC_CARD_TYPE_CAC_II;
176fa0
+			card->type = SC_CARD_TYPE_CAC_ALT_HID;
176fa0
 			card->drv_data = priv;
176fa0
 			return r;
176fa0
 		}
176fa0
@@ -1869,6 +1869,8 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
176fa0
 	 * FIPS 201 4.1.6.1 (numeric only) and * FIPS 140-2
176fa0
 	 * (6 character minimum) requirements.
176fa0
 	 */
176fa0
+	sc_apdu_t apdu;
176fa0
+	u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
176fa0
 	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
176fa0
 
176fa0
 	if (data->cmd == SC_PIN_CMD_CHANGE) {
176fa0
@@ -1881,6 +1883,18 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
176fa0
 				return SC_ERROR_INVALID_DATA;
176fa0
 			}
176fa0
 		}
176fa0
+
176fa0
+		/* We can change the PIN of Giesecke & Devrient CAC ALT tokens
176fa0
+		 * with a bit non-standard APDU */
176fa0
+		if (card->type == SC_CARD_TYPE_CAC_ALT_HID) {
176fa0
+			int r = 0;
176fa0
+			r = iso7816_build_pin_apdu(card, &apdu, data, sbuf, sizeof(sbuf));
176fa0
+			if (r < 0)
176fa0
+				return r;
176fa0
+			/* it requires P1 = 0x01 completely against the ISO specs */
176fa0
+			apdu.p1 = 0x01;
176fa0
+			data->apdu = &apd;;
176fa0
+		}
176fa0
 	}
176fa0
 
176fa0
 	return  iso_drv->ops->pin_cmd(card, data, tries_left);
176fa0
diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
176fa0
index 0ec25a46..16846d15 100644
176fa0
--- a/src/libopensc/cards.h
176fa0
+++ b/src/libopensc/cards.h
176fa0
@@ -244,6 +244,7 @@ enum {
176fa0
 	SC_CARD_TYPE_CAC_GENERIC,
176fa0
 	SC_CARD_TYPE_CAC_I,
176fa0
 	SC_CARD_TYPE_CAC_II,
176fa0
+	SC_CARD_TYPE_CAC_ALT_HID,
176fa0
 
176fa0
 	/* nPA cards */
176fa0
 	SC_CARD_TYPE_NPA = 34000,
176fa0
diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c
176fa0
index b1a0e88f..d41613b2 100644
176fa0
--- a/src/libopensc/iso7816.c
176fa0
+++ b/src/libopensc/iso7816.c
176fa0
@@ -1017,7 +1017,7 @@ iso7816_decipher(struct sc_card *card,
176fa0
 }
176fa0
 
176fa0
 
176fa0
-static int
176fa0
+int
176fa0
 iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
176fa0
 		struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
176fa0
 {
176fa0
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
176fa0
index b519c5d5..8ebf9fbd 100644
176fa0
--- a/src/libopensc/opensc.h
176fa0
+++ b/src/libopensc/opensc.h
176fa0
@@ -1664,6 +1664,19 @@ int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
176fa0
  * */
176fa0
 int iso7816_logout(sc_card_t *card, unsigned char pin_reference);
176fa0
 
176fa0
+/*
176fa0
+ * @brief Format PIN APDU for modifiction by card driver
176fa0
+ *
176fa0
+ * @param[in] card           card
176fa0
+ * @param[in] apdu           apdu structure to update with PIN APDU
176fa0
+ * @param[in] data           pin command data to set into the APDU
176fa0
+ * @param[in] buf            buffer for APDU data field
176fa0
+ * @param[in] buf_len        maximum buffer length
176fa0
+ */
176fa0
+int
176fa0
+iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
176fa0
+		struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len);
176fa0
+
176fa0
 #ifdef __cplusplus
176fa0
 }
176fa0
 #endif
176fa0
diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c
176fa0
index ccb27994..05056ea9 100644
176fa0
--- a/src/libopensc/pkcs15-cac.c
176fa0
+++ b/src/libopensc/pkcs15-cac.c
176fa0
@@ -79,6 +79,7 @@ static const char * cac_get_name(int type)
176fa0
     switch (type) {
176fa0
     case SC_CARD_TYPE_CAC_I: return ("CAC I");
176fa0
     case SC_CARD_TYPE_CAC_II: return ("CAC II");
176fa0
+    case SC_CARD_TYPE_CAC_ALT_HID: return ("CAC ALT HID");
176fa0
     default: break;
176fa0
     }
176fa0
     return ("CAC");