Overview
Comment: | Reset the card and rescan for certificates if we get the ISO 7816 error 6D 00 (Wrong instruction) error from the card when trying to verify. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | piv-reset-on-wronginstruction |
Files: | files | file ages | folders |
SHA1: |
52569c3e74727533fa081ffc00a7cc82 |
User & Date: | rkeene on 2015-07-16 16:06:35 |
Other Links: | branch diff | manifest | tags |
Context
2015-07-16
| ||
16:18 | Updated to retry login if it fails with a 6D 00 (wrong instruction) check-in: 4e30511f94 user: rkeene tags: trunk | |
16:06 | Reset the card and rescan for certificates if we get the ISO 7816 error 6D 00 (Wrong instruction) error from the card when trying to verify. Closed-Leaf check-in: 52569c3e74 user: rkeene tags: piv-reset-on-wronginstruction | |
2015-07-15
| ||
20:05 | Added support for updating the PIN check-in: b5ecb7c2d6 user: rkeene tags: trunk | |
Changes
Modified cackey.c from [3a0d4abad4] to [06b013b460].
︙ | ︙ | |||
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 | * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_set_pin(struct cackey_slot *slot, unsigned char *old_pin, unsigned long old_pin_len, unsigned char *pin, unsigned long pin_len) { struct cackey_pcsc_identity *pcsc_identities; unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; unsigned char old_cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; unsigned char pin_update[sizeof(cac_pin) + sizeof(old_cac_pin)]; unsigned long num_certs; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 | * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_token_present(struct cackey_slot *slot) { cackey_ret pcsc_connect_ret; DWORD reader_len = 0, state = 0, protocol = 0, atr_len; BYTE atr[MAX_ATR_SIZE]; LONG status_ret, scard_reconn_ret; CACKEY_DEBUG_PRINTF("Called."); if (slot->internal) { CACKEY_DEBUG_PRINTF("Returning token present (internal token)"); return(CACKEY_PCSC_S_TOKENPRESENT); } pcsc_connect_ret = cackey_connect_card(slot); if (pcsc_connect_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent"); return(CACKEY_PCSC_E_TOKENABSENT); } CACKEY_DEBUG_PRINTF("Calling SCardStatus() to determine card status"); atr_len = sizeof(atr); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); if (status_ret == SCARD_E_INVALID_HANDLE) { CACKEY_DEBUG_PRINTF("SCardStatus() returned SCARD_E_INVALID_HANDLE, marking is not already connected and trying again"); cackey_mark_slot_reset(slot); pcsc_connect_ret = cackey_connect_card(slot); if (pcsc_connect_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent"); return(CACKEY_PCSC_E_TOKENABSENT); } CACKEY_DEBUG_PRINTF("Calling SCardStatus() again"); atr_len = sizeof(atr); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); } if (status_ret != SCARD_S_SUCCESS) { cackey_mark_slot_reset(slot); if (status_ret == SCARD_W_RESET_CARD) { CACKEY_DEBUG_PRINTF("Reset required, please hold..."); scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1); if (scard_reconn_ret == SCARD_S_SUCCESS) { /* Re-establish transaction, if it was present */ if (slot->transaction_depth > 0) { slot->transaction_depth--; slot->transaction_need_hw_lock = 1; cackey_begin_transaction(slot); } CACKEY_DEBUG_PRINTF("Reset successful, requerying"); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); if (status_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret)); return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent. SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret)); return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret)); return(CACKEY_PCSC_E_TOKENABSENT); } } if ((state & SCARD_ABSENT) == SCARD_ABSENT) { CACKEY_DEBUG_PRINTF("Card is absent, returning token absent"); return(CACKEY_PCSC_E_TOKENABSENT); } CACKEY_DEBUG_PRINTF("Returning token present."); return(CACKEY_PCSC_S_TOKENPRESENT); } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_set_pin(struct cackey_slot *slot, unsigned char *old_pin, unsigned long old_pin_len, unsigned char *pin, unsigned long pin_len) { struct cackey_pcsc_identity *pcsc_identities; unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; unsigned char old_cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; unsigned char pin_update[sizeof(cac_pin) + sizeof(old_cac_pin)]; unsigned long num_certs; |
︙ | ︙ | |||
3236 3237 3238 3239 3240 3241 3242 | * RETURN VALUE * ... * * NOTES * ... * */ | | | > | 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 | * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p, int retries) { struct cackey_pcsc_identity *pcsc_identities; unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; unsigned long num_certs; uint16_t response_code; int tries_remaining; int send_ret; int key_reference = 0x00, have_piv = 0; cackey_ret connect_ret, token_ret; /* Indicate that we do not know about how many tries are remaining */ if (tries_remaining_p) { *tries_remaining_p = -1; } /* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */ |
︙ | ︙ | |||
3271 3272 3273 3274 3275 3276 3277 | /* PIV authentication uses a "key_reference" of 0x80 */ pcsc_identities = cackey_read_certs(slot, NULL, &num_certs); if (num_certs > 0 && pcsc_identities != NULL) { switch (pcsc_identities[0].id_type) { case CACKEY_ID_TYPE_PIV: CACKEY_DEBUG_PRINTF("We have PIV card, so we will attempt to authenticate using the PIV Application key reference"); | | > > > > | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 | /* PIV authentication uses a "key_reference" of 0x80 */ pcsc_identities = cackey_read_certs(slot, NULL, &num_certs); if (num_certs > 0 && pcsc_identities != NULL) { switch (pcsc_identities[0].id_type) { case CACKEY_ID_TYPE_PIV: CACKEY_DEBUG_PRINTF("We have PIV card, so we will attempt to authenticate using the PIV Application key reference"); have_piv = 1; break; default: break; } cackey_free_certs(pcsc_identities, num_certs, 1); } if (have_piv == 1) { key_reference = 0x80; } /* Issue PIN Verify */ send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, key_reference, sizeof(cac_pin), cac_pin, 0x00, &response_code, NULL, NULL); if (send_ret != CACKEY_PCSC_S_OK) { if ((response_code & 0x63C0) == 0x63C0) { tries_remaining = (response_code & 0xF); |
︙ | ︙ | |||
3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 | } if (response_code == 0x6983) { CACKEY_DEBUG_PRINTF("PIN Verification failed, device is locked"); return(CACKEY_PCSC_E_LOCKED); } return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("PIN Verification succeeded"); return(CACKEY_PCSC_S_OK); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 | } if (response_code == 0x6983) { CACKEY_DEBUG_PRINTF("PIN Verification failed, device is locked"); return(CACKEY_PCSC_E_LOCKED); } if (response_code == 0x6d00) { if (have_piv == 1 && retries > 0) { CACKEY_DEBUG_PRINTF("Got ISO 7816 Response \"6D 00\" in response to a VERIFY request."); CACKEY_DEBUG_PRINTF("We did not expect this because it is not mentioned in NIST SP 800-73-3 Part 2 Section 3.2.1"); CACKEY_DEBUG_PRINTF("We are going to try to reset the card and select the applet again."); cackey_mark_slot_reset(slot); connect_ret = cackey_connect_card(slot); if (connect_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Unable to reconnect after resetting the card, returning in error."); return(connect_ret); } CACKEY_DEBUG_PRINTF("Verifying we still have a token."); token_ret = cackey_token_present(slot); if (token_ret != CACKEY_PCSC_S_TOKENPRESENT) { CACKEY_DEBUG_PRINTF("Token not present, returning in error."); return(token_ret); } CACKEY_DEBUG_PRINTF("Trying to login again"); return(cackey_login(slot, pin, pin_len, tries_remaining_p, retries - 1)); } } return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("PIN Verification succeeded"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * ... * * ARGUMENTS * ... * |
︙ | ︙ | |||
5661 5662 5663 5664 5665 5666 5667 | return(CKR_PIN_INCORRECT); } pPin = (CK_UTF8CHAR_PTR) pinbuf; ulPinLen = strlen(pinbuf); } | | | 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 | return(CKR_PIN_INCORRECT); } pPin = (CK_UTF8CHAR_PTR) pinbuf; ulPinLen = strlen(pinbuf); } login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining, 3); if (login_ret != CACKEY_PCSC_S_OK) { if (lock_mutex) { cackey_mutex_unlock(cackey_biglock); } if (login_ret == CACKEY_PCSC_E_LOCKED) { CACKEY_DEBUG_PRINTF("Error. Token is locked."); |
︙ | ︙ |