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