Overview
Comment: | Added support for updating the PIN |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b5ecb7c2d6bcf1626969f443a67d31f5 |
User & Date: | rkeene on 2015-07-15 20:05:35 |
Other Links: | 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:10 | Merged in trunk Leaf check-in: 38771da1e8 user: rkeene tags: require-login-if-needed | |
20:08 | Merged in trunk Closed-Leaf check-in: bab332232a user: rkeene tags: protected-auth-path | |
20:05 | Added support for updating the PIN check-in: b5ecb7c2d6 user: rkeene tags: trunk | |
18:47 | Updated KPS CA Certs check-in: efe7692225 user: rkeene tags: trunk | |
Changes
Modified cackey.c from [65139610e9] to [3a0d4abad4].
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #define GSCIS_INSTR_READ_BINARY 0xB0 #define GSCIS_INSTR_UPDATE_BINARY 0xD6 #define GSCIS_INSTR_SELECT 0xA4 #define GSCIS_INSTR_EXTERNAL_AUTH 0x82 #define GSCIS_INSTR_GET_CHALLENGE 0x84 #define GSCIS_INSTR_INTERNAL_AUTH 0x88 #define GSCIS_INSTR_VERIFY 0x20 #define GSCIS_INSTR_SIGN 0x2A #define GSCIS_INSTR_GET_PROP 0x56 #define GSCIS_INSTR_GET_ACR 0x4C #define GSCIS_INSTR_READ_BUFFER 0x52 #define GSCIS_INSTR_SIGNDECRYPT 0x42 #define GSCIS_PARAM_SELECT_APPLET 0x04 | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #define GSCIS_INSTR_READ_BINARY 0xB0 #define GSCIS_INSTR_UPDATE_BINARY 0xD6 #define GSCIS_INSTR_SELECT 0xA4 #define GSCIS_INSTR_EXTERNAL_AUTH 0x82 #define GSCIS_INSTR_GET_CHALLENGE 0x84 #define GSCIS_INSTR_INTERNAL_AUTH 0x88 #define GSCIS_INSTR_VERIFY 0x20 #define GSCIS_INSTR_CHANGE_REFERENCE 0x24 #define GSCIS_INSTR_SIGN 0x2A #define GSCIS_INSTR_GET_PROP 0x56 #define GSCIS_INSTR_GET_ACR 0x4C #define GSCIS_INSTR_READ_BUFFER 0x52 #define GSCIS_INSTR_SIGNDECRYPT 0x42 #define GSCIS_PARAM_SELECT_APPLET 0x04 |
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | xmit_buf[xmit_len++] = le; } } /* Begin Smartcard Transaction */ cackey_begin_transaction(slot); | | | 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | xmit_buf[xmit_len++] = le; } } /* Begin Smartcard Transaction */ cackey_begin_transaction(slot); if (class == GSCIS_CLASS_ISO7816 && (instruction == GSCIS_INSTR_VERIFY || instruction == GSCIS_INSTR_CHANGE_REFERENCE) && p1 == 0x00) { CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>"); } else { CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len); } recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len); |
︙ | ︙ | |||
3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 | * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) { 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; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | * * 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; uint16_t response_code; int tries_remaining; int send_ret; int key_reference = 0x00; /* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */ if (pin_len >= 8) { memcpy(cac_pin, pin, 8); } else { memcpy(cac_pin, pin, pin_len); } if (old_pin_len >= 8) { memcpy(old_cac_pin, old_pin, 8); } else { memcpy(old_cac_pin, old_pin, old_pin_len); } /* Concatenate both PINs together to send as a single instruction */ memcpy(pin_update, old_cac_pin, sizeof(old_cac_pin)); memcpy(pin_update + sizeof(old_cac_pin), cac_pin, sizeof(cac_pin)); /* Reject PINs which are too short */ if (pin_len < 5) { CACKEY_DEBUG_PRINTF("Rejecting New PIN which is too short (length = %lu, must be atleast 5)", pin_len); return(CACKEY_PCSC_E_BADPIN); } if (old_pin_len < 5) { CACKEY_DEBUG_PRINTF("Rejecting Old PIN which is too short (length = %lu, must be atleast 5)", old_pin_len); return(CACKEY_PCSC_E_BADPIN); } /* 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"); key_reference = 0x80; break; default: break; } cackey_free_certs(pcsc_identities, num_certs, 1); } /* Issue a Set PIN (CHANGE REFERENCE) */ send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_CHANGE_REFERENCE, 0x00, key_reference, sizeof(pin_update), pin_update, 0x00, &response_code, NULL, NULL); if (send_ret != CACKEY_PCSC_S_OK) { if ((response_code & 0x63C0) == 0x63C0) { tries_remaining = (response_code & 0xF); CACKEY_DEBUG_PRINTF("PIN Verification failed, %i tries remaining", tries_remaining); return(CACKEY_PCSC_E_BADPIN); } if (response_code == 0x6983) { CACKEY_DEBUG_PRINTF("Unable to set PIN, device is locked or changing the PIN is disabled"); return(CACKEY_PCSC_E_LOCKED); } return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("PIN Change succeeded"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) { 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; |
︙ | ︙ | |||
4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 | return(identities); } *ids_found = 0; return(NULL); } CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) { CK_C_INITIALIZE_ARGS CK_PTR args; uint32_t idx, highest_slot; int mutex_init_ret; int include_dod_certs; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 | return(identities); } *ids_found = 0; return(NULL); } static cackey_ret cackey_get_pin(char *pinbuf) { FILE *pinfd; char *fgets_ret; int pclose_ret; if (cackey_pin_command == NULL) { return(CACKEY_PCSC_E_GENERIC); } if (pinbuf == NULL) { return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("CACKEY_PIN_COMMAND = %s", cackey_pin_command); pinfd = popen(cackey_pin_command, "r"); if (pinfd == NULL) { CACKEY_DEBUG_PRINTF("Error. %s: Unable to run", cackey_pin_command); return(CACKEY_PCSC_E_BADPIN); } fgets_ret = fgets(pinbuf, 32, pinfd); if (fgets_ret == NULL) { pinbuf[0] = '\0'; } pclose_ret = pclose(pinfd); if (pclose_ret == -1 && errno == ECHILD) { CACKEY_DEBUG_PRINTF("Notice. pclose() indicated it could not get the status of the child, assuming it succeeeded !"); pclose_ret = 0; } if (pclose_ret != 0) { CACKEY_DEBUG_PRINTF("Error. %s: exited with non-zero status of %i", cackey_pin_command, pclose_ret); return(CACKEY_PCSC_E_BADPIN); } if (strlen(pinbuf) < 1) { CACKEY_DEBUG_PRINTF("Error. %s: returned no data", cackey_pin_command); return(CACKEY_PCSC_E_BADPIN); } if (pinbuf[strlen(pinbuf) - 1] == '\n') { pinbuf[strlen(pinbuf) - 1] = '\0'; } return(CACKEY_PCSC_S_OK); } CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) { CK_C_INITIALIZE_ARGS CK_PTR args; uint32_t idx, highest_slot; int mutex_init_ret; int include_dod_certs; |
︙ | ︙ | |||
4987 4988 4989 4990 4991 4992 4993 | } CACKEY_DEBUG_PRINTF("Returning CKR_TOKEN_WRITE_PROTECTED (%i)", CKR_TOKEN_WRITE_PROTECTED); return(CKR_TOKEN_WRITE_PROTECTED); } | < > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > | 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 | } CACKEY_DEBUG_PRINTF("Returning CKR_TOKEN_WRITE_PROTECTED (%i)", CKR_TOKEN_WRITE_PROTECTED); return(CKR_TOKEN_WRITE_PROTECTED); } CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) { char oldpinbuf[64], newpinbuf[64]; cackey_ret set_pin_ret, get_pin_ret; CK_SLOT_ID slotID; int mutex_retval; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { CACKEY_DEBUG_PRINTF("Error. Not initialized."); return(CKR_CRYPTOKI_NOT_INITIALIZED); } mutex_retval = cackey_mutex_lock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Locking failed."); return(CKR_GENERAL_ERROR); } if (!cackey_sessions[hSession].active) { cackey_mutex_unlock(cackey_biglock); CACKEY_DEBUG_PRINTF("Error. Session not active."); return(CKR_SESSION_HANDLE_INVALID); } slotID = cackey_sessions[hSession].slotID; if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); cackey_mutex_unlock(cackey_biglock); return(CKR_GENERAL_ERROR); } if (cackey_slots[slotID].active == 0) { CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); cackey_mutex_unlock(cackey_biglock); return(CKR_GENERAL_ERROR); } if (cackey_pin_command != NULL) { /* Get old PIN */ get_pin_ret = cackey_get_pin(oldpinbuf); if (get_pin_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Error while getting Old PIN, returning CKR_PIN_INCORRECT."); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_INCORRECT); } pOldPin = (CK_UTF8CHAR_PTR) oldpinbuf; ulOldPinLen = strlen(oldpinbuf); /* Get new PIN */ get_pin_ret = cackey_get_pin(newpinbuf); if (get_pin_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Error while getting New PIN, returning CKR_PIN_INVALID."); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_INVALID); } pNewPin = (CK_UTF8CHAR_PTR) newpinbuf; ulNewPinLen = strlen(newpinbuf); } if (pOldPin == NULL) { CACKEY_DEBUG_PRINTF("Old PIN value is wrong (null)."); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_INCORRECT); } if (ulOldPinLen == 0 || ulOldPinLen > 8) { CACKEY_DEBUG_PRINTF("Old PIN length is wrong: %lu.", (unsigned long) ulOldPinLen); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_INCORRECT); } if (pNewPin == NULL) { CACKEY_DEBUG_PRINTF("New PIN value is wrong (either NULL, or too long/short)."); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_INVALID); } if (ulNewPinLen < 5 || ulNewPinLen > 8) { CACKEY_DEBUG_PRINTF("New PIN length is wrong: %lu, must be atleast 5 and no more than 8.", (unsigned long) ulNewPinLen); cackey_mutex_unlock(cackey_biglock); return(CKR_PIN_LEN_RANGE); } set_pin_ret = cackey_set_pin(&cackey_slots[slotID], pOldPin, ulOldPinLen, pNewPin, ulNewPinLen); if (set_pin_ret != CACKEY_PCSC_S_OK) { if (cackey_pin_command == NULL) { cackey_slots[slotID].token_flags |= CKF_LOGIN_REQUIRED; } if (set_pin_ret == CACKEY_PCSC_E_LOCKED) { cackey_slots[slotID].token_flags |= CKF_USER_PIN_LOCKED; } } mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); return(CKR_GENERAL_ERROR); } switch (set_pin_ret) { case CACKEY_PCSC_S_OK: CACKEY_DEBUG_PRINTF("Successfully set PIN."); return(CKR_OK); case CACKEY_PCSC_E_BADPIN: CACKEY_DEBUG_PRINTF("PIN was invalid."); return(CKR_PIN_INVALID); case CACKEY_PCSC_E_LOCKED: CACKEY_DEBUG_PRINTF("Token is locked or this change is not permitted."); return(CKR_PIN_LOCKED); default: CACKEY_DEBUG_PRINTF("Something else went wrong changing the PIN: %i", set_pin_ret); return(CKR_GENERAL_ERROR); } return(CKR_GENERAL_ERROR); } CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession) { unsigned long idx; int mutex_retval; int found_session = 0; |
︙ | ︙ | |||
5287 5288 5289 5290 5291 5292 5293 | CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED); return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, _C_LoginMutexArg)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, int lock_mutex) { CK_SLOT_ID slotID; | | | < | 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 | CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED); return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, _C_LoginMutexArg)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, int lock_mutex) { CK_SLOT_ID slotID; cackey_ret get_pin_ret; char pinbuf[64]; int mutex_retval; int tries_remaining; int login_ret; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { CACKEY_DEBUG_PRINTF("Error. Not initialized."); return(CKR_CRYPTOKI_NOT_INITIALIZED); |
︙ | ︙ | |||
5355 5356 5357 5358 5359 5360 5361 | if (lock_mutex) { cackey_mutex_unlock(cackey_biglock); } return(CKR_GENERAL_ERROR); } | | < < < < < < | < < | | < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 | if (lock_mutex) { cackey_mutex_unlock(cackey_biglock); } return(CKR_GENERAL_ERROR); } if (cackey_pin_command != NULL) { if (pPin != NULL) { CACKEY_DEBUG_PRINTF("Protected authentication path in effect and PIN provided !?"); } get_pin_ret = cackey_get_pin(pinbuf); if (get_pin_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("cackey_get_pin() returned in failure, assuming the PIN was incorrect."); if (lock_mutex) { cackey_mutex_unlock(cackey_biglock); } return(CKR_PIN_INCORRECT); } pPin = (CK_UTF8CHAR_PTR) pinbuf; ulPinLen = strlen(pinbuf); } login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining); |
︙ | ︙ |