Annotation of qemu/libcacard/card_7816.c, revision 1.1

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: }

unix.superglobalmegacorp.com