|
|
1.1 ! root 1: /* ! 2: * Implement the 7816 portion of the card spec ! 3: * ! 4: * This code is licensed under the GNU LGPL, version 2.1 or later. ! 5: * See the COPYING.LIB file in the top-level directory. ! 6: */ ! 7: ! 8: #include "qemu-common.h" ! 9: ! 10: #include "vcard.h" ! 11: #include "vcard_emul.h" ! 12: #include "card_7816.h" ! 13: ! 14: /* ! 15: * set the status bytes based on the status word ! 16: */ ! 17: static void ! 18: vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status) ! 19: { ! 20: unsigned char sw1, sw2; ! 21: response->b_status = status; /* make sure the status and swX representations ! 22: * are consistent */ ! 23: sw1 = (status >> 8) & 0xff; ! 24: sw2 = status & 0xff; ! 25: response->b_sw1 = sw1; ! 26: response->b_sw2 = sw2; ! 27: response->b_data[response->b_len] = sw1; ! 28: response->b_data[response->b_len+1] = sw2; ! 29: } ! 30: ! 31: /* ! 32: * set the status bytes in a response buffer ! 33: */ ! 34: static void ! 35: vcard_response_set_status_bytes(VCardResponse *response, ! 36: unsigned char sw1, unsigned char sw2) ! 37: { ! 38: response->b_status = sw1 << 8 | sw2; ! 39: response->b_sw1 = sw1; ! 40: response->b_sw2 = sw2; ! 41: response->b_data[response->b_len] = sw1; ! 42: response->b_data[response->b_len+1] = sw2; ! 43: } ! 44: ! 45: /* ! 46: * allocate a VCardResponse structure, plus space for the data buffer, and ! 47: * set up everything but the resonse bytes. ! 48: */ ! 49: VCardResponse * ! 50: vcard_response_new_data(unsigned char *buf, int len) ! 51: { ! 52: VCardResponse *new_response; ! 53: ! 54: new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse)); ! 55: new_response->b_data = qemu_malloc(len + 2); ! 56: memcpy(new_response->b_data, buf, len); ! 57: new_response->b_total_len = len+2; ! 58: new_response->b_len = len; ! 59: new_response->b_type = VCARD_MALLOC; ! 60: return new_response; ! 61: } ! 62: ! 63: static VCardResponse * ! 64: vcard_init_buffer_response(VCard *card, unsigned char *buf, int len) ! 65: { ! 66: VCardResponse *response; ! 67: VCardBufferResponse *buffer_response; ! 68: ! 69: buffer_response = vcard_get_buffer_response(card); ! 70: if (buffer_response) { ! 71: vcard_set_buffer_response(card, NULL); ! 72: vcard_buffer_response_delete(buffer_response); ! 73: } ! 74: buffer_response = vcard_buffer_response_new(buf, len); ! 75: if (buffer_response == NULL) { ! 76: return NULL; ! 77: } ! 78: response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES, ! 79: len > 255 ? 0 : len); ! 80: if (response == NULL) { ! 81: return NULL; ! 82: } ! 83: vcard_set_buffer_response(card, buffer_response); ! 84: return response; ! 85: } ! 86: ! 87: /* ! 88: * general buffer to hold results from APDU calls ! 89: */ ! 90: VCardResponse * ! 91: vcard_response_new(VCard *card, unsigned char *buf, ! 92: int len, int Le, vcard_7816_status_t status) ! 93: { ! 94: VCardResponse *new_response; ! 95: ! 96: if (len > Le) { ! 97: return vcard_init_buffer_response(card, buf, len); ! 98: } ! 99: new_response = vcard_response_new_data(buf, len); ! 100: if (new_response == NULL) { ! 101: return NULL; ! 102: } ! 103: vcard_response_set_status(new_response, status); ! 104: return new_response; ! 105: } ! 106: ! 107: /* ! 108: * general buffer to hold results from APDU calls ! 109: */ ! 110: VCardResponse * ! 111: vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le, ! 112: unsigned char sw1, unsigned char sw2) ! 113: { ! 114: VCardResponse *new_response; ! 115: ! 116: if (len > Le) { ! 117: return vcard_init_buffer_response(card, buf, len); ! 118: } ! 119: new_response = vcard_response_new_data(buf, len); ! 120: if (new_response == NULL) { ! 121: return NULL; ! 122: } ! 123: vcard_response_set_status_bytes(new_response, sw1, sw2); ! 124: return new_response; ! 125: } ! 126: ! 127: /* ! 128: * get a new Reponse buffer that only has a status. ! 129: */ ! 130: static VCardResponse * ! 131: vcard_response_new_status(vcard_7816_status_t status) ! 132: { ! 133: VCardResponse *new_response; ! 134: ! 135: new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse)); ! 136: new_response->b_data = &new_response->b_sw1; ! 137: new_response->b_len = 0; ! 138: new_response->b_total_len = 2; ! 139: new_response->b_type = VCARD_MALLOC_STRUCT; ! 140: vcard_response_set_status(new_response, status); ! 141: return new_response; ! 142: } ! 143: ! 144: /* ! 145: * same as above, but specify the status as separate bytes ! 146: */ ! 147: VCardResponse * ! 148: vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2) ! 149: { ! 150: VCardResponse *new_response; ! 151: ! 152: new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse)); ! 153: new_response->b_data = &new_response->b_sw1; ! 154: new_response->b_len = 0; ! 155: new_response->b_total_len = 2; ! 156: new_response->b_type = VCARD_MALLOC_STRUCT; ! 157: vcard_response_set_status_bytes(new_response, sw1, sw2); ! 158: return new_response; ! 159: } ! 160: ! 161: ! 162: /* ! 163: * free the response buffer. The Buffer has a type to handle the buffer ! 164: * allocated in other ways than through malloc. ! 165: */ ! 166: void ! 167: vcard_response_delete(VCardResponse *response) ! 168: { ! 169: if (response == NULL) { ! 170: return; ! 171: } ! 172: switch (response->b_type) { ! 173: case VCARD_MALLOC: ! 174: /* everything was malloc'ed */ ! 175: if (response->b_data) { ! 176: qemu_free(response->b_data); ! 177: } ! 178: qemu_free(response); ! 179: break; ! 180: case VCARD_MALLOC_DATA: ! 181: /* only the data buffer was malloc'ed */ ! 182: if (response->b_data) { ! 183: qemu_free(response->b_data); ! 184: } ! 185: break; ! 186: case VCARD_MALLOC_STRUCT: ! 187: /* only the structure was malloc'ed */ ! 188: qemu_free(response); ! 189: break; ! 190: case VCARD_STATIC: ! 191: break; ! 192: } ! 193: } ! 194: ! 195: /* ! 196: * decode the class bit and set our generic type field, channel, and ! 197: * secure messaging values. ! 198: */ ! 199: static vcard_7816_status_t ! 200: vcard_apdu_set_class(VCardAPDU *apdu) { ! 201: apdu->a_channel = 0; ! 202: apdu->a_secure_messaging = 0; ! 203: apdu->a_type = apdu->a_cla & 0xf0; ! 204: apdu->a_gen_type = VCARD_7816_ISO; ! 205: ! 206: /* parse the class tables 8 & 9 of the 7816-4 Part 4 spec */ ! 207: switch (apdu->a_type) { ! 208: /* we only support the basic types */ ! 209: case 0x00: ! 210: case 0x80: ! 211: case 0x90: ! 212: case 0xa0: ! 213: apdu->a_channel = apdu->a_cla & 3; ! 214: apdu->a_secure_messaging = apdu->a_cla & 0xe; ! 215: break; ! 216: case 0xb0: ! 217: case 0xc0: ! 218: break; ! 219: ! 220: case 0x10: ! 221: case 0x20: ! 222: case 0x30: ! 223: case 0x40: ! 224: case 0x50: ! 225: case 0x60: ! 226: case 0x70: ! 227: /* Reserved for future use */ ! 228: apdu->a_gen_type = VCARD_7816_RFU; ! 229: break; ! 230: case 0xd0: ! 231: case 0xe0: ! 232: case 0xf0: ! 233: default: ! 234: apdu->a_gen_type = ! 235: (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPIETARY; ! 236: break; ! 237: } ! 238: return VCARD7816_STATUS_SUCCESS; ! 239: } ! 240: ! 241: /* ! 242: * set the Le and Lc fiels according to table 5 of the ! 243: * 7816-4 part 4 spec ! 244: */ ! 245: static vcard_7816_status_t ! 246: vcard_apdu_set_length(VCardAPDU *apdu) ! 247: { ! 248: int L, Le; ! 249: ! 250: /* process according to table 5 of the 7816-4 Part 4 spec. ! 251: * variable names match the variables in the spec */ ! 252: L = apdu->a_len-4; /* fixed APDU header */ ! 253: apdu->a_Lc = 0; ! 254: apdu->a_Le = 0; ! 255: apdu->a_body = NULL; ! 256: switch (L) { ! 257: case 0: ! 258: /* 1 minimal apdu */ ! 259: return VCARD7816_STATUS_SUCCESS; ! 260: case 1: ! 261: /* 2S only return values apdu */ ! 262: /* zero maps to 256 here */ ! 263: apdu->a_Le = apdu->a_header->ah_Le ? ! 264: apdu->a_header->ah_Le : 256; ! 265: return VCARD7816_STATUS_SUCCESS; ! 266: default: ! 267: /* if the ah_Le byte is zero and we have more than ! 268: * 1 byte in the header, then we must be using extended Le and Lc. ! 269: * process the extended now. */ ! 270: if (apdu->a_header->ah_Le == 0) { ! 271: if (L < 3) { ! 272: /* coding error, need at least 3 bytes */ ! 273: return VCARD7816_STATUS_ERROR_WRONG_LENGTH; ! 274: } ! 275: /* calculate the first extended value. Could be either Le or Lc */ ! 276: Le = (apdu->a_header->ah_body[0] << 8) ! 277: || apdu->a_header->ah_body[1]; ! 278: if (L == 3) { ! 279: /* 2E extended, return data only */ ! 280: /* zero maps to 65536 */ ! 281: apdu->a_Le = Le ? Le : 65536; ! 282: return VCARD7816_STATUS_SUCCESS; ! 283: } ! 284: if (Le == 0) { ! 285: /* reserved for future use, probably for next time we need ! 286: * to extend the lengths */ ! 287: return VCARD7816_STATUS_ERROR_WRONG_LENGTH; ! 288: } ! 289: /* we know that the first extended value is Lc now */ ! 290: apdu->a_Lc = Le; ! 291: apdu->a_body = &apdu->a_header->ah_body[2]; ! 292: if (L == Le+3) { ! 293: /* 3E extended, only body parameters */ ! 294: return VCARD7816_STATUS_SUCCESS; ! 295: } ! 296: if (L == Le+5) { ! 297: /* 4E extended, parameters and return data */ ! 298: Le = (apdu->a_data[apdu->a_len-2] << 8) ! 299: || apdu->a_data[apdu->a_len-1]; ! 300: apdu->a_Le = Le ? Le : 65536; ! 301: return VCARD7816_STATUS_SUCCESS; ! 302: } ! 303: return VCARD7816_STATUS_ERROR_WRONG_LENGTH; ! 304: } ! 305: /* not extended */ ! 306: apdu->a_Lc = apdu->a_header->ah_Le; ! 307: apdu->a_body = &apdu->a_header->ah_body[0]; ! 308: if (L == apdu->a_Lc + 1) { ! 309: /* 3S only body parameters */ ! 310: return VCARD7816_STATUS_SUCCESS; ! 311: } ! 312: if (L == apdu->a_Lc + 2) { ! 313: /* 4S parameters and return data */ ! 314: Le = apdu->a_data[apdu->a_len-1]; ! 315: apdu->a_Le = Le ? Le : 256; ! 316: return VCARD7816_STATUS_SUCCESS; ! 317: } ! 318: break; ! 319: } ! 320: return VCARD7816_STATUS_ERROR_WRONG_LENGTH; ! 321: } ! 322: ! 323: /* ! 324: * create a new APDU from a raw set of bytes. This will decode all the ! 325: * above fields. users of VCARDAPDU's can then depend on the already decoded ! 326: * values. ! 327: */ ! 328: VCardAPDU * ! 329: vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status) ! 330: { ! 331: VCardAPDU *new_apdu; ! 332: ! 333: *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE; ! 334: if (len < 4) { ! 335: *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH; ! 336: return NULL; ! 337: } ! 338: ! 339: new_apdu = (VCardAPDU *)qemu_malloc(sizeof(VCardAPDU)); ! 340: new_apdu->a_data = qemu_malloc(len); ! 341: memcpy(new_apdu->a_data, raw_apdu, len); ! 342: new_apdu->a_len = len; ! 343: *status = vcard_apdu_set_class(new_apdu); ! 344: if (*status != VCARD7816_STATUS_SUCCESS) { ! 345: qemu_free(new_apdu); ! 346: return NULL; ! 347: } ! 348: *status = vcard_apdu_set_length(new_apdu); ! 349: if (*status != VCARD7816_STATUS_SUCCESS) { ! 350: qemu_free(new_apdu); ! 351: new_apdu = NULL; ! 352: } ! 353: return new_apdu; ! 354: } ! 355: ! 356: void ! 357: vcard_apdu_delete(VCardAPDU *apdu) ! 358: { ! 359: if (apdu == NULL) { ! 360: return; ! 361: } ! 362: if (apdu->a_data) { ! 363: qemu_free(apdu->a_data); ! 364: } ! 365: qemu_free(apdu); ! 366: } ! 367: ! 368: ! 369: /* ! 370: * declare response buffers for all the 7816 defined error codes ! 371: */ ! 372: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS) ! 373: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING) ! 374: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT) ! 375: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE) ! 376: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED) ! 377: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID) ! 378: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE) ! 379: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED) ! 380: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR) ! 381: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE) ! 382: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE) ! 383: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH) ! 384: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED) ! 385: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED) ! 386: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED) ! 387: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED) ! 388: VCARD_RESPONSE_NEW_STATIC_STATUS( ! 389: VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE) ! 390: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED) ! 391: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED) ! 392: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID) ! 393: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED) ! 394: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF) ! 395: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING) ! 396: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT) ! 397: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS) ! 398: VCARD_RESPONSE_NEW_STATIC_STATUS( ! 399: VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA) ! 400: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED) ! 401: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND) ! 402: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND) ! 403: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE) ! 404: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT) ! 405: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT) ! 406: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT) ! 407: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND) ! 408: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2) ! 409: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID) ! 410: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID) ! 411: VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL) ! 412: ! 413: /* ! 414: * return a single response code. This function cannot fail. It will always ! 415: * return a response. ! 416: */ ! 417: VCardResponse * ! 418: vcard_make_response(vcard_7816_status_t status) ! 419: { ! 420: VCardResponse *response = NULL; ! 421: ! 422: switch (status) { ! 423: /* known 7816 response codes */ ! 424: case VCARD7816_STATUS_SUCCESS: ! 425: return VCARD_RESPONSE_GET_STATIC( ! 426: VCARD7816_STATUS_SUCCESS); ! 427: case VCARD7816_STATUS_WARNING: ! 428: return VCARD_RESPONSE_GET_STATIC( ! 429: VCARD7816_STATUS_WARNING); ! 430: case VCARD7816_STATUS_WARNING_RET_CORUPT: ! 431: return VCARD_RESPONSE_GET_STATIC( ! 432: VCARD7816_STATUS_WARNING_RET_CORUPT); ! 433: case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE: ! 434: return VCARD_RESPONSE_GET_STATIC( ! 435: VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE); ! 436: case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED: ! 437: return VCARD_RESPONSE_GET_STATIC( ! 438: VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED); ! 439: case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID: ! 440: return VCARD_RESPONSE_GET_STATIC( ! 441: VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID); ! 442: case VCARD7816_STATUS_WARNING_CHANGE: ! 443: return VCARD_RESPONSE_GET_STATIC( ! 444: VCARD7816_STATUS_WARNING_CHANGE); ! 445: case VCARD7816_STATUS_WARNING_FILE_FILLED: ! 446: return VCARD_RESPONSE_GET_STATIC( ! 447: VCARD7816_STATUS_WARNING_FILE_FILLED); ! 448: case VCARD7816_STATUS_EXC_ERROR: ! 449: return VCARD_RESPONSE_GET_STATIC( ! 450: VCARD7816_STATUS_EXC_ERROR); ! 451: case VCARD7816_STATUS_EXC_ERROR_CHANGE: ! 452: return VCARD_RESPONSE_GET_STATIC( ! 453: VCARD7816_STATUS_EXC_ERROR_CHANGE); ! 454: case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE: ! 455: return VCARD_RESPONSE_GET_STATIC( ! 456: VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); ! 457: case VCARD7816_STATUS_ERROR_WRONG_LENGTH: ! 458: return VCARD_RESPONSE_GET_STATIC( ! 459: VCARD7816_STATUS_ERROR_WRONG_LENGTH); ! 460: case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED: ! 461: return VCARD_RESPONSE_GET_STATIC( ! 462: VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED); ! 463: case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED: ! 464: return VCARD_RESPONSE_GET_STATIC( ! 465: VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED); ! 466: case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED: ! 467: return VCARD_RESPONSE_GET_STATIC( ! 468: VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED); ! 469: case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED: ! 470: return VCARD_RESPONSE_GET_STATIC( ! 471: VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 472: case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE: ! 473: return VCARD_RESPONSE_GET_STATIC( ! 474: VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE); ! 475: case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED: ! 476: return VCARD_RESPONSE_GET_STATIC( ! 477: VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED); ! 478: case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED: ! 479: return VCARD_RESPONSE_GET_STATIC( ! 480: VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED); ! 481: case VCARD7816_STATUS_ERROR_DATA_INVALID: ! 482: return VCARD_RESPONSE_GET_STATIC( ! 483: VCARD7816_STATUS_ERROR_DATA_INVALID); ! 484: case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED: ! 485: return VCARD_RESPONSE_GET_STATIC( ! 486: VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); ! 487: case VCARD7816_STATUS_ERROR_DATA_NO_EF: ! 488: return VCARD_RESPONSE_GET_STATIC( ! 489: VCARD7816_STATUS_ERROR_DATA_NO_EF); ! 490: case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING: ! 491: return VCARD_RESPONSE_GET_STATIC( ! 492: VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING); ! 493: case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT: ! 494: return VCARD_RESPONSE_GET_STATIC( ! 495: VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT); ! 496: case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS: ! 497: return VCARD_RESPONSE_GET_STATIC( ! 498: VCARD7816_STATUS_ERROR_WRONG_PARAMETERS); ! 499: case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA: ! 500: return VCARD_RESPONSE_GET_STATIC( ! 501: VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA); ! 502: case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED: ! 503: return VCARD_RESPONSE_GET_STATIC( ! 504: VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED); ! 505: case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND: ! 506: return VCARD_RESPONSE_GET_STATIC( ! 507: VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); ! 508: case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND: ! 509: return VCARD_RESPONSE_GET_STATIC( ! 510: VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND); ! 511: case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE: ! 512: return VCARD_RESPONSE_GET_STATIC( ! 513: VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE); ! 514: case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT: ! 515: return VCARD_RESPONSE_GET_STATIC( ! 516: VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT); ! 517: case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT: ! 518: return VCARD_RESPONSE_GET_STATIC( ! 519: VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); ! 520: case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT: ! 521: return VCARD_RESPONSE_GET_STATIC( ! 522: VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT); ! 523: case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND: ! 524: return VCARD_RESPONSE_GET_STATIC( ! 525: VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); ! 526: case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2: ! 527: return VCARD_RESPONSE_GET_STATIC( ! 528: VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2); ! 529: case VCARD7816_STATUS_ERROR_INS_CODE_INVALID: ! 530: return VCARD_RESPONSE_GET_STATIC( ! 531: VCARD7816_STATUS_ERROR_INS_CODE_INVALID); ! 532: case VCARD7816_STATUS_ERROR_CLA_INVALID: ! 533: return VCARD_RESPONSE_GET_STATIC( ! 534: VCARD7816_STATUS_ERROR_CLA_INVALID); ! 535: case VCARD7816_STATUS_ERROR_GENERAL: ! 536: return VCARD_RESPONSE_GET_STATIC( ! 537: VCARD7816_STATUS_ERROR_GENERAL); ! 538: default: ! 539: /* we don't know this status code, create a response buffer to ! 540: * hold it */ ! 541: response = vcard_response_new_status(status); ! 542: if (response == NULL) { ! 543: /* couldn't allocate the buffer, return memmory error */ ! 544: return VCARD_RESPONSE_GET_STATIC( ! 545: VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); ! 546: } ! 547: } ! 548: assert(response); ! 549: return response; ! 550: } ! 551: ! 552: /* ! 553: * Add File card support here if you need it. ! 554: */ ! 555: static VCardStatus ! 556: vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu, ! 557: VCardResponse **response) ! 558: { ! 559: /* TODO: if we want to support a virtual file system card, we do it here. ! 560: * It would probably be a pkcs #15 card type */ ! 561: *response = vcard_make_response( ! 562: VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 563: return VCARD_DONE; ! 564: } ! 565: ! 566: /* ! 567: * VM card (including java cards) ! 568: */ ! 569: static VCardStatus ! 570: vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu, ! 571: VCardResponse **response) ! 572: { ! 573: int bytes_to_copy, next_byte_count, count; ! 574: VCardApplet *current_applet; ! 575: VCardBufferResponse *buffer_response; ! 576: vcard_7816_status_t status; ! 577: ! 578: /* parse the class first */ ! 579: if (apdu->a_gen_type != VCARD_7816_ISO) { ! 580: *response = vcard_make_response( ! 581: VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 582: return VCARD_DONE; ! 583: } ! 584: ! 585: /* use a switch so that if we need to support secure channel stuff later, ! 586: * we know where to put it */ ! 587: switch (apdu->a_secure_messaging) { ! 588: case 0x0: /* no SM */ ! 589: break; ! 590: case 0x4: /* proprietary SM */ ! 591: case 0x8: /* header not authenticated */ ! 592: case 0xc: /* header authenticated */ ! 593: default: ! 594: /* for now, don't try to support secure channel stuff in the ! 595: * virtual card. */ ! 596: *response = vcard_make_response( ! 597: VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED); ! 598: return VCARD_DONE; ! 599: } ! 600: ! 601: /* now parse the instruction */ ! 602: switch (apdu->a_ins) { ! 603: case VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */ ! 604: case VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */ ! 605: case VCARD7816_INS_GET_CHALLENGE: /* secure channel op */ ! 606: case VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */ ! 607: case VCARD7816_INS_ERASE_BINARY: /* applet control op */ ! 608: case VCARD7816_INS_READ_BINARY: /* applet control op */ ! 609: case VCARD7816_INS_WRITE_BINARY: /* applet control op */ ! 610: case VCARD7816_INS_UPDATE_BINARY: /* applet control op */ ! 611: case VCARD7816_INS_READ_RECORD: /* file op */ ! 612: case VCARD7816_INS_WRITE_RECORD: /* file op */ ! 613: case VCARD7816_INS_UPDATE_RECORD: /* file op */ ! 614: case VCARD7816_INS_APPEND_RECORD: /* file op */ ! 615: case VCARD7816_INS_ENVELOPE: ! 616: case VCARD7816_INS_PUT_DATA: ! 617: *response = vcard_make_response( ! 618: VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 619: break; ! 620: ! 621: case VCARD7816_INS_SELECT_FILE: ! 622: if (apdu->a_p1 != 0x04) { ! 623: *response = vcard_make_response( ! 624: VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED); ! 625: break; ! 626: } ! 627: ! 628: /* side effect, deselect the current applet if no applet has been found ! 629: * */ ! 630: current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc); ! 631: vcard_select_applet(card, apdu->a_channel, current_applet); ! 632: if (current_applet) { ! 633: unsigned char *aid; ! 634: int aid_len; ! 635: aid = vcard_applet_get_aid(current_applet, &aid_len); ! 636: *response = vcard_response_new(card, aid, aid_len, apdu->a_Le, ! 637: VCARD7816_STATUS_SUCCESS); ! 638: } else { ! 639: *response = vcard_make_response( ! 640: VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); ! 641: } ! 642: break; ! 643: ! 644: case VCARD7816_INS_VERIFY: ! 645: if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) { ! 646: *response = vcard_make_response( ! 647: VCARD7816_STATUS_ERROR_WRONG_PARAMETERS); ! 648: } else { ! 649: if (apdu->a_Lc == 0) { ! 650: /* handle pin count if possible */ ! 651: count = vcard_emul_get_login_count(card); ! 652: if (count < 0) { ! 653: *response = vcard_make_response( ! 654: VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); ! 655: } else { ! 656: if (count > 0xf) { ! 657: count = 0xf; ! 658: } ! 659: *response = vcard_response_new_status_bytes( ! 660: VCARD7816_SW1_WARNING_CHANGE, ! 661: 0xc0 | count); ! 662: if (*response == NULL) { ! 663: *response = vcard_make_response( ! 664: VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); ! 665: } ! 666: } ! 667: } else { ! 668: status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc); ! 669: *response = vcard_make_response(status); ! 670: } ! 671: } ! 672: break; ! 673: ! 674: case VCARD7816_INS_GET_RESPONSE: ! 675: buffer_response = vcard_get_buffer_response(card); ! 676: if (!buffer_response) { ! 677: *response = vcard_make_response( ! 678: VCARD7816_STATUS_ERROR_DATA_NOT_FOUND); ! 679: /* handle error */ ! 680: break; ! 681: } ! 682: bytes_to_copy = MIN(buffer_response->len, apdu->a_Le); ! 683: next_byte_count = MIN(256, buffer_response->len - bytes_to_copy); ! 684: *response = vcard_response_new_bytes( ! 685: card, buffer_response->current, bytes_to_copy, ! 686: apdu->a_Le, ! 687: next_byte_count ? ! 688: VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS, ! 689: next_byte_count); ! 690: buffer_response->current += bytes_to_copy; ! 691: buffer_response->len -= bytes_to_copy; ! 692: if (*response == NULL || (next_byte_count == 0)) { ! 693: vcard_set_buffer_response(card, NULL); ! 694: vcard_buffer_response_delete(buffer_response); ! 695: } ! 696: if (*response == NULL) { ! 697: *response = ! 698: vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); ! 699: } ! 700: break; ! 701: ! 702: case VCARD7816_INS_GET_DATA: ! 703: *response = ! 704: vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 705: break; ! 706: ! 707: default: ! 708: *response = ! 709: vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 710: break; ! 711: } ! 712: ! 713: /* response should have been set somewhere */ ! 714: assert(*response != NULL); ! 715: return VCARD_DONE; ! 716: } ! 717: ! 718: ! 719: /* ! 720: * APDU processing starts here. This routes the card processing stuff to the ! 721: * right location. ! 722: */ ! 723: VCardStatus ! 724: vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) ! 725: { ! 726: VCardStatus status; ! 727: VCardBufferResponse *buffer_response; ! 728: ! 729: /* first handle any PTS commands, which aren't really APDU's */ ! 730: if (apdu->a_type == VCARD_7816_PTS) { ! 731: /* the PTS responses aren't really responses either */ ! 732: *response = vcard_response_new_data(apdu->a_data, apdu->a_len); ! 733: /* PTS responses have no status bytes */ ! 734: (*response)->b_total_len = (*response)->b_len; ! 735: return VCARD_DONE; ! 736: } ! 737: buffer_response = vcard_get_buffer_response(card); ! 738: if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) { ! 739: /* clear out buffer_response, return an error */ ! 740: vcard_set_buffer_response(card, NULL); ! 741: vcard_buffer_response_delete(buffer_response); ! 742: *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR); ! 743: return VCARD_DONE; ! 744: } ! 745: ! 746: status = vcard_process_applet_apdu(card, apdu, response); ! 747: if (status != VCARD_NEXT) { ! 748: return status; ! 749: } ! 750: switch (vcard_get_type(card)) { ! 751: case VCARD_FILE_SYSTEM: ! 752: return vcard7816_file_system_process_apdu(card, apdu, response); ! 753: case VCARD_VM: ! 754: return vcard7816_vm_process_apdu(card, apdu, response); ! 755: case VCARD_DIRECT: ! 756: /* if we are type direct, then the applet should handle everything */ ! 757: assert("VCARD_DIRECT: applet failure"); ! 758: break; ! 759: } ! 760: *response = ! 761: vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ! 762: return VCARD_DONE; ! 763: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.