diff options
Diffstat (limited to 'libcacard/card_7816.c')
-rw-r--r-- | libcacard/card_7816.c | 757 |
1 files changed, 0 insertions, 757 deletions
diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c deleted file mode 100644 index 22fd334d15..0000000000 --- a/libcacard/card_7816.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Implement the 7816 portion of the card spec - * - * This code is licensed under the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - */ - -#include "glib-compat.h" - -#include <string.h> - -#include "vcard.h" -#include "vcard_emul.h" -#include "card_7816.h" - -/* - * set the status bytes based on the status word - */ -static void -vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status) -{ - unsigned char sw1, sw2; - response->b_status = status; /* make sure the status and swX representations - * are consistent */ - sw1 = (status >> 8) & 0xff; - sw2 = status & 0xff; - response->b_sw1 = sw1; - response->b_sw2 = sw2; - response->b_data[response->b_len] = sw1; - response->b_data[response->b_len+1] = sw2; -} - -/* - * set the status bytes in a response buffer - */ -static void -vcard_response_set_status_bytes(VCardResponse *response, - unsigned char sw1, unsigned char sw2) -{ - response->b_status = sw1 << 8 | sw2; - response->b_sw1 = sw1; - response->b_sw2 = sw2; - response->b_data[response->b_len] = sw1; - response->b_data[response->b_len+1] = sw2; -} - -/* - * allocate a VCardResponse structure, plus space for the data buffer, and - * set up everything but the resonse bytes. - */ -VCardResponse * -vcard_response_new_data(unsigned char *buf, int len) -{ - VCardResponse *new_response; - - new_response = g_new(VCardResponse, 1); - new_response->b_data = g_malloc(len + 2); - memcpy(new_response->b_data, buf, len); - new_response->b_total_len = len+2; - new_response->b_len = len; - new_response->b_type = VCARD_MALLOC; - return new_response; -} - -static VCardResponse * -vcard_init_buffer_response(VCard *card, unsigned char *buf, int len) -{ - VCardResponse *response; - VCardBufferResponse *buffer_response; - - buffer_response = vcard_get_buffer_response(card); - if (buffer_response) { - vcard_set_buffer_response(card, NULL); - vcard_buffer_response_delete(buffer_response); - } - buffer_response = vcard_buffer_response_new(buf, len); - if (buffer_response == NULL) { - return NULL; - } - response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES, - len > 255 ? 0 : len); - if (response == NULL) { - return NULL; - } - vcard_set_buffer_response(card, buffer_response); - return response; -} - -/* - * general buffer to hold results from APDU calls - */ -VCardResponse * -vcard_response_new(VCard *card, unsigned char *buf, - int len, int Le, vcard_7816_status_t status) -{ - VCardResponse *new_response; - - if (len > Le) { - return vcard_init_buffer_response(card, buf, len); - } - new_response = vcard_response_new_data(buf, len); - if (new_response == NULL) { - return NULL; - } - vcard_response_set_status(new_response, status); - return new_response; -} - -/* - * general buffer to hold results from APDU calls - */ -VCardResponse * -vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le, - unsigned char sw1, unsigned char sw2) -{ - VCardResponse *new_response; - - if (len > Le) { - return vcard_init_buffer_response(card, buf, len); - } - new_response = vcard_response_new_data(buf, len); - if (new_response == NULL) { - return NULL; - } - vcard_response_set_status_bytes(new_response, sw1, sw2); - return new_response; -} - -/* - * get a new Response buffer that only has a status. - */ -static VCardResponse * -vcard_response_new_status(vcard_7816_status_t status) -{ - VCardResponse *new_response; - - new_response = g_new(VCardResponse, 1); - new_response->b_data = &new_response->b_sw1; - new_response->b_len = 0; - new_response->b_total_len = 2; - new_response->b_type = VCARD_MALLOC_STRUCT; - vcard_response_set_status(new_response, status); - return new_response; -} - -/* - * same as above, but specify the status as separate bytes - */ -VCardResponse * -vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2) -{ - VCardResponse *new_response; - - new_response = g_new(VCardResponse, 1); - new_response->b_data = &new_response->b_sw1; - new_response->b_len = 0; - new_response->b_total_len = 2; - new_response->b_type = VCARD_MALLOC_STRUCT; - vcard_response_set_status_bytes(new_response, sw1, sw2); - return new_response; -} - - -/* - * free the response buffer. The Buffer has a type to handle the buffer - * allocated in other ways than through malloc. - */ -void -vcard_response_delete(VCardResponse *response) -{ - if (response == NULL) { - return; - } - switch (response->b_type) { - case VCARD_MALLOC: - /* everything was malloc'ed */ - g_free(response->b_data); - g_free(response); - break; - case VCARD_MALLOC_DATA: - /* only the data buffer was malloc'ed */ - g_free(response->b_data); - break; - case VCARD_MALLOC_STRUCT: - /* only the structure was malloc'ed */ - g_free(response); - break; - case VCARD_STATIC: - break; - } -} - -/* - * decode the class bit and set our generic type field, channel, and - * secure messaging values. - */ -static vcard_7816_status_t -vcard_apdu_set_class(VCardAPDU *apdu) { - apdu->a_channel = 0; - apdu->a_secure_messaging = 0; - apdu->a_type = apdu->a_cla & 0xf0; - apdu->a_gen_type = VCARD_7816_ISO; - - /* parse the class tables 8 & 9 of the 7816-4 Part 4 spec */ - switch (apdu->a_type) { - /* we only support the basic types */ - case 0x00: - case 0x80: - case 0x90: - case 0xa0: - apdu->a_channel = apdu->a_cla & 3; - apdu->a_secure_messaging = apdu->a_cla & 0xe; - break; - case 0xb0: - case 0xc0: - break; - - case 0x10: - case 0x20: - case 0x30: - case 0x40: - case 0x50: - case 0x60: - case 0x70: - /* Reserved for future use */ - apdu->a_gen_type = VCARD_7816_RFU; - break; - case 0xd0: - case 0xe0: - case 0xf0: - default: - apdu->a_gen_type = - (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY; - break; - } - return VCARD7816_STATUS_SUCCESS; -} - -/* - * set the Le and Lc fields according to table 5 of the - * 7816-4 part 4 spec - */ -static vcard_7816_status_t -vcard_apdu_set_length(VCardAPDU *apdu) -{ - int L, Le; - - /* process according to table 5 of the 7816-4 Part 4 spec. - * variable names match the variables in the spec */ - L = apdu->a_len-4; /* fixed APDU header */ - apdu->a_Lc = 0; - apdu->a_Le = 0; - apdu->a_body = NULL; - switch (L) { - case 0: - /* 1 minimal apdu */ - return VCARD7816_STATUS_SUCCESS; - case 1: - /* 2S only return values apdu */ - /* zero maps to 256 here */ - apdu->a_Le = apdu->a_header->ah_Le ? - apdu->a_header->ah_Le : 256; - return VCARD7816_STATUS_SUCCESS; - default: - /* if the ah_Le byte is zero and we have more than - * 1 byte in the header, then we must be using extended Le and Lc. - * process the extended now. */ - if (apdu->a_header->ah_Le == 0) { - if (L < 3) { - /* coding error, need at least 3 bytes */ - return VCARD7816_STATUS_ERROR_WRONG_LENGTH; - } - /* calculate the first extended value. Could be either Le or Lc */ - Le = (apdu->a_header->ah_body[0] << 8) - || apdu->a_header->ah_body[1]; - if (L == 3) { - /* 2E extended, return data only */ - /* zero maps to 65536 */ - apdu->a_Le = Le ? Le : 65536; - return VCARD7816_STATUS_SUCCESS; - } - if (Le == 0) { - /* reserved for future use, probably for next time we need - * to extend the lengths */ - return VCARD7816_STATUS_ERROR_WRONG_LENGTH; - } - /* we know that the first extended value is Lc now */ - apdu->a_Lc = Le; - apdu->a_body = &apdu->a_header->ah_body[2]; - if (L == Le+3) { - /* 3E extended, only body parameters */ - return VCARD7816_STATUS_SUCCESS; - } - if (L == Le+5) { - /* 4E extended, parameters and return data */ - Le = (apdu->a_data[apdu->a_len-2] << 8) - || apdu->a_data[apdu->a_len-1]; - apdu->a_Le = Le ? Le : 65536; - return VCARD7816_STATUS_SUCCESS; - } - return VCARD7816_STATUS_ERROR_WRONG_LENGTH; - } - /* not extended */ - apdu->a_Lc = apdu->a_header->ah_Le; - apdu->a_body = &apdu->a_header->ah_body[0]; - if (L == apdu->a_Lc + 1) { - /* 3S only body parameters */ - return VCARD7816_STATUS_SUCCESS; - } - if (L == apdu->a_Lc + 2) { - /* 4S parameters and return data */ - Le = apdu->a_data[apdu->a_len-1]; - apdu->a_Le = Le ? Le : 256; - return VCARD7816_STATUS_SUCCESS; - } - break; - } - return VCARD7816_STATUS_ERROR_WRONG_LENGTH; -} - -/* - * create a new APDU from a raw set of bytes. This will decode all the - * above fields. users of VCARDAPDU's can then depend on the already decoded - * values. - */ -VCardAPDU * -vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status) -{ - VCardAPDU *new_apdu; - - *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE; - if (len < 4) { - *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH; - return NULL; - } - - new_apdu = g_new(VCardAPDU, 1); - new_apdu->a_data = g_memdup(raw_apdu, len); - new_apdu->a_len = len; - *status = vcard_apdu_set_class(new_apdu); - if (*status != VCARD7816_STATUS_SUCCESS) { - g_free(new_apdu); - return NULL; - } - *status = vcard_apdu_set_length(new_apdu); - if (*status != VCARD7816_STATUS_SUCCESS) { - g_free(new_apdu); - new_apdu = NULL; - } - return new_apdu; -} - -void -vcard_apdu_delete(VCardAPDU *apdu) -{ - if (apdu == NULL) { - return; - } - g_free(apdu->a_data); - g_free(apdu); -} - - -/* - * declare response buffers for all the 7816 defined error codes - */ -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED) -VCARD_RESPONSE_NEW_STATIC_STATUS( - VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS) -VCARD_RESPONSE_NEW_STATIC_STATUS( - VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID) -VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL) - -/* - * return a single response code. This function cannot fail. It will always - * return a response. - */ -VCardResponse * -vcard_make_response(vcard_7816_status_t status) -{ - VCardResponse *response; - - switch (status) { - /* known 7816 response codes */ - case VCARD7816_STATUS_SUCCESS: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_SUCCESS); - case VCARD7816_STATUS_WARNING: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING); - case VCARD7816_STATUS_WARNING_RET_CORUPT: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_RET_CORUPT); - case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE); - case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED); - case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID); - case VCARD7816_STATUS_WARNING_CHANGE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_CHANGE); - case VCARD7816_STATUS_WARNING_FILE_FILLED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_WARNING_FILE_FILLED); - case VCARD7816_STATUS_EXC_ERROR: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_EXC_ERROR); - case VCARD7816_STATUS_EXC_ERROR_CHANGE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_EXC_ERROR_CHANGE); - case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); - case VCARD7816_STATUS_ERROR_WRONG_LENGTH: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_WRONG_LENGTH); - case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED); - case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED); - case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED); - case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE); - case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED); - case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED); - case VCARD7816_STATUS_ERROR_DATA_INVALID: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_DATA_INVALID); - case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); - case VCARD7816_STATUS_ERROR_DATA_NO_EF: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_DATA_NO_EF); - case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING); - case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT); - case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_WRONG_PARAMETERS); - case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA); - case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED); - case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); - case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND); - case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE); - case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT); - case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); - case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT); - case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); - case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2); - case VCARD7816_STATUS_ERROR_INS_CODE_INVALID: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_INS_CODE_INVALID); - case VCARD7816_STATUS_ERROR_CLA_INVALID: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_CLA_INVALID); - case VCARD7816_STATUS_ERROR_GENERAL: - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_ERROR_GENERAL); - default: - /* we don't know this status code, create a response buffer to - * hold it */ - response = vcard_response_new_status(status); - if (response == NULL) { - /* couldn't allocate the buffer, return memmory error */ - return VCARD_RESPONSE_GET_STATIC( - VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); - } - return response; - } -} - -/* - * Add File card support here if you need it. - */ -static VCardStatus -vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu, - VCardResponse **response) -{ - /* TODO: if we want to support a virtual file system card, we do it here. - * It would probably be a pkcs #15 card type */ - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - return VCARD_DONE; -} - -/* - * VM card (including java cards) - */ -static VCardStatus -vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu, - VCardResponse **response) -{ - int bytes_to_copy, next_byte_count, count; - VCardApplet *current_applet; - VCardBufferResponse *buffer_response; - vcard_7816_status_t status; - - /* parse the class first */ - if (apdu->a_gen_type != VCARD_7816_ISO) { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - return VCARD_DONE; - } - - /* use a switch so that if we need to support secure channel stuff later, - * we know where to put it */ - switch (apdu->a_secure_messaging) { - case 0x0: /* no SM */ - break; - case 0x4: /* proprietary SM */ - case 0x8: /* header not authenticated */ - case 0xc: /* header authenticated */ - default: - /* for now, don't try to support secure channel stuff in the - * virtual card. */ - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED); - return VCARD_DONE; - } - - /* now parse the instruction */ - switch (apdu->a_ins) { - case VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */ - case VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */ - case VCARD7816_INS_GET_CHALLENGE: /* secure channel op */ - case VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */ - case VCARD7816_INS_ERASE_BINARY: /* applet control op */ - case VCARD7816_INS_READ_BINARY: /* applet control op */ - case VCARD7816_INS_WRITE_BINARY: /* applet control op */ - case VCARD7816_INS_UPDATE_BINARY: /* applet control op */ - case VCARD7816_INS_READ_RECORD: /* file op */ - case VCARD7816_INS_WRITE_RECORD: /* file op */ - case VCARD7816_INS_UPDATE_RECORD: /* file op */ - case VCARD7816_INS_APPEND_RECORD: /* file op */ - case VCARD7816_INS_ENVELOPE: - case VCARD7816_INS_PUT_DATA: - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - break; - - case VCARD7816_INS_SELECT_FILE: - if (apdu->a_p1 != 0x04) { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED); - break; - } - - /* side effect, deselect the current applet if no applet has been found - * */ - current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc); - vcard_select_applet(card, apdu->a_channel, current_applet); - if (current_applet) { - unsigned char *aid; - int aid_len; - aid = vcard_applet_get_aid(current_applet, &aid_len); - *response = vcard_response_new(card, aid, aid_len, apdu->a_Le, - VCARD7816_STATUS_SUCCESS); - } else { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); - } - break; - - case VCARD7816_INS_VERIFY: - if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_WRONG_PARAMETERS); - } else { - if (apdu->a_Lc == 0) { - /* handle pin count if possible */ - count = vcard_emul_get_login_count(card); - if (count < 0) { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); - } else { - if (count > 0xf) { - count = 0xf; - } - *response = vcard_response_new_status_bytes( - VCARD7816_SW1_WARNING_CHANGE, - 0xc0 | count); - if (*response == NULL) { - *response = vcard_make_response( - VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); - } - } - } else { - status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc); - *response = vcard_make_response(status); - } - } - break; - - case VCARD7816_INS_GET_RESPONSE: - buffer_response = vcard_get_buffer_response(card); - if (!buffer_response) { - *response = vcard_make_response( - VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); - /* handle error */ - break; - } - bytes_to_copy = MIN(buffer_response->len, apdu->a_Le); - next_byte_count = MIN(256, buffer_response->len - bytes_to_copy); - *response = vcard_response_new_bytes( - card, buffer_response->current, bytes_to_copy, - apdu->a_Le, - next_byte_count ? - VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS, - next_byte_count); - buffer_response->current += bytes_to_copy; - buffer_response->len -= bytes_to_copy; - if (*response == NULL || (next_byte_count == 0)) { - vcard_set_buffer_response(card, NULL); - vcard_buffer_response_delete(buffer_response); - } - if (*response == NULL) { - *response = - vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); - } - break; - - case VCARD7816_INS_GET_DATA: - *response = - vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - break; - - default: - *response = - vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - break; - } - - /* response should have been set somewhere */ - assert(*response != NULL); - return VCARD_DONE; -} - - -/* - * APDU processing starts here. This routes the card processing stuff to the - * right location. - */ -VCardStatus -vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) -{ - VCardStatus status; - VCardBufferResponse *buffer_response; - - /* first handle any PTS commands, which aren't really APDU's */ - if (apdu->a_type == VCARD_7816_PTS) { - /* the PTS responses aren't really responses either */ - *response = vcard_response_new_data(apdu->a_data, apdu->a_len); - /* PTS responses have no status bytes */ - (*response)->b_total_len = (*response)->b_len; - return VCARD_DONE; - } - buffer_response = vcard_get_buffer_response(card); - if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) { - /* clear out buffer_response, return an error */ - vcard_set_buffer_response(card, NULL); - vcard_buffer_response_delete(buffer_response); - *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR); - return VCARD_DONE; - } - - status = vcard_process_applet_apdu(card, apdu, response); - if (status != VCARD_NEXT) { - return status; - } - switch (vcard_get_type(card)) { - case VCARD_FILE_SYSTEM: - return vcard7816_file_system_process_apdu(card, apdu, response); - case VCARD_VM: - return vcard7816_vm_process_apdu(card, apdu, response); - case VCARD_DIRECT: - /* if we are type direct, then the applet should handle everything */ - assert(!"VCARD_DIRECT: applet failure"); - break; - } - *response = - vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); - return VCARD_DONE; -} |