Differences From
Artifact [3a0d4abad4]:
3138 3138 *
3139 3139 * RETURN VALUE
3140 3140 * ...
3141 3141 *
3142 3142 * NOTES
3143 3143 * ...
3144 3144 *
3145 + */
3146 +static cackey_ret cackey_token_present(struct cackey_slot *slot) {
3147 + cackey_ret pcsc_connect_ret;
3148 + DWORD reader_len = 0, state = 0, protocol = 0, atr_len;
3149 + BYTE atr[MAX_ATR_SIZE];
3150 + LONG status_ret, scard_reconn_ret;
3151 +
3152 + CACKEY_DEBUG_PRINTF("Called.");
3153 +
3154 + if (slot->internal) {
3155 + CACKEY_DEBUG_PRINTF("Returning token present (internal token)");
3156 +
3157 + return(CACKEY_PCSC_S_TOKENPRESENT);
3158 + }
3159 +
3160 + pcsc_connect_ret = cackey_connect_card(slot);
3161 + if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
3162 + CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
3163 +
3164 + return(CACKEY_PCSC_E_TOKENABSENT);
3165 + }
3166 +
3167 + CACKEY_DEBUG_PRINTF("Calling SCardStatus() to determine card status");
3168 +
3169 + atr_len = sizeof(atr);
3170 + status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3171 +
3172 + if (status_ret == SCARD_E_INVALID_HANDLE) {
3173 + CACKEY_DEBUG_PRINTF("SCardStatus() returned SCARD_E_INVALID_HANDLE, marking is not already connected and trying again");
3174 + cackey_mark_slot_reset(slot);
3175 +
3176 + pcsc_connect_ret = cackey_connect_card(slot);
3177 + if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
3178 + CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
3179 +
3180 + return(CACKEY_PCSC_E_TOKENABSENT);
3181 + }
3182 +
3183 + CACKEY_DEBUG_PRINTF("Calling SCardStatus() again");
3184 +
3185 + atr_len = sizeof(atr);
3186 + status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3187 + }
3188 +
3189 + if (status_ret != SCARD_S_SUCCESS) {
3190 + cackey_mark_slot_reset(slot);
3191 +
3192 + if (status_ret == SCARD_W_RESET_CARD) {
3193 + CACKEY_DEBUG_PRINTF("Reset required, please hold...");
3194 +
3195 + scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);
3196 + if (scard_reconn_ret == SCARD_S_SUCCESS) {
3197 + /* Re-establish transaction, if it was present */
3198 + if (slot->transaction_depth > 0) {
3199 + slot->transaction_depth--;
3200 + slot->transaction_need_hw_lock = 1;
3201 + cackey_begin_transaction(slot);
3202 + }
3203 +
3204 + CACKEY_DEBUG_PRINTF("Reset successful, requerying");
3205 + status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3206 + if (status_ret != SCARD_S_SUCCESS) {
3207 + CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
3208 +
3209 + return(CACKEY_PCSC_E_TOKENABSENT);
3210 + }
3211 + } else {
3212 + CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent. SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret));
3213 +
3214 + return(CACKEY_PCSC_E_TOKENABSENT);
3215 + }
3216 + } else {
3217 + CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
3218 +
3219 + return(CACKEY_PCSC_E_TOKENABSENT);
3220 + }
3221 + }
3222 +
3223 + if ((state & SCARD_ABSENT) == SCARD_ABSENT) {
3224 + CACKEY_DEBUG_PRINTF("Card is absent, returning token absent");
3225 +
3226 + return(CACKEY_PCSC_E_TOKENABSENT);
3227 + }
3228 +
3229 + CACKEY_DEBUG_PRINTF("Returning token present.");
3230 +
3231 + return(CACKEY_PCSC_S_TOKENPRESENT);
3232 +}
3233 +
3234 +/*
3235 + * SYNPOSIS
3236 + * ...
3237 + *
3238 + * ARGUMENTS
3239 + * ...
3240 + *
3241 + * RETURN VALUE
3242 + * ...
3243 + *
3244 + * NOTES
3245 + * ...
3246 + *
3145 3247 */
3146 3248 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) {
3147 3249 struct cackey_pcsc_identity *pcsc_identities;
3148 3250 unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3149 3251 unsigned char old_cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3150 3252 unsigned char pin_update[sizeof(cac_pin) + sizeof(old_cac_pin)];
3151 3253 unsigned long num_certs;
................................................................................
3236 3338 * RETURN VALUE
3237 3339 * ...
3238 3340 *
3239 3341 * NOTES
3240 3342 * ...
3241 3343 *
3242 3344 */
3243 -static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
3345 +static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p, int retries) {
3244 3346 struct cackey_pcsc_identity *pcsc_identities;
3245 3347 unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3246 3348 unsigned long num_certs;
3247 3349 uint16_t response_code;
3248 3350 int tries_remaining;
3249 3351 int send_ret;
3250 - int key_reference = 0x00;
3352 + int key_reference = 0x00, have_piv = 0;
3353 + cackey_ret connect_ret, token_ret;
3251 3354
3252 3355 /* Indicate that we do not know about how many tries are remaining */
3253 3356 if (tries_remaining_p) {
3254 3357 *tries_remaining_p = -1;
3255 3358 }
3256 3359
3257 3360 /* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */
................................................................................
3271 3374 /* PIV authentication uses a "key_reference" of 0x80 */
3272 3375 pcsc_identities = cackey_read_certs(slot, NULL, &num_certs);
3273 3376 if (num_certs > 0 && pcsc_identities != NULL) {
3274 3377 switch (pcsc_identities[0].id_type) {
3275 3378 case CACKEY_ID_TYPE_PIV:
3276 3379 CACKEY_DEBUG_PRINTF("We have PIV card, so we will attempt to authenticate using the PIV Application key reference");
3277 3380
3278 - key_reference = 0x80;
3381 + have_piv = 1;
3279 3382 break;
3280 3383 default:
3281 3384 break;
3282 3385 }
3283 3386
3284 3387 cackey_free_certs(pcsc_identities, num_certs, 1);
3285 3388 }
3389 +
3390 + if (have_piv == 1) {
3391 + key_reference = 0x80;
3392 + }
3286 3393
3287 3394 /* Issue PIN Verify */
3288 3395 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);
3289 3396
3290 3397 if (send_ret != CACKEY_PCSC_S_OK) {
3291 3398 if ((response_code & 0x63C0) == 0x63C0) {
3292 3399 tries_remaining = (response_code & 0xF);
................................................................................
3301 3408 }
3302 3409
3303 3410 if (response_code == 0x6983) {
3304 3411 CACKEY_DEBUG_PRINTF("PIN Verification failed, device is locked");
3305 3412
3306 3413 return(CACKEY_PCSC_E_LOCKED);
3307 3414 }
3415 +
3416 + if (response_code == 0x6d00) {
3417 + if (have_piv == 1 && retries > 0) {
3418 + CACKEY_DEBUG_PRINTF("Got ISO 7816 Response \"6D 00\" in response to a VERIFY request.");
3419 + 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");
3420 + CACKEY_DEBUG_PRINTF("We are going to try to reset the card and select the applet again.");
3421 +
3422 + cackey_mark_slot_reset(slot);
3423 +
3424 + connect_ret = cackey_connect_card(slot);
3425 + if (connect_ret != CACKEY_PCSC_S_OK) {
3426 + CACKEY_DEBUG_PRINTF("Unable to reconnect after resetting the card, returning in error.");
3427 +
3428 + return(connect_ret);
3429 + }
3430 +
3431 + CACKEY_DEBUG_PRINTF("Verifying we still have a token.");
3432 + token_ret = cackey_token_present(slot);
3433 + if (token_ret != CACKEY_PCSC_S_TOKENPRESENT) {
3434 + CACKEY_DEBUG_PRINTF("Token not present, returning in error.");
3435 +
3436 + return(token_ret);
3437 + }
3438 +
3439 +
3440 + CACKEY_DEBUG_PRINTF("Trying to login again");
3441 + return(cackey_login(slot, pin, pin_len, tries_remaining_p, retries - 1));
3442 + }
3443 + }
3308 3444
3309 3445 return(CACKEY_PCSC_E_GENERIC);
3310 3446 }
3311 3447
3312 3448 CACKEY_DEBUG_PRINTF("PIN Verification succeeded");
3313 3449
3314 3450 return(CACKEY_PCSC_S_OK);
3315 3451 }
3316 3452
3317 -/*
3318 - * SYNPOSIS
3319 - * ...
3320 - *
3321 - * ARGUMENTS
3322 - * ...
3323 - *
3324 - * RETURN VALUE
3325 - * ...
3326 - *
3327 - * NOTES
3328 - * ...
3329 - *
3330 - */
3331 -static cackey_ret cackey_token_present(struct cackey_slot *slot) {
3332 - cackey_ret pcsc_connect_ret;
3333 - DWORD reader_len = 0, state = 0, protocol = 0, atr_len;
3334 - BYTE atr[MAX_ATR_SIZE];
3335 - LONG status_ret, scard_reconn_ret;
3336 -
3337 - CACKEY_DEBUG_PRINTF("Called.");
3338 -
3339 - if (slot->internal) {
3340 - CACKEY_DEBUG_PRINTF("Returning token present (internal token)");
3341 -
3342 - return(CACKEY_PCSC_S_TOKENPRESENT);
3343 - }
3344 -
3345 - pcsc_connect_ret = cackey_connect_card(slot);
3346 - if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
3347 - CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
3348 -
3349 - return(CACKEY_PCSC_E_TOKENABSENT);
3350 - }
3351 -
3352 - CACKEY_DEBUG_PRINTF("Calling SCardStatus() to determine card status");
3353 -
3354 - atr_len = sizeof(atr);
3355 - status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3356 -
3357 - if (status_ret == SCARD_E_INVALID_HANDLE) {
3358 - CACKEY_DEBUG_PRINTF("SCardStatus() returned SCARD_E_INVALID_HANDLE, marking is not already connected and trying again");
3359 - cackey_mark_slot_reset(slot);
3360 -
3361 - pcsc_connect_ret = cackey_connect_card(slot);
3362 - if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
3363 - CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
3364 -
3365 - return(CACKEY_PCSC_E_TOKENABSENT);
3366 - }
3367 -
3368 - CACKEY_DEBUG_PRINTF("Calling SCardStatus() again");
3369 -
3370 - atr_len = sizeof(atr);
3371 - status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3372 - }
3373 -
3374 - if (status_ret != SCARD_S_SUCCESS) {
3375 - cackey_mark_slot_reset(slot);
3376 -
3377 - if (status_ret == SCARD_W_RESET_CARD) {
3378 - CACKEY_DEBUG_PRINTF("Reset required, please hold...");
3379 -
3380 - scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);
3381 - if (scard_reconn_ret == SCARD_S_SUCCESS) {
3382 - /* Re-establish transaction, if it was present */
3383 - if (slot->transaction_depth > 0) {
3384 - slot->transaction_depth--;
3385 - slot->transaction_need_hw_lock = 1;
3386 - cackey_begin_transaction(slot);
3387 - }
3388 -
3389 - CACKEY_DEBUG_PRINTF("Reset successful, requerying");
3390 - status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
3391 - if (status_ret != SCARD_S_SUCCESS) {
3392 - CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
3393 -
3394 - return(CACKEY_PCSC_E_TOKENABSENT);
3395 - }
3396 - } else {
3397 - CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent. SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret));
3398 -
3399 - return(CACKEY_PCSC_E_TOKENABSENT);
3400 - }
3401 - } else {
3402 - CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
3403 -
3404 - return(CACKEY_PCSC_E_TOKENABSENT);
3405 - }
3406 - }
3407 -
3408 - if ((state & SCARD_ABSENT) == SCARD_ABSENT) {
3409 - CACKEY_DEBUG_PRINTF("Card is absent, returning token absent");
3410 -
3411 - return(CACKEY_PCSC_E_TOKENABSENT);
3412 - }
3413 -
3414 - CACKEY_DEBUG_PRINTF("Returning token present.");
3415 -
3416 - return(CACKEY_PCSC_S_TOKENPRESENT);
3417 -}
3418 -
3419 3453 /*
3420 3454 * SYNPOSIS
3421 3455 * ...
3422 3456 *
3423 3457 * ARGUMENTS
3424 3458 * ...
3425 3459 *
................................................................................
5661 5695 return(CKR_PIN_INCORRECT);
5662 5696 }
5663 5697
5664 5698 pPin = (CK_UTF8CHAR_PTR) pinbuf;
5665 5699 ulPinLen = strlen(pinbuf);
5666 5700 }
5667 5701
5668 - login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining);
5702 + login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining, 3);
5669 5703 if (login_ret != CACKEY_PCSC_S_OK) {
5670 5704 if (lock_mutex) {
5671 5705 cackey_mutex_unlock(cackey_biglock);
5672 5706 }
5673 5707
5674 5708 if (login_ret == CACKEY_PCSC_E_LOCKED) {
5675 5709 CACKEY_DEBUG_PRINTF("Error. Token is locked.");