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

    1: /*
    2:  * implement the applets for the CAC card.
    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 "cac.h"
   11: #include "vcard.h"
   12: #include "vcard_emul.h"
   13: #include "card_7816.h"
   14: 
   15: #define CAC_GET_PROPERTIES  0x56
   16: #define CAC_GET_ACR         0x4c
   17: #define CAC_READ_BUFFER     0x52
   18: #define CAC_UPDATE_BUFFER   0x58
   19: #define CAC_SIGN_DECRYPT    0x42
   20: #define CAC_GET_CERTIFICATE 0x36
   21: 
   22: /* private data for PKI applets */
   23: typedef struct CACPKIAppletDataStruct {
   24:     unsigned char *cert;
   25:     int cert_len;
   26:     unsigned char *cert_buffer;
   27:     int cert_buffer_len;
   28:     unsigned char *sign_buffer;
   29:     int sign_buffer_len;
   30:     VCardKey *key;
   31: } CACPKIAppletData;
   32: 
   33: /*
   34:  * CAC applet private data
   35:  */
   36: struct VCardAppletPrivateStruct {
   37:     union {
   38:         CACPKIAppletData pki_data;
   39:         void *reserved;
   40:     } u;
   41: };
   42: 
   43: /*
   44:  * handle all the APDU's that are common to all CAC applets
   45:  */
   46: static VCardStatus
   47: cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
   48: {
   49:     int ef;
   50: 
   51:     switch (apdu->a_ins) {
   52:     case VCARD7816_INS_SELECT_FILE:
   53:         if (apdu->a_p1 != 0x02) {
   54:             /* let the 7816 code handle applet switches */
   55:             return VCARD_NEXT;
   56:         }
   57:         /* handle file id setting */
   58:         if (apdu->a_Lc != 2) {
   59:             *response = vcard_make_response(
   60:                 VCARD7816_STATUS_ERROR_DATA_INVALID);
   61:             return VCARD_DONE;
   62:         }
   63:         /* CAC 1.0 only supports ef = 0 */
   64:         ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
   65:         if (ef != 0) {
   66:             *response = vcard_make_response(
   67:                 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
   68:             return VCARD_DONE;
   69:         }
   70:         *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
   71:         return VCARD_DONE;
   72:     case VCARD7816_INS_GET_RESPONSE:
   73:     case VCARD7816_INS_VERIFY:
   74:         /* let the 7816 code handle these */
   75:         return VCARD_NEXT;
   76:     case CAC_GET_PROPERTIES:
   77:     case CAC_GET_ACR:
   78:         /* skip these for now, this will probably be needed */
   79:         *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
   80:         return VCARD_DONE;
   81:     }
   82:     *response = vcard_make_response(
   83:         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
   84:     return VCARD_DONE;
   85: }
   86: 
   87: /*
   88:  *  reset the inter call state between applet selects
   89:  */
   90: static VCardStatus
   91: cac_applet_pki_reset(VCard *card, int channel)
   92: {
   93:     VCardAppletPrivate *applet_private = NULL;
   94:     CACPKIAppletData *pki_applet = NULL;
   95:     applet_private = vcard_get_current_applet_private(card, channel);
   96:     assert(applet_private);
   97:     pki_applet = &(applet_private->u.pki_data);
   98: 
   99:     pki_applet->cert_buffer = NULL;
  100:     if (pki_applet->sign_buffer) {
  101:         g_free(pki_applet->sign_buffer);
  102:         pki_applet->sign_buffer = NULL;
  103:     }
  104:     pki_applet->cert_buffer_len = 0;
  105:     pki_applet->sign_buffer_len = 0;
  106:     return VCARD_DONE;
  107: }
  108: 
  109: static VCardStatus
  110: cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
  111:                             VCardResponse **response)
  112: {
  113:     CACPKIAppletData *pki_applet = NULL;
  114:     VCardAppletPrivate *applet_private = NULL;
  115:     int size, next;
  116:     unsigned char *sign_buffer;
  117:     vcard_7816_status_t status;
  118: 
  119:     applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
  120:     assert(applet_private);
  121:     pki_applet = &(applet_private->u.pki_data);
  122: 
  123:     switch (apdu->a_ins) {
  124:     case CAC_UPDATE_BUFFER:
  125:         *response = vcard_make_response(
  126:             VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
  127:         return VCARD_DONE;
  128:     case CAC_GET_CERTIFICATE:
  129:         if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
  130:             *response = vcard_make_response(
  131:                              VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
  132:             break;
  133:         }
  134:         assert(pki_applet->cert != NULL);
  135:         size = apdu->a_Le;
  136:         if (pki_applet->cert_buffer == NULL) {
  137:             pki_applet->cert_buffer = pki_applet->cert;
  138:             pki_applet->cert_buffer_len = pki_applet->cert_len;
  139:         }
  140:         size = MIN(size, pki_applet->cert_buffer_len);
  141:         next = MIN(255, pki_applet->cert_buffer_len - size);
  142:         *response = vcard_response_new_bytes(
  143:                         card, pki_applet->cert_buffer, size,
  144:                         apdu->a_Le, next ?
  145:                         VCARD7816_SW1_WARNING_CHANGE :
  146:                         VCARD7816_SW1_SUCCESS,
  147:                         next);
  148:         pki_applet->cert_buffer += size;
  149:         pki_applet->cert_buffer_len -= size;
  150:         if ((*response == NULL) || (next == 0)) {
  151:             pki_applet->cert_buffer = NULL;
  152:         }
  153:         if (*response == NULL) {
  154:             *response = vcard_make_response(
  155:                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
  156:         }
  157:         return VCARD_DONE;
  158:     case CAC_SIGN_DECRYPT:
  159:         if (apdu->a_p2 != 0) {
  160:             *response = vcard_make_response(
  161:                              VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
  162:             break;
  163:         }
  164:         size = apdu->a_Lc;
  165: 
  166:         sign_buffer = realloc(pki_applet->sign_buffer,
  167:                       pki_applet->sign_buffer_len+size);
  168:         if (sign_buffer == NULL) {
  169:             g_free(pki_applet->sign_buffer);
  170:             pki_applet->sign_buffer = NULL;
  171:             pki_applet->sign_buffer_len = 0;
  172:             *response = vcard_make_response(
  173:                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
  174:             return VCARD_DONE;
  175:         }
  176:         memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
  177:         size += pki_applet->sign_buffer_len;
  178:         switch (apdu->a_p1) {
  179:         case  0x80:
  180:             /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
  181:              * the rest */
  182:             pki_applet->sign_buffer = sign_buffer;
  183:             pki_applet->sign_buffer_len = size;
  184:             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
  185:             return VCARD_DONE;
  186:         case 0x00:
  187:             /* we now have the whole buffer, do the operation, result will be
  188:              * in the sign_buffer */
  189:             status = vcard_emul_rsa_op(card, pki_applet->key,
  190:                                        sign_buffer, size);
  191:             if (status != VCARD7816_STATUS_SUCCESS) {
  192:                 *response = vcard_make_response(status);
  193:                 break;
  194:             }
  195:             *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
  196:                                                      VCARD7816_STATUS_SUCCESS);
  197:             if (*response == NULL) {
  198:                 *response = vcard_make_response(
  199:                                 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
  200:             }
  201:             break;
  202:         default:
  203:            *response = vcard_make_response(
  204:                                 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
  205:             break;
  206:         }
  207:         g_free(sign_buffer);
  208:         pki_applet->sign_buffer = NULL;
  209:         pki_applet->sign_buffer_len = 0;
  210:         return VCARD_DONE;
  211:     case CAC_READ_BUFFER:
  212:         /* new CAC call, go ahead and use the old version for now */
  213:         /* TODO: implement */
  214:         *response = vcard_make_response(
  215:                                 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
  216:         return VCARD_DONE;
  217:     }
  218:     return cac_common_process_apdu(card, apdu, response);
  219: }
  220: 
  221: 
  222: static VCardStatus
  223: cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
  224:                            VCardResponse **response)
  225: {
  226:     switch (apdu->a_ins) {
  227:     case CAC_UPDATE_BUFFER:
  228:         *response = vcard_make_response(
  229:                         VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
  230:         return VCARD_DONE;
  231:     case CAC_READ_BUFFER:
  232:         /* new CAC call, go ahead and use the old version for now */
  233:         /* TODO: implement */
  234:         *response = vcard_make_response(
  235:                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
  236:         return VCARD_DONE;
  237:     }
  238:     return cac_common_process_apdu(card, apdu, response);
  239: }
  240: 
  241: 
  242: /*
  243:  * TODO: if we ever want to support general CAC middleware, we will need to
  244:  * implement the various containers.
  245:  */
  246: static VCardStatus
  247: cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
  248:                                   VCardResponse **response)
  249: {
  250:     switch (apdu->a_ins) {
  251:     case CAC_READ_BUFFER:
  252:     case CAC_UPDATE_BUFFER:
  253:         *response = vcard_make_response(
  254:                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
  255:         return VCARD_DONE;
  256:     default:
  257:         break;
  258:     }
  259:     return cac_common_process_apdu(card, apdu, response);
  260: }
  261: 
  262: /*
  263:  * utilities for creating and destroying the private applet data
  264:  */
  265: static void
  266: cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
  267: {
  268:     CACPKIAppletData *pki_applet_data = NULL;
  269: 
  270:     if (applet_private == NULL) {
  271:         return;
  272:     }
  273:     pki_applet_data = &(applet_private->u.pki_data);
  274:     if (pki_applet_data->cert != NULL) {
  275:         g_free(pki_applet_data->cert);
  276:     }
  277:     if (pki_applet_data->sign_buffer != NULL) {
  278:         g_free(pki_applet_data->sign_buffer);
  279:     }
  280:     if (pki_applet_data->key != NULL) {
  281:         vcard_emul_delete_key(pki_applet_data->key);
  282:     }
  283:     g_free(applet_private);
  284: }
  285: 
  286: static VCardAppletPrivate *
  287: cac_new_pki_applet_private(const unsigned char *cert,
  288:                            int cert_len, VCardKey *key)
  289: {
  290:     CACPKIAppletData *pki_applet_data = NULL;
  291:     VCardAppletPrivate *applet_private = NULL;
  292:     applet_private = (VCardAppletPrivate *)g_malloc(sizeof(VCardAppletPrivate));
  293: 
  294:     pki_applet_data = &(applet_private->u.pki_data);
  295:     pki_applet_data->cert_buffer = NULL;
  296:     pki_applet_data->cert_buffer_len = 0;
  297:     pki_applet_data->sign_buffer = NULL;
  298:     pki_applet_data->sign_buffer_len = 0;
  299:     pki_applet_data->key = NULL;
  300:     pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1);
  301:     /*
  302:      * if we want to support compression, then we simply change the 0 to a 1
  303:      * and compress the cert data with libz
  304:      */
  305:     pki_applet_data->cert[0] = 0; /* not compressed */
  306:     memcpy(&pki_applet_data->cert[1], cert, cert_len);
  307:     pki_applet_data->cert_len = cert_len+1;
  308: 
  309:     pki_applet_data->key = key;
  310:     return applet_private;
  311: }
  312: 
  313: 
  314: /*
  315:  * create a new cac applet which links to a given cert
  316:  */
  317: static VCardApplet *
  318: cac_new_pki_applet(int i, const unsigned char *cert,
  319:                    int cert_len, VCardKey *key)
  320: {
  321:     VCardAppletPrivate *applet_private = NULL;
  322:     VCardApplet *applet = NULL;
  323:     unsigned char pki_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
  324:     int pki_aid_len = sizeof(pki_aid);
  325: 
  326:     pki_aid[pki_aid_len-1] = i;
  327: 
  328:     applet_private = cac_new_pki_applet_private(cert, cert_len, key);
  329:     if (applet_private == NULL) {
  330:         goto failure;
  331:     }
  332:     applet = vcard_new_applet(cac_applet_pki_process_apdu, cac_applet_pki_reset,
  333:                               pki_aid, pki_aid_len);
  334:     if (applet == NULL) {
  335:         goto failure;
  336:     }
  337:     vcard_set_applet_private(applet, applet_private,
  338:                              cac_delete_pki_applet_private);
  339:     applet_private = NULL;
  340: 
  341:     return applet;
  342: 
  343: failure:
  344:     if (applet_private != NULL) {
  345:         cac_delete_pki_applet_private(applet_private);
  346:     }
  347:     return NULL;
  348: }
  349: 
  350: 
  351: static unsigned char cac_default_container_aid[] = {
  352:     0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
  353: static unsigned char cac_id_aid[] = {
  354:     0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 };
  355: /*
  356:  * Initialize the cac card. This is the only public function in this file. All
  357:  * the rest are connected through function pointers.
  358:  */
  359: VCardStatus
  360: cac_card_init(VReader *reader, VCard *card,
  361:               const char *params,
  362:               unsigned char * const *cert,
  363:               int cert_len[],
  364:               VCardKey *key[] /* adopt the keys*/,
  365:               int cert_count)
  366: {
  367:     int i;
  368:     VCardApplet *applet;
  369: 
  370:     /* CAC Cards are VM Cards */
  371:     vcard_set_type(card, VCARD_VM);
  372: 
  373:     /* create one PKI applet for each cert */
  374:     for (i = 0; i < cert_count; i++) {
  375:         applet = cac_new_pki_applet(i, cert[i], cert_len[i], key[i]);
  376:         if (applet == NULL) {
  377:             goto failure;
  378:         }
  379:         vcard_add_applet(card, applet);
  380:     }
  381: 
  382:     /* create a default blank container applet */
  383:     applet = vcard_new_applet(cac_applet_container_process_apdu,
  384:                               NULL, cac_default_container_aid,
  385:                               sizeof(cac_default_container_aid));
  386:     if (applet == NULL) {
  387:         goto failure;
  388:     }
  389:     vcard_add_applet(card, applet);
  390: 
  391:     /* create a default blank container applet */
  392:     applet = vcard_new_applet(cac_applet_id_process_apdu,
  393:                               NULL, cac_id_aid,
  394:                               sizeof(cac_id_aid));
  395:     if (applet == NULL) {
  396:         goto failure;
  397:     }
  398:     vcard_add_applet(card, applet);
  399:     return VCARD_DONE;
  400: 
  401: failure:
  402:     return VCARD_FAIL;
  403: }
  404: 

unix.superglobalmegacorp.com