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