From 0a6c1c4fb3fee9b27cd71fd97e7e8b40a880286d Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Thu, 11 Aug 2016 18:36:57 +0200 Subject: [PATCH 1/4] Make OpenPGP card user/signature PIN order match PKCS#11 framework _get_auth_object_by_name() in pkcs11/framework-pkcs15.c needs user PIN to be the first one and then next one can be signature PIN, but OpenPGP card had it reversed. Signed-off-by: Maciej S. Szmigiero --- src/libopensc/pkcs15-openpgp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index e327d606..137770fc 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -58,16 +58,16 @@ typedef struct _pgp_pin_cfg { * "Signature PIN2 & "Encryption PIN" are two different PINs - not sync'ed by hardware */ static const pgp_pin_cfg_t pin_cfg_v1[3] = { - { "Signature PIN", 0x01, PGP_USER_PIN_FLAGS, 6, 0 }, // used for PSO:CDS { "Encryption PIN", 0x02, PGP_USER_PIN_FLAGS, 6, 1 }, // used for PSO:DEC, INT-AUT, {GET,PUT} DATA + { "Signature PIN", 0x01, PGP_USER_PIN_FLAGS, 6, 0 }, // used for PSO:CDS { "Admin PIN", 0x03, PGP_ADMIN_PIN_FLAGS, 8, 2 } }; /* OpenPGP cards v2: * "User PIN (sig)" & "User PIN" are the same PIN, but use different references depending on action */ static const pgp_pin_cfg_t pin_cfg_v2[3] = { - { "User PIN (sig)", 0x01, PGP_USER_PIN_FLAGS, 6, 0 }, // used for PSO:CDS { "User PIN", 0x02, PGP_USER_PIN_FLAGS, 6, 0 }, // used for PSO:DEC, INT-AUT, {GET,PUT} DATA + { "User PIN (sig)", 0x01, PGP_USER_PIN_FLAGS, 6, 0 }, // used for PSO:CDS { "Admin PIN", 0x03, PGP_ADMIN_PIN_FLAGS, 8, 2 } }; @@ -216,7 +216,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.auth_id.len = 1; - pin_info.auth_id.value[0] = i + 1; + pin_info.auth_id.value[0] = pin_cfg[i].reference; pin_info.attrs.pin.reference = pin_cfg[i].reference; pin_info.attrs.pin.flags = pin_cfg[i].flags; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_UTF8; From 3e3528bb687500a071e8c2b9bf53328b491e6467 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Thu, 11 Aug 2016 18:38:40 +0200 Subject: [PATCH 2/4] OpenPGP card doesn't support raw RSA so don't set such algo flag According to descriptions of commands "PSO: COMPUTE DIGITAL SIGNATURE", "PSO: DECIPHER" and "INTERNAL AUTHENTICATE" in OpenPGP card spec (versions 1.1 and 2.1.1) the card adds / strips and checks PKCS#1 padding automatically. There is no documented way to perform raw RSA operations on this card so SC_ALGORITHM_RSA_RAW flag shouldn't be set. Signed-off-by: Maciej S. Szmigiero --- src/libopensc/card-openpgp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index ba05ac82..916b38c9 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -569,10 +569,8 @@ pgp_get_card_features(sc_card_t *card) unsigned long flags; /* Is this correct? */ - /* OpenPGP card spec 1.1 & 2.0, section 2.1 */ - flags = SC_ALGORITHM_RSA_RAW; /* OpenPGP card spec 1.1 & 2.0, section 7.2.9 & 7.2.10 */ - flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + flags = SC_ALGORITHM_RSA_PAD_PKCS1; flags |= SC_ALGORITHM_RSA_HASH_NONE; /* Can be generated in card */ flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; From 80f5c8b835c89a869d67fe13d0e55c5905adcee2 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Thu, 11 Aug 2016 18:39:11 +0200 Subject: [PATCH 3/4] Code files don't need execute permission Some .c files had execute permission bit set needlessly. Signed-off-by: Maciej S. Szmigiero --- src/libopensc/card-entersafe.c | 0 src/pkcs15init/pkcs15-openpgp.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/libopensc/card-entersafe.c mode change 100755 => 100644 src/pkcs15init/pkcs15-openpgp.c diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c old mode 100755 new mode 100644 diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c old mode 100755 new mode 100644 From dc476a9f3313a0aab4ea09220a8763765fe639f2 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 14 Aug 2016 01:46:55 +0200 Subject: [PATCH 4/4] Improve handling of OpenPGP card PIN change and unblock commands "CHANGE REFERENCE DATA" (PIN change) and "RESET RETRY COUNTER" (PIN unblock) commands in OpenPGP card have various limitations. These also depend on whether the card is version 1.x or 2.x. Provide helpful debug messages for user in case he is trying to do a PIN command in a way that isn't supported by the card. Also, take into account that version 2.x cards don't support references to PW1-mode 2 (82) in these commands - change them to PW1 (81). Signed-off-by: Maciej S. Szmigiero --- src/libopensc/card-openpgp.c | 48 ++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 916b38c9..35e7c509 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -1518,6 +1518,8 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len) static int pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { + struct pgp_priv_data *priv = DRVDATA(card); + LOG_FUNC_CALLED(card->ctx); if (data->pin_type != SC_AC_CHV) @@ -1531,8 +1533,17 @@ pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) * So, if we receive Ref=1, Ref=2, we must convert to 81, 82... * In OpenPGP v1, the PINs are named CHV1, CHV2, CHV3. * In v2, they are named PW1, PW3 (PW1 operates in 2 modes). - * However, the PIN references (P2 in APDU) are the same in both versions: - * 81 (CHV1 or PW1), 82 (CHV2 or PW1-mode 2), 83 (CHV3 or PW3). + * + * The PIN references (P2 in APDU) for "VERIFY" are the same in both versions: + * 81 (CHV1 or PW1), 82 (CHV2 or PW1-mode 2), 83 (CHV3 or PW3), + * On the other hand from version 2.0 "CHANGE REFERENCE DATA" and + * "RESET RETRY COUNTER" don't support PW1-mode 2 (82) and need this + * value changed to PW1 (81). + * Both of these commands also differ between card versions in that + * v1 cards can use only implicit old PIN or CHV3 test for both commands + * whereas v2 can use both implicit (for PW3) and explicit + * (for special "Resetting Code") PIN test for "RESET RETRY COUNTER" + * and only explicit test for "CHANGE REFERENCE DATA". * * Note that if this function is called from sc_pkcs15_verify_pin() in pkcs15-pin.c, * the Ref is already 81, 82, 83. @@ -1540,6 +1551,39 @@ pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) /* convert the PIN Reference if needed */ data->pin_reference |= 0x80; + + /* check version-dependent constraints */ + if (data->cmd == SC_PIN_CMD_CHANGE || data->cmd == SC_PIN_CMD_UNBLOCK) { + if (priv->bcd_version >= OPENPGP_CARD_2_0) { + if (data->pin_reference == 0x82) + data->pin_reference = 0x81; + + if (data->cmd == SC_PIN_CMD_CHANGE) { + if (data->pin1.len == 0 && + !(data->flags & SC_PIN_CMD_USE_PINPAD)) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, + "v2 cards don't support implicit old PIN for PIN change."); + + data->flags &= ~SC_PIN_CMD_IMPLICIT_CHANGE; + } + } else { + if (data->pin1.len != 0) { + sc_log(card->ctx, + "v1 cards don't support explicit old or CHV3 PIN, PIN ignored."); + sc_log(card->ctx, + "please make sure that you have verified the relevant PIN first."); + data->pin1.len = 0; + } + + data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE; + } + } + + if (data->cmd == SC_PIN_CMD_UNBLOCK && data->pin2.len == 0 && + !(data->flags & SC_PIN_CMD_USE_PINPAD)) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, + "new PIN must be provided for unblock operation."); + /* ensure pin_reference is 81, 82, 83 */ if (!(data->pin_reference == 0x81 || data->pin_reference == 0x82 || data->pin_reference == 0x83)) { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,