Annotation of qemu/libcacard/cac.c, revision 1.1.1.2

1.1       root        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) {
1.1.1.2 ! root      101:         g_free(pki_applet->sign_buffer);
1.1       root      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) {
1.1.1.2 ! root      169:             g_free(pki_applet->sign_buffer);
1.1       root      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:         }
1.1.1.2 ! root      207:         g_free(sign_buffer);
1.1       root      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;
1.1.1.2 ! root      269: 
        !           270:     if (applet_private == NULL) {
1.1       root      271:         return;
                    272:     }
                    273:     pki_applet_data = &(applet_private->u.pki_data);
                    274:     if (pki_applet_data->cert != NULL) {
1.1.1.2 ! root      275:         g_free(pki_applet_data->cert);
1.1       root      276:     }
                    277:     if (pki_applet_data->sign_buffer != NULL) {
1.1.1.2 ! root      278:         g_free(pki_applet_data->sign_buffer);
1.1       root      279:     }
                    280:     if (pki_applet_data->key != NULL) {
                    281:         vcard_emul_delete_key(pki_applet_data->key);
                    282:     }
1.1.1.2 ! root      283:     g_free(applet_private);
1.1       root      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;
1.1.1.2 ! root      292:     applet_private = (VCardAppletPrivate *)g_malloc(sizeof(VCardAppletPrivate));
1.1       root      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;
1.1.1.2 ! root      300:     pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1);
1.1       root      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