Differences From Artifact [c365c15fc9]:
- File
cackey.c
— part of check-in
[a3d727289c]
at
2010-05-12 14:52:58
on branch trunk
— Added test driver (from libssh-agent-pkcs11-provider)
Added basic ASN.1 X.509 BER decoder (from libssh-agent-pkcs11-provider)
Work towards updating CACKey to talk to CAC using PC/SC (user: rkeene, size: 109701) [annotate] [blame] [check-ins using]
To Artifact [d5b94d106d]:
- File
cackey.c
— part of check-in
[2d8b4030f7]
at
2010-05-12 17:25:06
on branch trunk
— Updated PC/SC error messages to include text return value as well as numeric value
Minor reorganization (user: rkeene, size: 113326) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | if (retval == NULL) { retval = "UNKNOWN"; } return(retval); } # define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__) # define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__) #else # define CACKEY_DEBUG_PRINTF(x...) /**/ # define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/ # define CACKEY_DEBUG_PERROR(x) /**/ # define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED" #endif struct cackey_identity { CK_ATTRIBUTE *attributes; CK_ULONG attributes_count; }; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | if (retval == NULL) { retval = "UNKNOWN"; } return(retval); } static const char *CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(LONG retcode) { const char *retval = NULL; switch (retcode) { case SCARD_S_SUCCESS: retval = "SCARD_S_SUCCESS"; break; case SCARD_E_CANCELLED: retval = "SCARD_E_CANCELLED"; break; case SCARD_E_CANT_DISPOSE: retval = "SCARD_E_CANT_DISPOSE"; break; case SCARD_E_INSUFFICIENT_BUFFER: retval = "SCARD_E_INSUFFICIENT_BUFFER"; break; case SCARD_E_INVALID_ATR: retval = "SCARD_E_INVALID_ATR"; break; case SCARD_E_INVALID_HANDLE: retval = "SCARD_E_INVALID_HANDLE"; break; case SCARD_E_INVALID_PARAMETER: retval = "SCARD_E_INVALID_PARAMETER"; break; case SCARD_E_INVALID_TARGET: retval = "SCARD_E_INVALID_TARGET"; break; case SCARD_E_INVALID_VALUE: retval = "SCARD_E_INVALID_VALUE"; break; case SCARD_E_NO_MEMORY: retval = "SCARD_E_NO_MEMORY"; break; case SCARD_E_UNKNOWN_READER: retval = "SCARD_E_UNKNOWN_READER"; break; case SCARD_E_TIMEOUT: retval = "SCARD_E_TIMEOUT"; break; case SCARD_E_SHARING_VIOLATION: retval = "SCARD_E_SHARING_VIOLATION"; break; case SCARD_E_NO_SMARTCARD: retval = "SCARD_E_NO_SMARTCARD"; break; case SCARD_E_UNKNOWN_CARD: retval = "SCARD_E_UNKNOWN_CARD"; break; case SCARD_E_PROTO_MISMATCH: retval = "SCARD_E_PROTO_MISMATCH"; break; case SCARD_E_NOT_READY: retval = "SCARD_E_NOT_READY"; break; case SCARD_E_SYSTEM_CANCELLED: retval = "SCARD_E_SYSTEM_CANCELLED"; break; case SCARD_E_NOT_TRANSACTED: retval = "SCARD_E_NOT_TRANSACTED"; break; case SCARD_E_READER_UNAVAILABLE: retval = "SCARD_E_READER_UNAVAILABLE"; break; case SCARD_W_UNSUPPORTED_CARD: retval = "SCARD_W_UNSUPPORTED_CARD"; break; case SCARD_W_UNRESPONSIVE_CARD: retval = "SCARD_W_UNRESPONSIVE_CARD"; break; case SCARD_W_UNPOWERED_CARD: retval = "SCARD_W_UNPOWERED_CARD"; break; case SCARD_W_RESET_CARD: retval = "SCARD_W_RESET_CARD"; break; case SCARD_W_REMOVED_CARD: retval = "SCARD_W_REMOVED_CARD"; break; case SCARD_E_PCI_TOO_SMALL: retval = "SCARD_E_PCI_TOO_SMALL"; break; case SCARD_E_READER_UNSUPPORTED: retval = "SCARD_E_READER_UNSUPPORTED"; break; case SCARD_E_DUPLICATE_READER: retval = "SCARD_E_DUPLICATE_READER"; break; case SCARD_E_CARD_UNSUPPORTED: retval = "SCARD_E_CARD_UNSUPPORTED"; break; case SCARD_E_NO_SERVICE: retval = "SCARD_E_NO_SERVICE"; break; case SCARD_E_SERVICE_STOPPED: retval = "SCARD_E_SERVICE_STOPPED"; break; case SCARD_W_INSERTED_CARD: retval = "SCARD_W_INSERTED_CARD"; break; case SCARD_E_UNSUPPORTED_FEATURE: retval = "SCARD_E_UNSUPPORTED_FEATURE"; break; } if (retval == NULL) { retval = "UNKNOWN"; } return(retval); } # define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__) # define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__) #else # define CACKEY_DEBUG_PRINTF(x...) /**/ # define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/ # define CACKEY_DEBUG_PERROR(x) /**/ # define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED" # define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED" #endif struct cackey_identity { CK_ATTRIBUTE *attributes; CK_ULONG attributes_count; }; |
︙ | ︙ | |||
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | int active; char *pcsc_reader; int pcsc_card_connected; SCARDHANDLE pcsc_card; }; struct cackey_tlv_entity { uint8_t tag; size_t length; unsigned char *value_buf; /* Raw buffer */ }; /* CACKEY Global Handles */ static void *cackey_biglock = NULL; static struct cackey_session cackey_sessions[128]; static struct cackey_slot cackey_slots[128]; static int cackey_initialized = 0; | > > > > | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | int active; char *pcsc_reader; int pcsc_card_connected; SCARDHANDLE pcsc_card; }; struct cackey_tlv_cardurl { }; struct cackey_tlv_entity { uint8_t tag; size_t length; unsigned char *value_buf; /* Raw buffer */ void *value; }; /* CACKEY Global Handles */ static void *cackey_biglock = NULL; static struct cackey_session cackey_sessions[128]; static struct cackey_slot cackey_slots[128]; static int cackey_initialized = 0; |
︙ | ︙ | |||
486 487 488 489 490 491 492 | return(-1); } CACKEY_DEBUG_PRINTF("SCardEstablishContext() called"); scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle); if (scard_est_context_ret != SCARD_S_SUCCESS) { | | | | | 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | return(-1); } CACKEY_DEBUG_PRINTF("SCardEstablishContext() called"); scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle); if (scard_est_context_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret); free(cackey_pcsc_handle); cackey_slots_disconnect_all(); return(-1); } } #ifdef HAVE_SCARDISVALIDCONTEXT CACKEY_DEBUG_PRINTF("SCardIsValidContext() called"); scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle); if (scard_isvalid_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %s/%li), trying to re-establish...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_isvalid_ret), (long) scard_isvalid_ret); CACKEY_DEBUG_PRINTF("SCardEstablishContext() called"); scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle); if (scard_est_context_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret); free(cackey_pcsc_handle); cackey_slots_disconnect_all(); return(-1); } |
︙ | ︙ | |||
556 557 558 559 560 561 562 | /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader); scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol); if (scard_conn_ret != SCARD_S_SUCCESS) { | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader); scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol); 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(-1); } slot->pcsc_card_connected = 1; } |
︙ | ︙ | |||
586 587 588 589 590 591 592 | } CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len); recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len); if (scard_xmit_ret != SCARD_S_SUCCESS) { | | | | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | } CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len); recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len); if (scard_xmit_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); if (scard_xmit_ret == SCARD_W_RESET_CARD) { CACKEY_DEBUG_PRINTF("Reset required, please hold..."); scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol); if (scard_reconn_ret == SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Reset successful, retransmitting"); scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T0, recv_buf, &recv_len); if (scard_xmit_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Retransmit failed, returning in failure after disconnecting the card (SCardTransmit = %s/%li)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (long) scard_xmit_ret); SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD); slot->pcsc_card_connected = 0; return(-1); } } else { |
︙ | ︙ | |||
775 776 777 778 779 780 781 782 783 784 785 786 787 788 | return(-1); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(0); } static int cackey_read_tlv(struct cackey_slot *slot, int follow_url) { struct cackey_tlv_entity curr_entity; unsigned char tlen_buf[2], tval_buf[1024], *tval; unsigned char vlen_buf[2], vval_buf[8192], *vval; ssize_t tlen, vlen; ssize_t read_ret; | > > > > > > > > > > > > > > > > > > > > > > | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 | return(-1); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(0); } static int cackey_select_file(struct cackey_slot *slot, uint16_t ef) { unsigned char fid_buf[2]; int send_ret; CACKEY_DEBUG_PRINTF("Called"); /* Open the elementary file */ fid_buf[0] = (ef >> 8) & 0xff; fid_buf[1] = ef & 0xff; send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, 0x02, 0x0C, sizeof(fid_buf), fid_buf, 0x00, NULL, NULL, NULL); if (send_ret < 0) { CACKEY_DEBUG_PRINTF("Failed to open file, returning in failure"); return(-1); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(0); } static int cackey_read_tlv(struct cackey_slot *slot, int follow_url) { struct cackey_tlv_entity curr_entity; unsigned char tlen_buf[2], tval_buf[1024], *tval; unsigned char vlen_buf[2], vval_buf[8192], *vval; ssize_t tlen, vlen; ssize_t read_ret; |
︙ | ︙ | |||
880 881 882 883 884 885 886 | cackey_read_tlv(slot, 0); } break; } } | < < < < < < < < < < < < < < < < < < < < < < | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | cackey_read_tlv(slot, 0); } break; } } return(0); } /* Returns 1 if a token is in the specified slot, 0 otherwise */ static int cackey_token_present(struct cackey_slot *slot) { unsigned char ccc_aid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00}; int send_ret; |
︙ | ︙ | |||
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | pcsc_readers += curr_reader_len + 1; } if (currslot > 0) { slot_count = currslot; } } free(pcsc_readers_s); } } mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); | > > > > | 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 | pcsc_readers += curr_reader_len + 1; } if (currslot > 0) { slot_count = currslot; } } else { CACKEY_DEBUG_PRINTF("Second call to SCardListReaders failed, return %s/%li", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_listreaders_ret), (long) scard_listreaders_ret); } free(pcsc_readers_s); } else { CACKEY_DEBUG_PRINTF("First call to SCardListReaders failed, return %s/%li", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_listreaders_ret), (long) scard_listreaders_ret); } } mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); |
︙ | ︙ |