Overview
Comment: | Added comments
Updated buffer name in PRINTBUF to avoid aliases |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
11bf77ef42ad6879b630f97454e893b4 |
User & Date: | rkeene on 2010-05-14 00:56:32 |
Other Links: | manifest | tags |
Context
2010-05-14
| ||
02:16 |
Added transaction support
Updated reading certs to be transactional Added function to connect to card check-in: fab9cf1772 user: rkeene tags: trunk | |
00:56 |
Added comments
Updated buffer name in PRINTBUF to avoid aliases check-in: 11bf77ef42 user: rkeene tags: trunk | |
2010-05-13
| ||
19:23 | Removed incorrect comment check-in: a52326f02b user: rkeene tags: trunk | |
Changes
Modified cackey.c from [95e7747218] to [b9a7131d32].
︙ | ︙ | |||
147 148 149 150 151 152 153 | #ifdef CACKEY_DEBUG # ifdef HAVE_STDIO_H # include <stdio.h> # endif # define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); } | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #ifdef CACKEY_DEBUG # ifdef HAVE_STDIO_H # include <stdio.h> # endif # define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); } # define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); fprintf(stderr, "%s(): %s (%s/%lu = {%02x", __func__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); } # define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s(): ", __func__); perror(x); } # define free(x) { CACKEY_DEBUG_PRINTF("FREE(%p) (%s)", x, #x); free(x); } static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func) { void *retval; retval = malloc(size); |
︙ | ︙ | |||
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 | CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval); return(retval); } /* PC/SC Related Functions */ static void cackey_slots_disconnect_all(void) { uint32_t idx; CACKEY_DEBUG_PRINTF("Called."); for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) { if (cackey_slots[idx].pcsc_card_connected) { CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx); SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD); } cackey_slots[idx].pcsc_card_connected = 0; } CACKEY_DEBUG_PRINTF("Returning"); return; } static cackey_ret cackey_pcsc_connect(void) { LONG scard_est_context_ret; #ifdef HAVE_SCARDISVALIDCONTEXT LONG scard_isvalid_ret; #endif CACKEY_DEBUG_PRINTF("Called."); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 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 637 638 639 640 641 642 643 644 645 | CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval); return(retval); } /* PC/SC Related Functions */ /* * SYNPOSIS * void cackey_slots_disconnect_all(void); * * ARGUMENTS * None * * RETURN VALUE * None * * NOTES * This function disconnects from all cards. * */ static void cackey_slots_disconnect_all(void) { uint32_t idx; CACKEY_DEBUG_PRINTF("Called."); for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) { if (cackey_slots[idx].pcsc_card_connected) { CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx); SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD); } cackey_slots[idx].pcsc_card_connected = 0; } CACKEY_DEBUG_PRINTF("Returning"); return; } /* * SYNPOSIS * cackey_ret cackey_pcsc_connect(void); * * ARGUMENTS * None * * RETURN VALUE * CACKEY_PCSC_S_OK On success * CACKEY_PCSC_E_GENERIC On error * * NOTES * This function connects to the PC/SC Connection Manager and updates the * global handle. * */ static cackey_ret cackey_pcsc_connect(void) { LONG scard_est_context_ret; #ifdef HAVE_SCARDISVALIDCONTEXT LONG scard_isvalid_ret; #endif CACKEY_DEBUG_PRINTF("Called."); |
︙ | ︙ | |||
661 662 663 664 665 666 667 | CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success"); return(CACKEY_PCSC_S_OK); } /* APDU Related Functions */ | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 691 692 693 694 695 696 697 698 699 700 701 702 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 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success"); return(CACKEY_PCSC_S_OK); } /* APDU Related Functions */ /* * SYNPOSIS * cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len); * * ARGUMENTS * cackey_slot *slot * Slot to send commands to * * unsigned char class * APDU Class (GSCIS_CLASS_ISO7816 or GSCIS_CLASS_GLOBAL_PLATFORM * usually), (CLA) * * unsigned char instruction * APDU Instruction (INS) * * unsigned char p1 * APDU Parameter 1 (P1) * * unsigned char p2 * APDU Parameter 2 (P2) * * unsigned char lc * APDU Length of Content (Lc) -- this is the length of "data" * parameter. If "data" is specified as NULL, this parameter will * be ignored. * * unsigned char *data * Pointer to buffer to send. It should be "Lc" bytes long. If * specified as NULL, "Lc" will not be sent, and this buffer will be * ignored. * * unsigned char le * APDU Length of Expectation (Le) -- this is the length of the * expected reply. If this is specified as 0 then it will not * be sent. * * uint16_t *respcode * [OUT] Pointer to storage of APDU response code. If this is * specified as NULL, the response code will be discarded. * * unsigned char *respdata * [OUT] Pointer to storage of APDU response data. If this is * specified as NULL, the response data will be discarded. If * the "respdata_len" parameter is specified as NULL, this buffer * will not be updated. * * size_t *respdata_len * [IN, OUT] Pointer initialing containing the size of the "respdata" * buffer. Before returning, the pointed to value is updated to the * number of bytes written to the buffer. If this is specified as * NULL, it will not be updated, and "respdata" will be ignored causing * the response data to be discarded. * * RETURN VALUE * CACKEY_PCSC_S_OK On success * CACKEY_PCSC_E_GENERIC On error * * NOTES * This function will connect to the PC/SC Connection Manager via * cackey_pcsc_connect() if needed. * * It will connect to the card in the reader attached to the slot * specified. It will reconnect to the card if the connection * goes away. * */ static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) { uint8_t major_rc, minor_rc; size_t bytes_to_copy, tmp_respdata_len; DWORD protocol; DWORD xmit_len, recv_len; LONG scard_conn_ret, scard_xmit_ret, scard_reconn_ret; BYTE xmit_buf[1024], recv_buf[1024]; |
︙ | ︙ | |||
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } static ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset) { size_t offset = 0, max_offset, max_count; unsigned char cmd[2]; uint16_t respcode; int send_ret; CACKEY_DEBUG_PRINTF("Called."); max_offset = count; max_count = 252; cmd[0] = t_or_v; while (1) { if (offset >= max_offset) { CACKEY_DEBUG_PRINTF("Buffer too small, returning what we got..."); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 | CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } /* * SYNPOSIS * ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset); * * ARGUMENTS * struct cackey_slot *slot * Slot to send commands to * * unsigned char *buffer * [OUT] Buffer * * size_t count * Number of bytes to attempt to read * * unsigned char t_or_v * Select the T-buffer (01) or V-buffer (02) to read from. * * size_t initial_offset * Specify the offset to begin the read from * * * RETURN VALUE * This function returns the number of bytes actually read, or -1 on error. * * NOTES * None * */ static ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset) { size_t offset = 0, max_offset, max_count; unsigned char cmd[2]; uint16_t respcode; int send_ret; CACKEY_DEBUG_PRINTF("Called."); max_offset = count; max_count = 252; if (t_or_v != 1 && t_or_v != 2) { CACKEY_DEBUG_PRINTF("Invalid T or V parameter specified, returning in failure"); return(-1); } cmd[0] = t_or_v; while (1) { if (offset >= max_offset) { CACKEY_DEBUG_PRINTF("Buffer too small, returning what we got..."); |
︙ | ︙ | |||
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 | } CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) offset); return(offset); } static cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) { int send_ret; CACKEY_DEBUG_PRINTF("Called."); CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len); send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, GSCIS_PARAM_SELECT_APPLET, 0x0C, aid_len, aid, 0x00, NULL, NULL, NULL); if (send_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Failed to open applet, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(CACKEY_PCSC_S_OK); } static cackey_ret 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 */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | } CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) offset); return(offset); } /* * SYNPOSIS * cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len); * * ARGUMENTS * struct cackey_slot *slot * Slot to send commands to * * unsigned char *aid * Buffer containing Applet ID to select * * size_t aid_len * Number of bytes in the "aid" (Applet ID) parameter * * RETURN VALUE * CACKEY_PCSC_S_OK On success * CACKEY_PCSC_E_GENERIC On error * * NOTES * None * */ static cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) { int send_ret; CACKEY_DEBUG_PRINTF("Called."); CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len); send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, GSCIS_PARAM_SELECT_APPLET, 0x0C, aid_len, aid, 0x00, NULL, NULL, NULL); if (send_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Failed to open applet, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * cackey_ret cackey_select_file(struct cackey_slot *slot, uint16_t ef); * * ARGUMENTS * struct cackey_slot *slot * Slot to send commands to * * uint16_t ef * Elemental File to select * * RETURN VALUE * CACKEY_PCSC_S_OK On success * CACKEY_PCSC_E_GENERIC On error * * NOTES * This selects an Elementary File (EF) under the currently selected * Dedicated File (DF) * * Typically this is called after selecting the correct Applet (using * cackey_select_applet) for VM cards * */ static cackey_ret 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 */ |
︙ | ︙ | |||
937 938 939 940 941 942 943 944 945 946 947 948 949 950 | } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(CACKEY_PCSC_S_OK); } static void cackey_free_tlv(struct cackey_tlv_entity *root) { struct cackey_tlv_entity *curr, *next; if (root == NULL) { return; } | > > > > > > > > > > > > > > > > | 1111 1112 1113 1114 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 1140 | } CACKEY_DEBUG_PRINTF("Successfully selected file"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * void cackey_free_tlv(struct cackey_tlv_entity *root); * * ARGUMENTS * struct cackey_tlv_entity *root * Root of the TLV list to start freeing * * RETURN VALUE * None * * NOTES * This function frees the TLV linked listed returned from * "cackey_read_tlv" * */ static void cackey_free_tlv(struct cackey_tlv_entity *root) { struct cackey_tlv_entity *curr, *next; if (root == NULL) { return; } |
︙ | ︙ | |||
967 968 969 970 971 972 973 974 975 976 977 978 979 980 | free(curr); } return; } static struct cackey_tlv_entity *cackey_read_tlv(struct cackey_slot *slot) { struct cackey_tlv_entity *curr_entity, *root = NULL, *last = NULL; unsigned char tlen_buf[2], tval_buf[1024], *tval; unsigned char vlen_buf[2], vval_buf[8192], *vval; unsigned char *tmpbuf; ssize_t tlen, vlen; ssize_t read_ret; | > > > > > > > > > > > > > > | 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 | free(curr); } return; } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static struct cackey_tlv_entity *cackey_read_tlv(struct cackey_slot *slot) { struct cackey_tlv_entity *curr_entity, *root = NULL, *last = NULL; unsigned char tlen_buf[2], tval_buf[1024], *tval; unsigned char vlen_buf[2], vval_buf[8192], *vval; unsigned char *tmpbuf; ssize_t tlen, vlen; ssize_t read_ret; |
︙ | ︙ | |||
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 | last = curr_entity; } } return(root); } static void cackey_free_certs(struct cackey_pcsc_identity *start, size_t count, int free_start) { size_t idx; for (idx = 0; idx < count; idx++) { if (start[idx].certificate) { free(start[idx].certificate); } } if (free_start) { free(start); } return; } static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) { struct cackey_pcsc_identity *curr_id; struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr; unsigned char ccc_aid[] = {GSCIS_AID_CCC}; unsigned char curr_aid[7]; unsigned long outidx = 0; int certs_resizable; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | last = curr_entity; } } return(root); } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static void cackey_free_certs(struct cackey_pcsc_identity *start, size_t count, int free_start) { size_t idx; for (idx = 0; idx < count; idx++) { if (start[idx].certificate) { free(start[idx].certificate); } } if (free_start) { free(start); } return; } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) { struct cackey_pcsc_identity *curr_id; struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr; unsigned char ccc_aid[] = {GSCIS_AID_CCC}; unsigned char curr_aid[7]; unsigned long outidx = 0; int certs_resizable; |
︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | if (certs_resizable) { certs = realloc(certs, sizeof(*certs) * (*count)); } return(certs); } static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) { unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint16_t response_code; int tries_remaining; int send_ret; /* Indicate that we do not know about how many tries are remaining */ | > > > > > > > > > > > > > > | 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | if (certs_resizable) { certs = realloc(certs, sizeof(*certs) * (*count)); } return(certs); } /* * 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) { unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint16_t response_code; int tries_remaining; int send_ret; /* Indicate that we do not know about how many tries are remaining */ |
︙ | ︙ | |||
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | } CACKEY_DEBUG_PRINTF("PIN Verification succeeded"); return(CACKEY_PCSC_S_OK); } static cackey_ret cackey_token_present(struct cackey_slot *slot) { unsigned char ccc_aid[] = {GSCIS_AID_CCC}; int send_ret; /* Select the CCC Applet */ send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid)); if (send_ret != CACKEY_PCSC_S_OK) { | > > > > > > > > > > > > > > | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 | } CACKEY_DEBUG_PRINTF("PIN Verification succeeded"); return(CACKEY_PCSC_S_OK); } /* * SYNPOSIS * ... * * ARGUMENTS * ... * * RETURN VALUE * ... * * NOTES * ... * */ static cackey_ret cackey_token_present(struct cackey_slot *slot) { unsigned char ccc_aid[] = {GSCIS_AID_CCC}; int send_ret; /* Select the CCC Applet */ send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid)); if (send_ret != CACKEY_PCSC_S_OK) { |
︙ | ︙ |