Overview
Comment: | Better handling of loss of connection to the PCSC daemon or card resetting |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9f8b1347d98f3b40475e1dbb4780b18e |
User & Date: | rkeene on 2016-02-16 16:06:27 |
Other Links: | manifest | tags |
Context
2016-02-16
| ||
16:06 | Fixed an issue where the mutex released slightly too early check-in: 54d3a148ef user: rkeene tags: trunk | |
16:06 | Better handling of loss of connection to the PCSC daemon or card resetting check-in: 9f8b1347d9 user: rkeene tags: trunk | |
15:25 | Updated AppFS build script to set the PIN entry program check-in: 3fe401d585 user: rkeene tags: trunk | |
Changes
Modified cackey.c from [6bf4e65a64] to [ef984b4aeb].
︙ | |||
723 724 725 726 727 728 729 730 731 732 733 734 735 736 | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | + + | * functions and not include any symbols in the output shared object. */ #include "asn1-x509.c" #include "sha1.c" #include "md5.c" typedef enum { CACKEY_ID_TYPE_ERROR, CACKEY_ID_TYPE_UNKNOWN, CACKEY_ID_TYPE_CAC, CACKEY_ID_TYPE_PIV, CACKEY_ID_TYPE_CERT_ONLY } cackey_pcsc_id_type; struct cackey_pcsc_identity { cackey_pcsc_id_type id_type; |
︙ | |||
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | + + + - - | * * NOTES * This function marks a slot has having been reset, to later be cleaned up. * Cleanup only happens when a PKCS#11 client calls C_FindObjectsInit. * */ static void cackey_mark_slot_reset(struct cackey_slot *slot) { struct cackey_pcsc_identity *pcsc_identities; unsigned long num_certs; if (slot == NULL) { return; } CACKEY_DEBUG_PRINTF("Called."); if (slot->pcsc_card_connected) { SCardDisconnect(slot->pcsc_card, SCARD_LEAVE_CARD); } slot->slot_reset = 1; slot->pcsc_card_connected = 0; if (cackey_pin_command == NULL) { slot->token_flags = CKF_LOGIN_REQUIRED; } else { slot->token_flags = 0; } |
︙ | |||
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 | 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | + + + + + + + + + + + + | CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1") scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol); } } scard_conn_ret = cackey_reconnect_card(slot, protocol); } if (scard_conn_ret == SCARD_E_NO_SERVICE) { CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_NO_SERVICE -- which could mean our handle is invalid, will try to reconnect to PC/SC service"); cackey_pcsc_disconnect(); cackey_pcsc_connect(); cackey_mark_slot_reset(slot); return(cackey_connect_card(slot)); } if (scard_conn_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Connection to card failed, returning in failure (SCardConnect() = %s/%li)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_conn_ret), (long) scard_conn_ret); return(CACKEY_PCSC_E_GENERIC); } |
︙ | |||
1553 1554 1555 1556 1557 1558 1559 | 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 | - + + + + + + + + + | recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len); if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) { CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will ask calling function to retry (not resetting card)...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); |
︙ | |||
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 | 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * cackey_pcsc_id_type cackey_detect_and_select_root_applet(struct cackey_slot *slot, cackey_pcsc_id_type type_hint); * * ARGUMENTS * struct cackey_slot *slot * Slot to send commands to * * cackey_pcsc_id_type type_hint * A hint as to which type of card might be in this slot (CAC or PIV) * * RETURN VALUE * CACKEY_ID_TYPE_PIV If the card connected is a PIV * CACKEY_ID_TYPE_CAC If the card connected is a CAC with the CCC * applet * CACKEY_ID_TYPE_ERROR If we are unable to determine what type of card * is connected * * NOTES * This function reselects the "root" applet, after this function is called * the user may be required to login again * */ static cackey_pcsc_id_type cackey_detect_and_select_root_applet(struct cackey_slot *slot, cackey_pcsc_id_type type_hint) { unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID}; cackey_pcsc_id_type try_types[2], try_type; int send_ret; int idx; CACKEY_DEBUG_PRINTF("Reselecting the root applet"); if (type_hint == CACKEY_ID_TYPE_UNKNOWN) { if (slot->cached_certs && slot->cached_certs_count > 0) { type_hint = slot->cached_certs[0].id_type; } } switch (type_hint) { case CACKEY_ID_TYPE_PIV: CACKEY_DEBUG_PRINTF("Trying to reselect the PIV root applet first"); try_types[0] = CACKEY_ID_TYPE_PIV; try_types[1] = CACKEY_ID_TYPE_CAC; break; default: CACKEY_DEBUG_PRINTF("Trying to reselect the CAC CCC applet first"); try_types[0] = CACKEY_ID_TYPE_CAC; try_types[1] = CACKEY_ID_TYPE_PIV; break; } for (idx = 0; idx < (sizeof(try_types) / sizeof(try_types[0])); idx++) { try_type = try_types[idx]; switch (try_type) { case CACKEY_ID_TYPE_CAC: CACKEY_DEBUG_PRINTF("Trying to select the CAC CCC applet"); send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid)); break; case CACKEY_ID_TYPE_PIV: CACKEY_DEBUG_PRINTF("Trying to select the PIV root applet"); send_ret = cackey_select_applet(slot, piv_aid, sizeof(piv_aid)); break; } if (send_ret == CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Successfully selected the %s applet -- setting the \"LOGIN REQUIRED\" flag on the token", try_type == CACKEY_ID_TYPE_CAC ? "CAC" : "PIV" ); slot->token_flags = CKF_LOGIN_REQUIRED; return(try_type); } } CACKEY_DEBUG_PRINTF("Unable to select any applet, returning in failure"); return(CACKEY_ID_TYPE_ERROR); } /* * SYNPOSIS * cackey_ret cackey_select_file(struct cackey_slot *slot, uint16_t ef); * * ARGUMENTS * struct cackey_slot *slot |
︙ | |||
2446 2447 2448 2449 2450 2451 2452 2453 2454 | 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 | + - + + | * ... * * NOTES * ... * */ static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) { cackey_pcsc_id_type check_id_type; struct cackey_pcsc_identity *curr_id; struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr; |
︙ | |||
2482 2483 2484 2485 2486 2487 2488 2489 2490 | 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 | + + + + + + + + + + - - - - - - - - + + + + + + + + - + - - + + + - - - + + + + - - - + - + + - - + + - + + + + + + | if (*count == 0) { CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit"); return(certs); } } cached_certs_valid = 0; if (!slot->slot_reset) { if (slot->cached_certs) { cached_certs_valid = 1; if (slot->cached_certs_count > 0) { cached_certs_valid = 1; } } } if (cached_certs_valid) { |
︙ | |||
2788 2789 2790 2791 2792 2793 2794 | 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 | - + | * ... * * NOTES * ... * */ static ssize_t cackey_signdecrypt(struct cackey_slot *slot, struct cackey_identity *identity, unsigned char *buf, size_t buflen, unsigned char *outbuf, size_t outbuflen, int padInput, int unpadOutput) { |
︙ | |||
3000 3001 3002 3003 3004 3005 3006 | 3129 3130 3131 3132 3133 3134 3135 3136 3137 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 | - - + + + + + + + - + | CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- retrying."); return(cackey_signdecrypt(slot, identity, buf, buflen, outbuf, outbuflen, padInput, unpadOutput)); } CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error."); |
︙ | |||
3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 | 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 | + + + + - | } if (response_code == 0x6d00) { if (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 or GSC-IS v2.1"); CACKEY_DEBUG_PRINTF("We are going to try to reset the card and select the applet again."); if (num_certs > 0 && pcsc_identities != NULL) { cackey_detect_and_select_root_applet(slot, pcsc_identities[0].id_type); } 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); } |
︙ |