Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround Yubikey bug with SELECT DATA #2969

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Workaround Yubikey bug with SELECT DATA
There is a known issue with Yubikey tokens, that they're requiring
another length byte in APDU for SELECT DATA:
Yubico/yubikey-manager#403

Let's workaround this, by checking return value of SELECT DATA,
and if error indicates that parameters are wrong, let's try
Yubikey-specific ones.
  • Loading branch information
ya-isakov committed Dec 25, 2023
commit fc4886c3710c11a817ffcf67af8e9ae72b8a39e2
39 changes: 39 additions & 0 deletions src/libopensc/card-openpgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,42 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
LOG_FUNC_RETURN(card->ctx, (int)len);
}

/**
* Internal: Same as pgp_select_data, but with Yubikey workaround
* https://github.com/Yubico/yubikey-manager/issues/403
*
* p1: number of an instance (DO 7F21: 0x00 for AUT, 0x01 for DEC and 0x02 for SIG)
*/
static int
pgp_select_data_yubikey(sc_card_t *card, u8 p1)
{
sc_apdu_t apdu;
u8 apdu_data[7];
int r;

LOG_FUNC_CALLED(card->ctx);

sc_log(card->ctx, "select data with: %u (Yubikey workaround)", p1);
// Yubikey wants another length
apdu_data[0] = 0x06;
// create apdu data (taken from spec: SELECT DATA 7.2.5.)
apdu_data[1] = 0x60;
apdu_data[2] = 0x04;
apdu_data[3] = 0x5c;
apdu_data[4] = 0x02;
apdu_data[5] = 0x7f;
apdu_data[6] = 0x21;

// apdu, cla, ins, p1, p2, data, datalen, resp, resplen
sc_format_apdu_ex(&apdu, 0x00, 0xA5, p1, 0x04, apdu_data, sizeof(apdu_data), NULL, 0);

// transmit apdu
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, r);
}

/**
* Internal: SELECT DATA - selects a DO within a DO tag with several instances
Expand Down Expand Up @@ -1809,6 +1845,9 @@ pgp_select_data(sc_card_t *card, u8 p1)
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
// If parameters are incorrect, let's try to read it again, with Yubikey parameters
if (r == SC_ERROR_INCORRECT_PARAMETERS)
return pgp_select_data_yubikey(card, p1);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, r);
}
Expand Down