Skip to content

Commit

Permalink
Improve handling of OpenPGP card PIN change and unblock commands
Browse files Browse the repository at this point in the history
"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 <[email protected]>
  • Loading branch information
maciejsszmigiero committed Aug 26, 2016
1 parent 6cbf2bc commit 4e5ff7c
Showing 1 changed file with 46 additions and 2 deletions.
48 changes: 46 additions & 2 deletions src/libopensc/card-openpgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -1531,15 +1533,57 @@ 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.
*/

/* 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,
Expand Down

0 comments on commit 4e5ff7c

Please sign in to comment.