File:  [Qemu by Fabrice Bellard] / qemu / libcacard / vcard_emul_nss.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:03:08 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.1

    1: /*
    2:  * This is the actual card emulator.
    3:  *
    4:  * These functions can be implemented in different ways on different platforms
    5:  * using the underlying system primitives. For Linux it uses NSS, though direct
    6:  * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
    7:  * used. On Windows CAPI could be used.
    8:  *
    9:  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
   10:  * See the COPYING.LIB file in the top-level directory.
   11:  */
   12: 
   13: /*
   14:  * NSS headers
   15:  */
   16: 
   17: /* avoid including prototypes.h that redefines uint32 */
   18: #define NO_NSPR_10_SUPPORT
   19: 
   20: #include <nss.h>
   21: #include <pk11pub.h>
   22: #include <cert.h>
   23: #include <key.h>
   24: #include <secmod.h>
   25: #include <prthread.h>
   26: #include <secerr.h>
   27: 
   28: #include "qemu-common.h"
   29: 
   30: #include "vcard.h"
   31: #include "card_7816t.h"
   32: #include "vcard_emul.h"
   33: #include "vreader.h"
   34: #include "vevent.h"
   35: 
   36: struct VCardKeyStruct {
   37:     CERTCertificate *cert;
   38:     PK11SlotInfo *slot;
   39:     SECKEYPrivateKey *key;
   40: };
   41: 
   42: 
   43: typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
   44: 
   45: struct VReaderEmulStruct {
   46:     PK11SlotInfo *slot;
   47:     VCardEmulType default_type;
   48:     char *type_params;
   49:     PRBool present;
   50:     int     series;
   51:     VCard *saved_vcard;
   52: };
   53: 
   54: /*
   55:  *  NSS Specific options
   56:  */
   57: struct VirtualReaderOptionsStruct {
   58:     char *name;
   59:     char *vname;
   60:     VCardEmulType card_type;
   61:     char *type_params;
   62:     char **cert_name;
   63:     int cert_count;
   64: };
   65: 
   66: struct VCardEmulOptionsStruct {
   67:     void *nss_db;
   68:     VirtualReaderOptions *vreader;
   69:     int vreader_count;
   70:     VCardEmulType hw_card_type;
   71:     const char *hw_type_params;
   72:     PRBool use_hw;
   73: };
   74: 
   75: static int nss_emul_init;
   76: 
   77: /* if we have more that just the slot, define
   78:  * VCardEmulStruct here */
   79: 
   80: /*
   81:  * allocate the set of arrays for certs, cert_len, key
   82:  */
   83: static PRBool
   84: vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
   85:                         VCardKey ***keysp, int cert_count)
   86: {
   87:     *certsp = NULL;
   88:     *cert_lenp = NULL;
   89:     *keysp = NULL;
   90:     *certsp = (unsigned char **)qemu_malloc(sizeof(unsigned char *)*cert_count);
   91:     *cert_lenp = (int *)qemu_malloc(sizeof(int)*cert_count);
   92:     *keysp = (VCardKey **)qemu_malloc(sizeof(VCardKey *)*cert_count);
   93:     return PR_TRUE;
   94: }
   95: 
   96: /*
   97:  * Emulator specific card information
   98:  */
   99: typedef struct CardEmulCardStruct CardEmulPrivate;
  100: 
  101: static VCardEmul *
  102: vcard_emul_new_card(PK11SlotInfo *slot)
  103: {
  104:     PK11_ReferenceSlot(slot);
  105:     /* currently we don't need anything other than the slot */
  106:     return (VCardEmul *)slot;
  107: }
  108: 
  109: static void
  110: vcard_emul_delete_card(VCardEmul *vcard_emul)
  111: {
  112:     PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
  113:     if (slot == NULL) {
  114:         return;
  115:     }
  116:     PK11_FreeSlot(slot);
  117: }
  118: 
  119: static PK11SlotInfo *
  120: vcard_emul_card_get_slot(VCard *card)
  121: {
  122:     /* note, the card is holding the reference, no need to get another one */
  123:     return (PK11SlotInfo *)vcard_get_private(card);
  124: }
  125: 
  126: 
  127: /*
  128:  * key functions
  129:  */
  130: /* private constructure */
  131: static VCardKey *
  132: vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
  133: {
  134:     VCardKey *key;
  135: 
  136:     key = (VCardKey *)qemu_malloc(sizeof(VCardKey));
  137:     key->slot = PK11_ReferenceSlot(slot);
  138:     key->cert = CERT_DupCertificate(cert);
  139:     /* NOTE: if we aren't logged into the token, this could return NULL */
  140:     /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
  141:      * use the DER version of this function */
  142:     key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
  143:     return key;
  144: }
  145: 
  146: /* destructor */
  147: void
  148: vcard_emul_delete_key(VCardKey *key)
  149: {
  150:     if (!nss_emul_init || (key == NULL)) {
  151:         return;
  152:     }
  153:     if (key->key) {
  154:         SECKEY_DestroyPrivateKey(key->key);
  155:         key->key = NULL;
  156:     }
  157:     if (key->cert) {
  158:         CERT_DestroyCertificate(key->cert);
  159:     }
  160:     if (key->slot) {
  161:         PK11_FreeSlot(key->slot);
  162:     }
  163:     return;
  164: }
  165: 
  166: /*
  167:  * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
  168:  */
  169: static SECKEYPrivateKey *
  170: vcard_emul_get_nss_key(VCardKey *key)
  171: {
  172:     if (key->key) {
  173:         return key->key;
  174:     }
  175:     /* NOTE: if we aren't logged into the token, this could return NULL */
  176:     key->key = PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
  177:     return key->key;
  178: }
  179: 
  180: /*
  181:  * Map NSS errors to 7816 errors
  182:  */
  183: static vcard_7816_status_t
  184: vcard_emul_map_error(int error)
  185: {
  186:     switch (error) {
  187:     case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
  188:         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
  189:     case SEC_ERROR_BAD_DATA:
  190:     case SEC_ERROR_OUTPUT_LEN:
  191:     case SEC_ERROR_INPUT_LEN:
  192:     case SEC_ERROR_INVALID_ARGS:
  193:     case SEC_ERROR_INVALID_ALGORITHM:
  194:     case SEC_ERROR_NO_KEY:
  195:     case SEC_ERROR_INVALID_KEY:
  196:     case SEC_ERROR_DECRYPTION_DISALLOWED:
  197:         return VCARD7816_STATUS_ERROR_DATA_INVALID;
  198:     case SEC_ERROR_NO_MEMORY:
  199:         return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
  200:     }
  201:     return VCARD7816_STATUS_EXC_ERROR_CHANGE;
  202: }
  203: 
  204: /* RSA sign/decrypt with the key, signature happens 'in place' */
  205: vcard_7816_status_t
  206: vcard_emul_rsa_op(VCard *card, VCardKey *key,
  207:                   unsigned char *buffer, int buffer_size)
  208: {
  209:     SECKEYPrivateKey *priv_key;
  210:     unsigned signature_len;
  211:     SECStatus rv;
  212: 
  213:     if ((!nss_emul_init) || (key == NULL)) {
  214:         /* couldn't get the key, indicate that we aren't logged in */
  215:         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
  216:     }
  217:     priv_key = vcard_emul_get_nss_key(key);
  218: 
  219:     /*
  220:      * this is only true of the rsa signature
  221:      */
  222:     signature_len = PK11_SignatureLen(priv_key);
  223:     if (buffer_size != signature_len) {
  224:         return  VCARD7816_STATUS_ERROR_DATA_INVALID;
  225:     }
  226:     rv = PK11_PrivDecryptRaw(priv_key, buffer, &signature_len, signature_len,
  227:                              buffer, buffer_size);
  228:     if (rv != SECSuccess) {
  229:         return vcard_emul_map_error(PORT_GetError());
  230:     }
  231:     assert(buffer_size == signature_len);
  232:     return VCARD7816_STATUS_SUCCESS;
  233: }
  234: 
  235: /*
  236:  * Login functions
  237:  */
  238: /* return the number of login attempts still possible on the card. if unknown,
  239:  * return -1 */
  240: int
  241: vcard_emul_get_login_count(VCard *card)
  242: {
  243:     return -1;
  244: }
  245: 
  246: /* login into the card, return the 7816 status word (sw2 || sw1) */
  247: vcard_7816_status_t
  248: vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
  249: {
  250:     PK11SlotInfo *slot;
  251:     unsigned char *pin_string = NULL;
  252:     int i;
  253:     SECStatus rv;
  254: 
  255:     if (!nss_emul_init) {
  256:         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
  257:     }
  258:     slot = vcard_emul_card_get_slot(card);
  259:      /* We depend on the PKCS #11 module internal login state here because we
  260:       * create a separate process to handle each guest instance. If we needed
  261:       * to handle multiple guests from one process, then we would need to keep
  262:       * a lot of extra state in our card structure
  263:       * */
  264:     pin_string = qemu_malloc(pin_len+1);
  265:     memcpy(pin_string, pin, pin_len);
  266:     pin_string[pin_len] = 0;
  267: 
  268:     /* handle CAC expanded pins correctly */
  269:     for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
  270:         pin_string[i] = 0;
  271:     }
  272: 
  273:     rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
  274:     memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
  275:                                         to be snooped */
  276:     qemu_free(pin_string);
  277:     if (rv == SECSuccess) {
  278:         return VCARD7816_STATUS_SUCCESS;
  279:     }
  280:     /* map the error from port get error */
  281:     return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
  282: }
  283: 
  284: void
  285: vcard_emul_reset(VCard *card, VCardPower power)
  286: {
  287:     PK11SlotInfo *slot;
  288: 
  289:     if (!nss_emul_init) {
  290:         return;
  291:     }
  292: 
  293:     /*
  294:      * if we reset the card (either power on or power off), we lose our login
  295:      * state
  296:      */
  297:     /* TODO: we may also need to send insertion/removal events? */
  298:     slot = vcard_emul_card_get_slot(card);
  299:     PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
  300:     return;
  301: }
  302: 
  303: 
  304: static VReader *
  305: vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
  306: {
  307:     VReaderList *reader_list = vreader_get_reader_list();
  308:     VReaderListEntry *current_entry = NULL;
  309: 
  310:     if (reader_list == NULL) {
  311:         return NULL;
  312:     }
  313:     for (current_entry = vreader_list_get_first(reader_list); current_entry;
  314:                         current_entry = vreader_list_get_next(current_entry)) {
  315:         VReader *reader = vreader_list_get_reader(current_entry);
  316:         VReaderEmul *reader_emul = vreader_get_private(reader);
  317:         if (reader_emul->slot == slot) {
  318:             return reader;
  319:         }
  320:         vreader_free(reader);
  321:     }
  322: 
  323:     return NULL;
  324: }
  325: 
  326: /*
  327:  * create a new reader emul
  328:  */
  329: static VReaderEmul *
  330: vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
  331: {
  332:     VReaderEmul *new_reader_emul;
  333: 
  334:     new_reader_emul = (VReaderEmul *)qemu_malloc(sizeof(VReaderEmul));
  335: 
  336:     new_reader_emul->slot = PK11_ReferenceSlot(slot);
  337:     new_reader_emul->default_type = type;
  338:     new_reader_emul->type_params = strdup(params);
  339:     new_reader_emul->present = PR_FALSE;
  340:     new_reader_emul->series = 0;
  341:     new_reader_emul->saved_vcard = NULL;
  342:     return new_reader_emul;
  343: }
  344: 
  345: static void
  346: vreader_emul_delete(VReaderEmul *vreader_emul)
  347: {
  348:     if (vreader_emul == NULL) {
  349:         return;
  350:     }
  351:     if (vreader_emul->slot) {
  352:         PK11_FreeSlot(vreader_emul->slot);
  353:     }
  354:     if (vreader_emul->type_params) {
  355:         qemu_free(vreader_emul->type_params);
  356:     }
  357:     qemu_free(vreader_emul);
  358: }
  359: 
  360: /*
  361:  *  TODO: move this to emulater non-specific file
  362:  */
  363: static VCardEmulType
  364: vcard_emul_get_type(VReader *vreader)
  365: {
  366:     VReaderEmul *vreader_emul;
  367: 
  368:     vreader_emul = vreader_get_private(vreader);
  369:     if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
  370:         return vreader_emul->default_type;
  371:     }
  372: 
  373:     return vcard_emul_type_select(vreader);
  374: }
  375: /*
  376:  *  TODO: move this to emulater non-specific file
  377:  */
  378: static const char *
  379: vcard_emul_get_type_params(VReader *vreader)
  380: {
  381:     VReaderEmul *vreader_emul;
  382: 
  383:     vreader_emul = vreader_get_private(vreader);
  384:     if (vreader_emul && vreader_emul->type_params) {
  385:         return vreader_emul->type_params;
  386:     }
  387: 
  388:     return "";
  389: }
  390: 
  391: /* pull the slot out of the reader private data */
  392: static PK11SlotInfo *
  393: vcard_emul_reader_get_slot(VReader *vreader)
  394: {
  395:     VReaderEmul *vreader_emul = vreader_get_private(vreader);
  396:     if (vreader_emul == NULL) {
  397:         return NULL;
  398:     }
  399:     return vreader_emul->slot;
  400: }
  401: 
  402: /*
  403:  *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
  404:  *  historical bytes for any software emulated card. The remaining bytes can be
  405:  *  used to indicate the actual emulator
  406:  */
  407: static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
  408: 
  409: void
  410: vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
  411: {
  412:     int len = MIN(sizeof(nss_atr), *atr_len);
  413:     assert(atr != NULL);
  414: 
  415:     memcpy(atr, nss_atr, len);
  416:     *atr_len = len;
  417:     return;
  418: }
  419: 
  420: /*
  421:  * create a new card from certs and keys
  422:  */
  423: static VCard *
  424: vcard_emul_make_card(VReader *reader,
  425:                      unsigned char * const *certs, int *cert_len,
  426:                      VCardKey *keys[], int cert_count)
  427: {
  428:     VCardEmul *vcard_emul;
  429:     VCard *vcard;
  430:     PK11SlotInfo *slot;
  431:     VCardEmulType type;
  432:     const char *params;
  433: 
  434:     type = vcard_emul_get_type(reader);
  435: 
  436:     /* ignore the inserted card */
  437:     if (type == VCARD_EMUL_NONE) {
  438:         return NULL;
  439:     }
  440:     slot = vcard_emul_reader_get_slot(reader);
  441:     if (slot == NULL) {
  442:         return NULL;
  443:     }
  444: 
  445:     params = vcard_emul_get_type_params(reader);
  446:     /* params these can be NULL */
  447: 
  448:     vcard_emul = vcard_emul_new_card(slot);
  449:     if (vcard_emul == NULL) {
  450:         return NULL;
  451:     }
  452:     vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
  453:     if (vcard == NULL) {
  454:         vcard_emul_delete_card(vcard_emul);
  455:         return NULL;
  456:     }
  457:     vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
  458:     return vcard;
  459: }
  460: 
  461: 
  462: /*
  463:  * 'clone' a physical card as a virtual card
  464:  */
  465: static VCard *
  466: vcard_emul_mirror_card(VReader *vreader)
  467: {
  468:     /*
  469:      * lookup certs using the C_FindObjects. The Stan Cert handle won't give
  470:      * us the real certs until we log in.
  471:      */
  472:     PK11GenericObject *firstObj, *thisObj;
  473:     int cert_count;
  474:     unsigned char **certs;
  475:     int *cert_len;
  476:     VCardKey **keys;
  477:     PK11SlotInfo *slot;
  478:     PRBool ret;
  479: 
  480:     slot = vcard_emul_reader_get_slot(vreader);
  481:     if (slot == NULL) {
  482:         return NULL;
  483:     }
  484: 
  485:     firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
  486:     if (firstObj == NULL) {
  487:         return NULL;
  488:     }
  489: 
  490:     /* count the certs */
  491:     cert_count = 0;
  492:     for (thisObj = firstObj; thisObj;
  493:                              thisObj = PK11_GetNextGenericObject(thisObj)) {
  494:         cert_count++;
  495:     }
  496: 
  497:     if (cert_count == 0) {
  498:         PK11_DestroyGenericObjects(firstObj);
  499:         return NULL;
  500:     }
  501: 
  502:     /* allocate the arrays */
  503:     ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
  504:     if (ret == PR_FALSE) {
  505:         return NULL;
  506:     }
  507: 
  508:     /* fill in the arrays */
  509:     cert_count = 0;
  510:     for (thisObj = firstObj; thisObj;
  511:                              thisObj = PK11_GetNextGenericObject(thisObj)) {
  512:         SECItem derCert;
  513:         CERTCertificate *cert;
  514:         SECStatus rv;
  515: 
  516:         rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
  517:                                    CKA_VALUE, &derCert);
  518:         if (rv != SECSuccess) {
  519:             continue;
  520:         }
  521:         /* create floating temp cert. This gives us a cert structure even if
  522:          * the token isn't logged in */
  523:         cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
  524:                                        NULL, PR_FALSE, PR_TRUE);
  525:         SECITEM_FreeItem(&derCert, PR_FALSE);
  526:         if (cert == NULL) {
  527:             continue;
  528:         }
  529: 
  530:         certs[cert_count] = cert->derCert.data;
  531:         cert_len[cert_count] = cert->derCert.len;
  532:         keys[cert_count] = vcard_emul_make_key(slot, cert);
  533:         cert_count++;
  534:         CERT_DestroyCertificate(cert); /* key obj still has a reference */
  535:     }
  536: 
  537:     /* now create the card */
  538:     return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
  539: }
  540: 
  541: static VCardEmulType default_card_type = VCARD_EMUL_NONE;
  542: static const char *default_type_params = "";
  543: 
  544: /*
  545:  * This thread looks for card and reader insertions and puts events on the
  546:  * event queue
  547:  */
  548: static void
  549: vcard_emul_event_thread(void *arg)
  550: {
  551:     PK11SlotInfo *slot;
  552:     VReader *vreader;
  553:     VReaderEmul *vreader_emul;
  554:     VCard *vcard;
  555:     SECMODModule *module = (SECMODModule *)arg;
  556: 
  557:     do {
  558:         slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
  559:         if (slot == NULL) {
  560:             break;
  561:         }
  562:         vreader = vcard_emul_find_vreader_from_slot(slot);
  563:         if (vreader == NULL) {
  564:             /* new vreader */
  565:             vreader_emul = vreader_emul_new(slot, default_card_type,
  566:                                             default_type_params);
  567:             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
  568:                                   vreader_emul_delete);
  569:             PK11_FreeSlot(slot);
  570:             slot = NULL;
  571:             vreader_add_reader(vreader);
  572:             vreader_free(vreader);
  573:             continue;
  574:         }
  575:         /* card remove/insert */
  576:         vreader_emul = vreader_get_private(vreader);
  577:         if (PK11_IsPresent(slot)) {
  578:             int series = PK11_GetSlotSeries(slot);
  579:             if (series != vreader_emul->series) {
  580:                 if (vreader_emul->present) {
  581:                     vreader_insert_card(vreader, NULL);
  582:                 }
  583:                 vcard = vcard_emul_mirror_card(vreader);
  584:                 vreader_insert_card(vreader, vcard);
  585:                 vcard_free(vcard);
  586:             }
  587:             vreader_emul->series = series;
  588:             vreader_emul->present = 1;
  589:             vreader_free(vreader);
  590:             PK11_FreeSlot(slot);
  591:             continue;
  592:         }
  593:         if (vreader_emul->present) {
  594:             vreader_insert_card(vreader, NULL);
  595:         }
  596:         vreader_emul->series = 0;
  597:         vreader_emul->present = 0;
  598:         PK11_FreeSlot(slot);
  599:         vreader_free(vreader);
  600:     } while (1);
  601: }
  602: 
  603: /* if the card is inserted when we start up, make sure our state is correct */
  604: static void
  605: vcard_emul_init_series(VReader *vreader, VCard *vcard)
  606: {
  607:     VReaderEmul *vreader_emul = vreader_get_private(vreader);
  608:     PK11SlotInfo *slot = vreader_emul->slot;
  609: 
  610:     vreader_emul->present = PK11_IsPresent(slot);
  611:     vreader_emul->series = PK11_GetSlotSeries(slot);
  612:     if (vreader_emul->present == 0) {
  613:         vreader_insert_card(vreader, NULL);
  614:     }
  615: }
  616: 
  617: /*
  618:  * each module has a separate wait call, create a thread for each module that
  619:  * we are using.
  620:  */
  621: static void
  622: vcard_emul_new_event_thread(SECMODModule *module)
  623: {
  624:     PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
  625:                      module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
  626:                      PR_UNJOINABLE_THREAD, 0);
  627: }
  628: 
  629: static const VCardEmulOptions default_options = {
  630:     .nss_db = NULL,
  631:     .vreader = NULL,
  632:     .vreader_count = 0,
  633:     .hw_card_type = VCARD_EMUL_CAC,
  634:     .hw_type_params = "",
  635:     .use_hw = PR_TRUE
  636: };
  637: 
  638: 
  639: /*
  640:  *  NSS needs the app to supply a password prompt. In our case the only time
  641:  *  the password is supplied is as part of the Login APDU. The actual password
  642:  *  is passed in the pw_arg in that case. In all other cases pw_arg should be
  643:  *  NULL.
  644:  */
  645: static char *
  646: vcard_emul_get_password(PK11SlotInfo *slot, PRBool retries, void *pw_arg)
  647: {
  648:     /* if it didn't work the first time, don't keep trying */
  649:     if (retries) {
  650:         return NULL;
  651:     }
  652:     /* we are looking up a password when we don't have one in hand */
  653:     if (pw_arg == NULL) {
  654:         return NULL;
  655:     }
  656:     /* TODO: we really should verify that were are using the right slot */
  657:     return PORT_Strdup(pw_arg);
  658: }
  659: 
  660: /* Force a card removal even if the card is not physically removed */
  661: VCardEmulError
  662: vcard_emul_force_card_remove(VReader *vreader)
  663: {
  664:     if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
  665:         return VCARD_EMUL_FAIL; /* card is already removed */
  666:     }
  667: 
  668:     /* OK, remove it */
  669:     vreader_insert_card(vreader, NULL);
  670:     return VCARD_EMUL_OK;
  671: }
  672: 
  673: /* Re-insert of a card that has been removed by force removal */
  674: VCardEmulError
  675: vcard_emul_force_card_insert(VReader *vreader)
  676: {
  677:     VReaderEmul *vreader_emul;
  678:     VCard *vcard;
  679: 
  680:     if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
  681:         return VCARD_EMUL_FAIL; /* card is already removed */
  682:     }
  683:     vreader_emul = vreader_get_private(vreader);
  684: 
  685:     /* if it's a softcard, get the saved vcard from the reader emul structure */
  686:     if (vreader_emul->saved_vcard) {
  687:         vcard = vcard_reference(vreader_emul->saved_vcard);
  688:     } else {
  689:         /* it must be a physical card, rebuild it */
  690:         if (!PK11_IsPresent(vreader_emul->slot)) {
  691:             /* physical card has been removed, not way to reinsert it */
  692:             return VCARD_EMUL_FAIL;
  693:         }
  694:         vcard = vcard_emul_mirror_card(vreader);
  695:     }
  696:     vreader_insert_card(vreader, vcard);
  697:     vcard_free(vcard);
  698: 
  699:     return VCARD_EMUL_OK;
  700: }
  701: 
  702: 
  703: static PRBool
  704: module_has_removable_hw_slots(SECMODModule *mod)
  705: {
  706:     int i;
  707:     PRBool ret = PR_FALSE;
  708:     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  709: 
  710:     if (!moduleLock) {
  711:         PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
  712:         return ret;
  713:     }
  714:     SECMOD_GetReadLock(moduleLock);
  715:     for (i = 0; i < mod->slotCount; i++) {
  716:         PK11SlotInfo *slot = mod->slots[i];
  717:         if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
  718:             ret = PR_TRUE;
  719:             break;
  720:         }
  721:     }
  722:     SECMOD_ReleaseReadLock(moduleLock);
  723:     return ret;
  724: }
  725: 
  726: /* Previously we returned FAIL if no readers found. This makes
  727:  * no sense when using hardware, since there may be no readers connected
  728:  * at the time vcard_emul_init is called, but they will be properly
  729:  * recognized later. So Instead return FAIL only if no_hw==1 and no
  730:  * vcards can be created (indicates error with certificates provided
  731:  * or db), or if any other higher level error (NSS error, missing coolkey). */
  732: static int vcard_emul_init_called;
  733: 
  734: VCardEmulError
  735: vcard_emul_init(const VCardEmulOptions *options)
  736: {
  737:     SECStatus rv;
  738:     PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
  739:     VReader *vreader;
  740:     VReaderEmul *vreader_emul;
  741:     SECMODListLock *module_lock;
  742:     SECMODModuleList *module_list;
  743:     SECMODModuleList *mlp;
  744:     int i;
  745: 
  746:     if (vcard_emul_init_called) {
  747:         return VCARD_EMUL_INIT_ALREADY_INITED;
  748:     }
  749:     vcard_emul_init_called = 1;
  750:     vreader_init();
  751:     vevent_queue_init();
  752: 
  753:     if (options == NULL) {
  754:         options = &default_options;
  755:     }
  756: 
  757:     /* first initialize NSS */
  758:     if (options->nss_db) {
  759:         rv = NSS_Init(options->nss_db);
  760:     } else {
  761:         rv = NSS_Init("sql:/etc/pki/nssdb");
  762:     }
  763:     if (rv != SECSuccess) {
  764:         return VCARD_EMUL_FAIL;
  765:     }
  766:     /* Set password callback function */
  767:     PK11_SetPasswordFunc(vcard_emul_get_password);
  768: 
  769:     /* set up soft cards emulated by software certs rather than physical cards
  770:      * */
  771:     for (i = 0; i < options->vreader_count; i++) {
  772:         int j;
  773:         int cert_count;
  774:         unsigned char **certs;
  775:         int *cert_len;
  776:         VCardKey **keys;
  777:         PK11SlotInfo *slot;
  778: 
  779:         slot = PK11_FindSlotByName(options->vreader[i].name);
  780:         if (slot == NULL) {
  781:             continue;
  782:         }
  783:         vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
  784:                                         options->vreader[i].type_params);
  785:         vreader = vreader_new(options->vreader[i].vname, vreader_emul,
  786:                               vreader_emul_delete);
  787:         vreader_add_reader(vreader);
  788:         cert_count = options->vreader[i].cert_count;
  789: 
  790:         ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
  791:                                       options->vreader[i].cert_count);
  792:         if (ret == PR_FALSE) {
  793:             continue;
  794:         }
  795:         cert_count = 0;
  796:         for (j = 0; j < options->vreader[i].cert_count; j++) {
  797:             /* we should have a better way of identifying certs than by
  798:              * nickname here */
  799:             CERTCertificate *cert = PK11_FindCertFromNickname(
  800:                                         options->vreader[i].cert_name[j],
  801:                                         NULL);
  802:             if (cert == NULL) {
  803:                 continue;
  804:             }
  805:             certs[cert_count] = cert->derCert.data;
  806:             cert_len[cert_count] = cert->derCert.len;
  807:             keys[cert_count] = vcard_emul_make_key(slot, cert);
  808:             /* this is safe because the key is still holding a cert reference */
  809:             CERT_DestroyCertificate(cert);
  810:             cert_count++;
  811:         }
  812:         if (cert_count) {
  813:             VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
  814:                                                 keys, cert_count);
  815:             vreader_insert_card(vreader, vcard);
  816:             vcard_emul_init_series(vreader, vcard);
  817:             /* allow insertion and removal of soft cards */
  818:             vreader_emul->saved_vcard = vcard_reference(vcard);
  819:             vcard_free(vcard);
  820:             vreader_free(vreader);
  821:             has_readers = PR_TRUE;
  822:         }
  823:     }
  824: 
  825:     /* if we aren't suppose to use hw, skip looking up hardware tokens */
  826:     if (!options->use_hw) {
  827:         nss_emul_init = has_readers;
  828:         return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
  829:     }
  830: 
  831:     /* make sure we have some PKCS #11 module loaded */
  832:     module_lock = SECMOD_GetDefaultModuleListLock();
  833:     module_list = SECMOD_GetDefaultModuleList();
  834:     need_coolkey_module = !has_readers;
  835:     SECMOD_GetReadLock(module_lock);
  836:     for (mlp = module_list; mlp; mlp = mlp->next) {
  837:         SECMODModule *module = mlp->module;
  838:         if (module_has_removable_hw_slots(module)) {
  839:             need_coolkey_module = PR_FALSE;
  840:             break;
  841:         }
  842:     }
  843:     SECMOD_ReleaseReadLock(module_lock);
  844: 
  845:     if (need_coolkey_module) {
  846:         SECMODModule *module;
  847:         module = SECMOD_LoadUserModule(
  848:                     (char *)"library=libcoolkeypk11.so name=Coolkey",
  849:                     NULL, PR_FALSE);
  850:         if (module == NULL) {
  851:             return VCARD_EMUL_FAIL;
  852:         }
  853:         SECMOD_DestroyModule(module); /* free our reference, Module will still
  854:                                        * be on the list.
  855:                                        * until we destroy it */
  856:     }
  857: 
  858:     /* now examine all the slots, finding which should be readers */
  859:     /* We should control this with options. For now we mirror out any
  860:      * removable hardware slot */
  861:     default_card_type = options->hw_card_type;
  862:     default_type_params = strdup(options->hw_type_params);
  863: 
  864:     SECMOD_GetReadLock(module_lock);
  865:     for (mlp = module_list; mlp; mlp = mlp->next) {
  866:         SECMODModule *module = mlp->module;
  867:         PRBool has_emul_slots = PR_FALSE;
  868: 
  869:         if (module == NULL) {
  870:                 continue;
  871:         }
  872: 
  873:         for (i = 0; i < module->slotCount; i++) {
  874:             PK11SlotInfo *slot = module->slots[i];
  875: 
  876:             /* only map removable HW slots */
  877:             if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
  878:                 continue;
  879:             }
  880:             vreader_emul = vreader_emul_new(slot, options->hw_card_type,
  881:                                             options->hw_type_params);
  882:             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
  883:                                   vreader_emul_delete);
  884:             vreader_add_reader(vreader);
  885: 
  886:             has_readers = PR_TRUE;
  887:             has_emul_slots = PR_TRUE;
  888: 
  889:             if (PK11_IsPresent(slot)) {
  890:                 VCard *vcard;
  891:                 vcard = vcard_emul_mirror_card(vreader);
  892:                 vreader_insert_card(vreader, vcard);
  893:                 vcard_emul_init_series(vreader, vcard);
  894:                 vcard_free(vcard);
  895:             }
  896:         }
  897:         if (has_emul_slots) {
  898:             vcard_emul_new_event_thread(module);
  899:         }
  900:     }
  901:     SECMOD_ReleaseReadLock(module_lock);
  902:     nss_emul_init = has_readers;
  903: 
  904:     return VCARD_EMUL_OK;
  905: }
  906: 
  907: /* Recreate card insert events for all readers (user should
  908:  * deduce implied reader insert. perhaps do a reader insert as well?)
  909:  */
  910: void
  911: vcard_emul_replay_insertion_events(void)
  912: {
  913:     VReaderListEntry *current_entry;
  914:     VReaderListEntry *next_entry = NULL;
  915:     VReaderList *list = vreader_get_reader_list();
  916: 
  917:     for (current_entry = vreader_list_get_first(list); current_entry;
  918:             current_entry = next_entry) {
  919:         VReader *vreader = vreader_list_get_reader(current_entry);
  920:         next_entry = vreader_list_get_next(current_entry);
  921:         vreader_queue_card_event(vreader);
  922:     }
  923: }
  924: 
  925: /*
  926:  *  Silly little functions to help parsing our argument string
  927:  */
  928: static char *
  929: copy_string(const char *str, int str_len)
  930: {
  931:     char *new_str;
  932: 
  933:     new_str = qemu_malloc(str_len+1);
  934:     memcpy(new_str, str, str_len);
  935:     new_str[str_len] = 0;
  936:     return new_str;
  937: }
  938: 
  939: static int
  940: count_tokens(const char *str, char token, char token_end)
  941: {
  942:     int count = 0;
  943: 
  944:     for (; *str; str++) {
  945:         if (*str == token) {
  946:             count++;
  947:         }
  948:         if (*str == token_end) {
  949:             break;
  950:         }
  951:     }
  952:     return count;
  953: }
  954: 
  955: static const char *
  956: strip(const char *str)
  957: {
  958:     for (; *str && isspace(*str); str++) {
  959:     }
  960:     return str;
  961: }
  962: 
  963: static const char *
  964: find_blank(const char *str)
  965: {
  966:     for (; *str && !isspace(*str); str++) {
  967:     }
  968:     return str;
  969: }
  970: 
  971: 
  972: /*
  973:  *  We really want to use some existing argument parsing library here. That
  974:  *  would give us a consistent look */
  975: static VCardEmulOptions options;
  976: #define READER_STEP 4
  977: 
  978: VCardEmulOptions *
  979: vcard_emul_options(const char *args)
  980: {
  981:     int reader_count = 0;
  982:     VCardEmulOptions *opts;
  983:     char type_str[100];
  984:     int type_len;
  985: 
  986:     /* Allow the future use of allocating the options structure on the fly */
  987:     memcpy(&options, &default_options, sizeof(options));
  988:     opts = &options;
  989: 
  990:     do {
  991:         args = strip(args); /* strip off the leading spaces */
  992:         if (*args == ',') {
  993:             continue;
  994:         }
  995:         /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
  996:          *       cert_2,cert_3...) */
  997:         if (strncmp(args, "soft=", 5) == 0) {
  998:             const char *name;
  999:             const char *vname;
 1000:             const char *type_params;
 1001:             VCardEmulType type;
 1002:             int name_length, vname_length, type_params_length, count, i;
 1003:             VirtualReaderOptions *vreaderOpt = NULL;
 1004: 
 1005:             args = strip(args + 5);
 1006:             if (*args != '(') {
 1007:                 continue;
 1008:             }
 1009:             name = args;
 1010:             args = strpbrk(args + 1, ",)");
 1011:             if (*args == 0) {
 1012:                 break;
 1013:             }
 1014:             if (*args == ')') {
 1015:                 args++;
 1016:                 continue;
 1017:             }
 1018:             args = strip(args+1);
 1019:             name_length = args - name - 2;
 1020:             vname = args;
 1021:             args = strpbrk(args + 1, ",)");
 1022:             if (*args == 0) {
 1023:                 break;
 1024:             }
 1025:             if (*args == ')') {
 1026:                 args++;
 1027:                 continue;
 1028:             }
 1029:             vname_length = args - name - 2;
 1030:             args = strip(args+1);
 1031:             type_len = strpbrk(args, ",)") - args;
 1032:             assert(sizeof(type_str) > type_len);
 1033:             strncpy(type_str, args, type_len);
 1034:             type_str[type_len] = 0;
 1035:             type = vcard_emul_type_from_string(type_str);
 1036:             args = strpbrk(args, ",)");
 1037:             if (*args == 0) {
 1038:                 break;
 1039:             }
 1040:             if (*args == ')') {
 1041:                 args++;
 1042:                 continue;
 1043:             }
 1044:             args = strip(args++);
 1045:             type_params = args;
 1046:             args = strpbrk(args + 1, ",)");
 1047:             if (*args == 0) {
 1048:                 break;
 1049:             }
 1050:             if (*args == ')') {
 1051:                 args++;
 1052:                 continue;
 1053:             }
 1054:             type_params_length = args - name;
 1055:             args = strip(args++);
 1056:             if (*args == 0) {
 1057:                 break;
 1058:             }
 1059: 
 1060:             if (opts->vreader_count >= reader_count) {
 1061:                 reader_count += READER_STEP;
 1062:                 vreaderOpt = realloc(opts->vreader,
 1063:                                 reader_count * sizeof(*vreaderOpt));
 1064:                 if (vreaderOpt == NULL) {
 1065:                     return opts; /* we're done */
 1066:                 }
 1067:             }
 1068:             opts->vreader = vreaderOpt;
 1069:             vreaderOpt = &vreaderOpt[opts->vreader_count];
 1070:             vreaderOpt->name = copy_string(name, name_length);
 1071:             vreaderOpt->vname = copy_string(vname, vname_length);
 1072:             vreaderOpt->card_type = type;
 1073:             vreaderOpt->type_params =
 1074:                 copy_string(type_params, type_params_length);
 1075:             count = count_tokens(args, ',', ')');
 1076:             vreaderOpt->cert_count = count;
 1077:             vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
 1078:             for (i = 0; i < count; i++) {
 1079:                 const char *cert = args + 1;
 1080:                 args = strpbrk(args + 1, ",)");
 1081:                 vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
 1082:             }
 1083:             if (*args == ')') {
 1084:                 args++;
 1085:             }
 1086:             opts->vreader_count++;
 1087:         /* use_hw= */
 1088:         } else if (strncmp(args, "use_hw=", 7) == 0) {
 1089:             args = strip(args+7);
 1090:             if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
 1091:                 opts->use_hw = PR_FALSE;
 1092:             } else {
 1093:                 opts->use_hw = PR_TRUE;
 1094:             }
 1095:             args = find_blank(args);
 1096:         /* hw_type= */
 1097:         } else if (strncmp(args, "hw_type=", 8) == 0) {
 1098:             args = strip(args+8);
 1099:             opts->hw_card_type = vcard_emul_type_from_string(args);
 1100:             args = find_blank(args);
 1101:         /* hw_params= */
 1102:         } else if (strncmp(args, "hw_params=", 10) == 0) {
 1103:             const char *params;
 1104:             args = strip(args+10);
 1105:             params = args;
 1106:             args = find_blank(args);
 1107:             opts->hw_type_params = copy_string(params, args-params);
 1108:         /* db="/data/base/path" */
 1109:         } else if (strncmp(args, "db=", 3) == 0) {
 1110:             const char *db;
 1111:             args = strip(args+3);
 1112:             if (*args != '"') {
 1113:                 continue;
 1114:             }
 1115:             args++;
 1116:             db = args;
 1117:             args = strpbrk(args, "\"\n");
 1118:             opts->nss_db = copy_string(db, args-db);
 1119:             if (*args != 0) {
 1120:                 args++;
 1121:             }
 1122:         } else {
 1123:             args = find_blank(args);
 1124:         }
 1125:     } while (*args != 0);
 1126: 
 1127:     return opts;
 1128: }
 1129: 
 1130: void
 1131: vcard_emul_usage(void)
 1132: {
 1133:    fprintf(stderr,
 1134: "emul args: comma separated list of the following arguments\n"
 1135: " db={nss_database}               (default sql:/etc/pki/nssdb)\n"
 1136: " use_hw=[yes|no]                 (default yes)\n"
 1137: " hw_type={card_type_to_emulate}  (default CAC)\n"
 1138: " hw_param={param_for_card}       (default \"\")\n"
 1139: " soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
 1140: "       {cert1},{cert2},{cert3}    (default none)\n"
 1141: "\n"
 1142: "  {nss_database}          The location of the NSS cert & key database\n"
 1143: "  {card_type_to_emulate}  What card interface to present to the guest\n"
 1144: "  {param_for_card}        Card interface specific parameters\n"
 1145: "  {slot_name}             NSS slot that contains the certs\n"
 1146: "  {vreader_name}          Virutal reader name to present to the guest\n"
 1147: "  {certN}                 Nickname of the certificate n on the virtual card\n"
 1148: "\n"
 1149: "These parameters come as a single string separated by blanks or newlines."
 1150: "\n"
 1151: "Unless use_hw is set to no, all tokens that look like removable hardware\n"
 1152: "tokens will be presented to the guest using the emulator specified by\n"
 1153: "hw_type, and parameters of hw_param.\n"
 1154: "\n"
 1155: "If more one or more soft= parameters are specified, these readers will be\n"
 1156: "presented to the guest\n");
 1157: }

unix.superglobalmegacorp.com