Some CAC / PIV cards do not support Discovery Object

Some CAC card return '6A80` Incorrect parameters in APDU when trying to
read the Discovery object. If it fails other then not found, then we can
not use the Discovery object to test for the active AID.

The test is done in piv_match_card just after doing a SELECT AID for the PIV.
and set CI_DISCOVERY_USELESS if needed. piv_card_reader_lock_obtained will
then not use the Discovery object.

Some older PIV cards, prior to the introduction of the PIV
Discovery and History objects, may get errors trying to read them.
Ignore these errors too.

Remove comment and remove code to check verify Lc=0 as requested in:

https://github.com/OpenSC/OpenSC/pull/1256#pullrequestreview-96124443

They can easily be added back in.

 On branch piv-aid-discovery

 Changes to be committed:
	modified:   src/libopensc/card-piv.c
This commit is contained in:
Doug Engert 2018-02-08 20:08:43 -06:00
parent 27add2ee3c
commit efe7eb598f
1 changed files with 37 additions and 22 deletions

View File

@ -213,6 +213,7 @@ static struct piv_aid piv_aids[] = {
/* will also test after first PIN verify if protected object can be used instead */
#define CI_CANT_USE_GETDATA_FOR_STATE 0x00000008U /* No object to test verification inplace of VERIFY Lc=0 */
#define CI_LEAKS_FILE_NOT_FOUND 0x00000010U /* GET DATA of empty object returns 6A 82 even if PIN not verified */
#define CI_DISCOVERY_USELESS 0x00000020U /* Discovery can not be used to query active AID */
#define CI_OTHER_AID_LOSE_STATE 0x00000100U /* Other drivers match routines may reset our security state and lose AID!!! */
#define CI_NFC_EXPOSE_TOO_MUCH 0x00000200U /* PIN, crypto and objects exposed over NFS in violation of 800-73-3 */
@ -2662,7 +2663,6 @@ err:
}
/* Do not use the cache value but read every time */
static int piv_find_discovery(sc_card_t *card)
{
int r = 0;
@ -2957,7 +2957,7 @@ piv_finish(sc_card_t *card)
static int piv_match_card(sc_card_t *card)
{
int i, k;
int i, i7e, k;
size_t j;
u8 *p, *pe;
sc_file_t aidfile;
@ -3058,7 +3058,7 @@ static int piv_match_card(sc_card_t *card)
* We may get interference on some cards by other drivers trying SELECT_AID before
* we get to see if PIV application is still active.
* putting PIV driver first might help.
* TODO could be cached too
* This may fail if the wrong AID is active
*/
i = piv_find_discovery(card);
@ -3067,6 +3067,22 @@ static int piv_match_card(sc_card_t *card)
i = piv_find_aid(card, &aidfile);
}
if (i >= 0) {
/*
* We now know PIV AID is active, test DISCOVERY object
* Some CAC cards with PIV don't support DISCOVERY and return
* SC_ERROR_INCORRECT_PARAMETERS. Any error other then
* SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
* to test for active AID.
*/
i7e = piv_find_discovery(card);
if (i7e != 0 && i7e != SC_ERROR_FILE_NOT_FOUND) {
priv->card_issues |= CI_DISCOVERY_USELESS;
priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT;
}
}
if (i < 0) {
piv_finish(card);
/* don't match. Does not have a PIV applet. */
@ -3083,7 +3099,7 @@ static int piv_match_card(sc_card_t *card)
static int piv_init(sc_card_t *card)
{
int r;
int r = 0;
piv_private_data_t * priv = PIV_DATA(card);
sc_apdu_t apdu;
unsigned long flags;
@ -3136,7 +3152,7 @@ static int piv_init(sc_card_t *card)
switch(card->type) {
case SC_CARD_TYPE_PIV_II_NEO:
priv->card_issues = CI_NO_EC384
priv->card_issues |= CI_NO_EC384
| CI_VERIFY_630X
| CI_OTHER_AID_LOSE_STATE
| CI_LEAKS_FILE_NOT_FOUND
@ -3146,18 +3162,18 @@ static int piv_init(sc_card_t *card)
break;
case SC_CARD_TYPE_PIV_II_YUBIKEY4:
priv->card_issues = CI_OTHER_AID_LOSE_STATE
priv->card_issues |= CI_OTHER_AID_LOSE_STATE
| CI_LEAKS_FILE_NOT_FOUND;
if (priv->neo_version < 0x00040302)
priv->card_issues |= CI_VERIFY_LC0_FAIL;
break;
case SC_CARD_TYPE_PIV_II_HIST:
priv->card_issues = 0;
priv->card_issues |= 0;
break;
case SC_CARD_TYPE_PIV_II_GENERIC:
priv->card_issues = CI_VERIFY_LC0_FAIL
priv->card_issues |= CI_VERIFY_LC0_FAIL
| CI_OTHER_AID_LOSE_STATE;
/* TODO may need more research */
break;
@ -3196,12 +3212,13 @@ static int piv_init(sc_card_t *card)
* 800-73-3 cards may have a history object and/or a discovery object
* We want to process them now as this has information on what
* keys and certs the card has and how the pin might be used.
* If they fail, ignore it there are optional and introdced in
* NIST 800-73-3 and NIST 800-73-2 so some older cards may
* not handle the requets.
*/
piv_process_history(card);
r = piv_process_discovery(card);
if (r > 0)
r = 0;
piv_process_discovery(card);
priv->pstate=PIV_STATE_NORMAL;
sc_unlock(card) ; /* obtained in piv_match */
@ -3477,7 +3494,6 @@ static int piv_card_reader_lock_obtained(sc_card_t *card, int was_reset)
int r = 0;
u8 temp[256];
size_t templen = sizeof(temp);
struct sc_pin_cmd_data data;
piv_private_data_t * priv = PIV_DATA(card); /* may be null */
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
@ -3494,7 +3510,14 @@ static int piv_card_reader_lock_obtained(sc_card_t *card, int was_reset)
/* first see if AID is active AID by reading discovery object '7E' */
/* If not try selecting AID */
r = piv_find_discovery(card);
/* but if x card does not support DISCOVERY object we can not use it */
if (priv->card_issues & CI_DISCOVERY_USELESS) {
r = SC_ERROR_NO_CARD_SUPPORT;
} else {
r = piv_find_discovery(card);
}
if (r < 0)
r = piv_select_aid(card, piv_aids[0].value, piv_aids[0].len_short, temp, &templen);
@ -3504,15 +3527,7 @@ static int piv_card_reader_lock_obtained(sc_card_t *card, int was_reset)
if (was_reset > 0)
priv->logged_in = SC_PIN_STATE_UNKNOWN;
/* See if VERIFY Lc=empty will tell us the state */
memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_GET_INFO;
data.pin_type = SC_AC_CHV;
data.pin_reference = priv->pin_preference;
/* will try our best to see if logged_in or not */
r = piv_pin_cmd(card, &data, NULL);
r = 0; /* ignore return from piv_pin_cmd */
r = 0;
err:
LOG_FUNC_RETURN(card->ctx, r);