File:  [Qemu by Fabrice Bellard] / qemu / libcacard / card_7816.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:31:38 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

    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 *)g_malloc(sizeof(VCardResponse));
   55:     new_response->b_data = g_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 *)g_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 *)g_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:             g_free(response->b_data);
  177:         }
  178:         g_free(response);
  179:         break;
  180:     case VCARD_MALLOC_DATA:
  181:         /* only the data buffer was malloc'ed */
  182:         if (response->b_data) {
  183:             g_free(response->b_data);
  184:         }
  185:         break;
  186:     case VCARD_MALLOC_STRUCT:
  187:         /* only the structure was malloc'ed */
  188:         g_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 *)g_malloc(sizeof(VCardAPDU));
  340:     new_apdu->a_data = g_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:         g_free(new_apdu);
  346:         return NULL;
  347:     }
  348:     *status = vcard_apdu_set_length(new_apdu);
  349:     if (*status != VCARD7816_STATUS_SUCCESS) {
  350:         g_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:         g_free(apdu->a_data);
  364:     }
  365:     g_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