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