Statistics
| Branch: | Revision:

root / libcacard / vcard_emul_nss.c @ d246b3cf

History | View | Annotate | Download (37.4 kB)

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
typedef enum {
37
    VCardEmulUnknown = -1,
38
    VCardEmulFalse = 0,
39
    VCardEmulTrue = 1
40
} VCardEmulTriState;
41

    
42
struct VCardKeyStruct {
43
    CERTCertificate *cert;
44
    PK11SlotInfo *slot;
45
    SECKEYPrivateKey *key;
46
    VCardEmulTriState failedX509;
47
};
48

    
49

    
50
typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
51

    
52
struct VReaderEmulStruct {
53
    PK11SlotInfo *slot;
54
    VCardEmulType default_type;
55
    char *type_params;
56
    PRBool present;
57
    int     series;
58
    VCard *saved_vcard;
59
};
60

    
61
/*
62
 *  NSS Specific options
63
 */
64
struct VirtualReaderOptionsStruct {
65
    char *name;
66
    char *vname;
67
    VCardEmulType card_type;
68
    char *type_params;
69
    char **cert_name;
70
    int cert_count;
71
};
72

    
73
struct VCardEmulOptionsStruct {
74
    void *nss_db;
75
    VirtualReaderOptions *vreader;
76
    int vreader_count;
77
    VCardEmulType hw_card_type;
78
    const char *hw_type_params;
79
    PRBool use_hw;
80
};
81

    
82
static int nss_emul_init;
83

    
84
/* if we have more that just the slot, define
85
 * VCardEmulStruct here */
86

    
87
/*
88
 * allocate the set of arrays for certs, cert_len, key
89
 */
90
static PRBool
91
vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
92
                        VCardKey ***keysp, int cert_count)
93
{
94
    *certsp = NULL;
95
    *cert_lenp = NULL;
96
    *keysp = NULL;
97
    *certsp = (unsigned char **)qemu_malloc(sizeof(unsigned char *)*cert_count);
98
    *cert_lenp = (int *)qemu_malloc(sizeof(int)*cert_count);
99
    *keysp = (VCardKey **)qemu_malloc(sizeof(VCardKey *)*cert_count);
100
    return PR_TRUE;
101
}
102

    
103
/*
104
 * Emulator specific card information
105
 */
106
typedef struct CardEmulCardStruct CardEmulPrivate;
107

    
108
static VCardEmul *
109
vcard_emul_new_card(PK11SlotInfo *slot)
110
{
111
    PK11_ReferenceSlot(slot);
112
    /* currently we don't need anything other than the slot */
113
    return (VCardEmul *)slot;
114
}
115

    
116
static void
117
vcard_emul_delete_card(VCardEmul *vcard_emul)
118
{
119
    PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
120
    if (slot == NULL) {
121
        return;
122
    }
123
    PK11_FreeSlot(slot);
124
}
125

    
126
static PK11SlotInfo *
127
vcard_emul_card_get_slot(VCard *card)
128
{
129
    /* note, the card is holding the reference, no need to get another one */
130
    return (PK11SlotInfo *)vcard_get_private(card);
131
}
132

    
133

    
134
/*
135
 * key functions
136
 */
137
/* private constructure */
138
static VCardKey *
139
vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
140
{
141
    VCardKey *key;
142

    
143
    key = (VCardKey *)qemu_malloc(sizeof(VCardKey));
144
    key->slot = PK11_ReferenceSlot(slot);
145
    key->cert = CERT_DupCertificate(cert);
146
    /* NOTE: if we aren't logged into the token, this could return NULL */
147
    /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
148
     * use the DER version of this function */
149
    key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
150
    key->failedX509 = VCardEmulUnknown;
151
    return key;
152
}
153

    
154
/* destructor */
155
void
156
vcard_emul_delete_key(VCardKey *key)
157
{
158
    if (!nss_emul_init || (key == NULL)) {
159
        return;
160
    }
161
    if (key->key) {
162
        SECKEY_DestroyPrivateKey(key->key);
163
        key->key = NULL;
164
    }
165
    if (key->cert) {
166
        CERT_DestroyCertificate(key->cert);
167
    }
168
    if (key->slot) {
169
        PK11_FreeSlot(key->slot);
170
    }
171
    return;
172
}
173

    
174
/*
175
 * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
176
 */
177
static SECKEYPrivateKey *
178
vcard_emul_get_nss_key(VCardKey *key)
179
{
180
    if (key->key) {
181
        return key->key;
182
    }
183
    /* NOTE: if we aren't logged into the token, this could return NULL */
184
    key->key = PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
185
    return key->key;
186
}
187

    
188
/*
189
 * Map NSS errors to 7816 errors
190
 */
191
static vcard_7816_status_t
192
vcard_emul_map_error(int error)
193
{
194
    switch (error) {
195
    case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
196
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
197
    case SEC_ERROR_BAD_DATA:
198
    case SEC_ERROR_OUTPUT_LEN:
199
    case SEC_ERROR_INPUT_LEN:
200
    case SEC_ERROR_INVALID_ARGS:
201
    case SEC_ERROR_INVALID_ALGORITHM:
202
    case SEC_ERROR_NO_KEY:
203
    case SEC_ERROR_INVALID_KEY:
204
    case SEC_ERROR_DECRYPTION_DISALLOWED:
205
        return VCARD7816_STATUS_ERROR_DATA_INVALID;
206
    case SEC_ERROR_NO_MEMORY:
207
        return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
208
    }
209
    return VCARD7816_STATUS_EXC_ERROR_CHANGE;
210
}
211

    
212
/* RSA sign/decrypt with the key, signature happens 'in place' */
213
vcard_7816_status_t
214
vcard_emul_rsa_op(VCard *card, VCardKey *key,
215
                  unsigned char *buffer, int buffer_size)
216
{
217
    SECKEYPrivateKey *priv_key;
218
    unsigned signature_len;
219
    PK11SlotInfo *slot;
220
    SECStatus rv;
221
    unsigned char buf[2048];
222
    unsigned char *bp = NULL;
223
    int pad_len;
224
    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
225

    
226
    if ((!nss_emul_init) || (key == NULL)) {
227
        /* couldn't get the key, indicate that we aren't logged in */
228
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
229
    }
230
    priv_key = vcard_emul_get_nss_key(key);
231
    if (priv_key == NULL) {
232
        /* couldn't get the key, indicate that we aren't logged in */
233
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
234
    }
235
    slot = vcard_emul_card_get_slot(card);
236

    
237
    /*
238
     * this is only true of the rsa signature
239
     */
240
    signature_len = PK11_SignatureLen(priv_key);
241
    if (buffer_size != signature_len) {
242
        return  VCARD7816_STATUS_ERROR_DATA_INVALID;
243
    }
244
    /* be able to handle larger keys if necessariy */
245
    bp = &buf[0];
246
    if (sizeof(buf) < signature_len) {
247
        bp = qemu_malloc(signature_len);
248
    }
249

    
250
    /*
251
     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
252
     * choke when they try to do the actual operations. Try to detect
253
     * those cases and treat them as if the token didn't claim support for
254
     * X_509.
255
     */
256
    if (key->failedX509 != VCardEmulTrue
257
                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
258
        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
259
                                 buffer, buffer_size);
260
        if (rv == SECSuccess) {
261
            assert(buffer_size == signature_len);
262
            memcpy(buffer, bp, signature_len);
263
            key->failedX509 = VCardEmulFalse;
264
            goto cleanup;
265
        }
266
        /*
267
         * we've had a successful X509 operation, this failure must be
268
         * somethine else
269
         */
270
        if (key->failedX509 == VCardEmulFalse) {
271
            ret = vcard_emul_map_error(PORT_GetError());
272
            goto cleanup;
273
        }
274
        /*
275
         * key->failedX509 must be Unknown at this point, try the
276
         * non-x_509 case
277
         */
278
    }
279
    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
280
    /* is this a PKCS #1 formatted signature? */
281
    if ((buffer[0] == 0) && (buffer[1] == 1)) {
282
        int i;
283

    
284
        for (i = 2; i < buffer_size; i++) {
285
            /* rsa signature pad */
286
            if (buffer[i] != 0xff) {
287
                break;
288
            }
289
        }
290
        if ((i < buffer_size) && (buffer[i] == 0)) {
291
            /* yes, we have a properly formated PKCS #1 signature */
292
            /*
293
             * NOTE: even if we accidentally got an encrypt buffer, which
294
             * through shear luck started with 00, 01, ff, 00, it won't matter
295
             * because the resulting Sign operation will effectively decrypt
296
             * the real buffer.
297
             */
298
            SECItem signature;
299
            SECItem hash;
300

    
301
            i++;
302
            hash.data = &buffer[i];
303
            hash.len = buffer_size - i;
304
            signature.data = bp;
305
            signature.len = signature_len;
306
            rv = PK11_Sign(priv_key,  &signature, &hash);
307
            if (rv != SECSuccess) {
308
                ret = vcard_emul_map_error(PORT_GetError());
309
                goto cleanup;
310
            }
311
            assert(buffer_size == signature.len);
312
            memcpy(buffer, bp, signature.len);
313
            /*
314
             * we got here because either the X509 attempt failed, or the
315
             * token couldn't do the X509 operation, in either case stay
316
             * with the PKCS version for future operations on this key
317
             */
318
            key->failedX509 = VCardEmulTrue;
319
            goto cleanup;
320
        }
321
    }
322
    pad_len = buffer_size - signature_len;
323
    assert(pad_len < 4);
324
    /*
325
     * OK now we've decrypted the payload, package it up in PKCS #1 for the
326
     * upper layer.
327
     */
328
    buffer[0] = 0;
329
    buffer[1] = 2; /* RSA_encrypt  */
330
    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
331
    /*
332
     * padding for PKCS #1 encrypted data is a string of random bytes. The
333
     * random butes protect against potential decryption attacks against RSA.
334
     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
335
     * them. This shouldn't matter to the upper level code which should just
336
     * strip this code out anyway, so We'll pad with a constant 3.
337
     */
338
    memset(&buffer[2], 0x03, pad_len);
339
    pad_len += 2; /* index to the end of the pad */
340
    buffer[pad_len] = 0;
341
    pad_len++; /* index to the start of the data */
342
    memcpy(&buffer[pad_len], bp, signature_len);
343
    /*
344
     * we got here because either the X509 attempt failed, or the
345
     * token couldn't do the X509 operation, in either case stay
346
     * with the PKCS version for future operations on this key
347
     */
348
    key->failedX509 = VCardEmulTrue;
349
cleanup:
350
    if (bp != buf) {
351
        qemu_free(bp);
352
    }
353
    return ret;
354
}
355

    
356
/*
357
 * Login functions
358
 */
359
/* return the number of login attempts still possible on the card. if unknown,
360
 * return -1 */
361
int
362
vcard_emul_get_login_count(VCard *card)
363
{
364
    return -1;
365
}
366

    
367
/* login into the card, return the 7816 status word (sw2 || sw1) */
368
vcard_7816_status_t
369
vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
370
{
371
    PK11SlotInfo *slot;
372
    unsigned char *pin_string = NULL;
373
    int i;
374
    SECStatus rv;
375

    
376
    if (!nss_emul_init) {
377
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
378
    }
379
    slot = vcard_emul_card_get_slot(card);
380
     /* We depend on the PKCS #11 module internal login state here because we
381
      * create a separate process to handle each guest instance. If we needed
382
      * to handle multiple guests from one process, then we would need to keep
383
      * a lot of extra state in our card structure
384
      * */
385
    pin_string = qemu_malloc(pin_len+1);
386
    memcpy(pin_string, pin, pin_len);
387
    pin_string[pin_len] = 0;
388

    
389
    /* handle CAC expanded pins correctly */
390
    for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
391
        pin_string[i] = 0;
392
    }
393

    
394
    rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
395
    memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
396
                                        to be snooped */
397
    qemu_free(pin_string);
398
    if (rv == SECSuccess) {
399
        return VCARD7816_STATUS_SUCCESS;
400
    }
401
    /* map the error from port get error */
402
    return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
403
}
404

    
405
void
406
vcard_emul_reset(VCard *card, VCardPower power)
407
{
408
    PK11SlotInfo *slot;
409

    
410
    if (!nss_emul_init) {
411
        return;
412
    }
413

    
414
    /*
415
     * if we reset the card (either power on or power off), we lose our login
416
     * state
417
     */
418
    /* TODO: we may also need to send insertion/removal events? */
419
    slot = vcard_emul_card_get_slot(card);
420
    PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
421
    return;
422
}
423

    
424

    
425
static VReader *
426
vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
427
{
428
    VReaderList *reader_list = vreader_get_reader_list();
429
    VReaderListEntry *current_entry = NULL;
430

    
431
    if (reader_list == NULL) {
432
        return NULL;
433
    }
434
    for (current_entry = vreader_list_get_first(reader_list); current_entry;
435
                        current_entry = vreader_list_get_next(current_entry)) {
436
        VReader *reader = vreader_list_get_reader(current_entry);
437
        VReaderEmul *reader_emul = vreader_get_private(reader);
438
        if (reader_emul->slot == slot) {
439
            return reader;
440
        }
441
        vreader_free(reader);
442
    }
443

    
444
    return NULL;
445
}
446

    
447
/*
448
 * create a new reader emul
449
 */
450
static VReaderEmul *
451
vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
452
{
453
    VReaderEmul *new_reader_emul;
454

    
455
    new_reader_emul = (VReaderEmul *)qemu_malloc(sizeof(VReaderEmul));
456

    
457
    new_reader_emul->slot = PK11_ReferenceSlot(slot);
458
    new_reader_emul->default_type = type;
459
    new_reader_emul->type_params = strdup(params);
460
    new_reader_emul->present = PR_FALSE;
461
    new_reader_emul->series = 0;
462
    new_reader_emul->saved_vcard = NULL;
463
    return new_reader_emul;
464
}
465

    
466
static void
467
vreader_emul_delete(VReaderEmul *vreader_emul)
468
{
469
    if (vreader_emul == NULL) {
470
        return;
471
    }
472
    if (vreader_emul->slot) {
473
        PK11_FreeSlot(vreader_emul->slot);
474
    }
475
    if (vreader_emul->type_params) {
476
        qemu_free(vreader_emul->type_params);
477
    }
478
    qemu_free(vreader_emul);
479
}
480

    
481
/*
482
 *  TODO: move this to emulater non-specific file
483
 */
484
static VCardEmulType
485
vcard_emul_get_type(VReader *vreader)
486
{
487
    VReaderEmul *vreader_emul;
488

    
489
    vreader_emul = vreader_get_private(vreader);
490
    if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
491
        return vreader_emul->default_type;
492
    }
493

    
494
    return vcard_emul_type_select(vreader);
495
}
496
/*
497
 *  TODO: move this to emulater non-specific file
498
 */
499
static const char *
500
vcard_emul_get_type_params(VReader *vreader)
501
{
502
    VReaderEmul *vreader_emul;
503

    
504
    vreader_emul = vreader_get_private(vreader);
505
    if (vreader_emul && vreader_emul->type_params) {
506
        return vreader_emul->type_params;
507
    }
508

    
509
    return "";
510
}
511

    
512
/* pull the slot out of the reader private data */
513
static PK11SlotInfo *
514
vcard_emul_reader_get_slot(VReader *vreader)
515
{
516
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
517
    if (vreader_emul == NULL) {
518
        return NULL;
519
    }
520
    return vreader_emul->slot;
521
}
522

    
523
/*
524
 *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
525
 *  historical bytes for any software emulated card. The remaining bytes can be
526
 *  used to indicate the actual emulator
527
 */
528
static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
529

    
530
void
531
vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
532
{
533
    int len = MIN(sizeof(nss_atr), *atr_len);
534
    assert(atr != NULL);
535

    
536
    memcpy(atr, nss_atr, len);
537
    *atr_len = len;
538
    return;
539
}
540

    
541
/*
542
 * create a new card from certs and keys
543
 */
544
static VCard *
545
vcard_emul_make_card(VReader *reader,
546
                     unsigned char * const *certs, int *cert_len,
547
                     VCardKey *keys[], int cert_count)
548
{
549
    VCardEmul *vcard_emul;
550
    VCard *vcard;
551
    PK11SlotInfo *slot;
552
    VCardEmulType type;
553
    const char *params;
554

    
555
    type = vcard_emul_get_type(reader);
556

    
557
    /* ignore the inserted card */
558
    if (type == VCARD_EMUL_NONE) {
559
        return NULL;
560
    }
561
    slot = vcard_emul_reader_get_slot(reader);
562
    if (slot == NULL) {
563
        return NULL;
564
    }
565

    
566
    params = vcard_emul_get_type_params(reader);
567
    /* params these can be NULL */
568

    
569
    vcard_emul = vcard_emul_new_card(slot);
570
    if (vcard_emul == NULL) {
571
        return NULL;
572
    }
573
    vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
574
    if (vcard == NULL) {
575
        vcard_emul_delete_card(vcard_emul);
576
        return NULL;
577
    }
578
    vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
579
    return vcard;
580
}
581

    
582

    
583
/*
584
 * 'clone' a physical card as a virtual card
585
 */
586
static VCard *
587
vcard_emul_mirror_card(VReader *vreader)
588
{
589
    /*
590
     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
591
     * us the real certs until we log in.
592
     */
593
    PK11GenericObject *firstObj, *thisObj;
594
    int cert_count;
595
    unsigned char **certs;
596
    int *cert_len;
597
    VCardKey **keys;
598
    PK11SlotInfo *slot;
599
    PRBool ret;
600
    VCard *card;
601

    
602
    slot = vcard_emul_reader_get_slot(vreader);
603
    if (slot == NULL) {
604
        return NULL;
605
    }
606

    
607
    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
608
    if (firstObj == NULL) {
609
        return NULL;
610
    }
611

    
612
    /* count the certs */
613
    cert_count = 0;
614
    for (thisObj = firstObj; thisObj;
615
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
616
        cert_count++;
617
    }
618

    
619
    if (cert_count == 0) {
620
        PK11_DestroyGenericObjects(firstObj);
621
        return NULL;
622
    }
623

    
624
    /* allocate the arrays */
625
    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
626
    if (ret == PR_FALSE) {
627
        return NULL;
628
    }
629

    
630
    /* fill in the arrays */
631
    cert_count = 0;
632
    for (thisObj = firstObj; thisObj;
633
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
634
        SECItem derCert;
635
        CERTCertificate *cert;
636
        SECStatus rv;
637

    
638
        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
639
                                   CKA_VALUE, &derCert);
640
        if (rv != SECSuccess) {
641
            continue;
642
        }
643
        /* create floating temp cert. This gives us a cert structure even if
644
         * the token isn't logged in */
645
        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
646
                                       NULL, PR_FALSE, PR_TRUE);
647
        SECITEM_FreeItem(&derCert, PR_FALSE);
648
        if (cert == NULL) {
649
            continue;
650
        }
651

    
652
        certs[cert_count] = cert->derCert.data;
653
        cert_len[cert_count] = cert->derCert.len;
654
        keys[cert_count] = vcard_emul_make_key(slot, cert);
655
        cert_count++;
656
        CERT_DestroyCertificate(cert); /* key obj still has a reference */
657
    }
658

    
659
    /* now create the card */
660
    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
661
    qemu_free(certs);
662
    qemu_free(cert_len);
663
    qemu_free(keys);
664

    
665
    return card;
666
}
667

    
668
static VCardEmulType default_card_type = VCARD_EMUL_NONE;
669
static const char *default_type_params = "";
670

    
671
/*
672
 * This thread looks for card and reader insertions and puts events on the
673
 * event queue
674
 */
675
static void
676
vcard_emul_event_thread(void *arg)
677
{
678
    PK11SlotInfo *slot;
679
    VReader *vreader;
680
    VReaderEmul *vreader_emul;
681
    VCard *vcard;
682
    SECMODModule *module = (SECMODModule *)arg;
683

    
684
    do {
685
        slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
686
        if (slot == NULL) {
687
            break;
688
        }
689
        vreader = vcard_emul_find_vreader_from_slot(slot);
690
        if (vreader == NULL) {
691
            /* new vreader */
692
            vreader_emul = vreader_emul_new(slot, default_card_type,
693
                                            default_type_params);
694
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
695
                                  vreader_emul_delete);
696
            PK11_FreeSlot(slot);
697
            slot = NULL;
698
            vreader_add_reader(vreader);
699
            vreader_free(vreader);
700
            continue;
701
        }
702
        /* card remove/insert */
703
        vreader_emul = vreader_get_private(vreader);
704
        if (PK11_IsPresent(slot)) {
705
            int series = PK11_GetSlotSeries(slot);
706
            if (series != vreader_emul->series) {
707
                if (vreader_emul->present) {
708
                    vreader_insert_card(vreader, NULL);
709
                }
710
                vcard = vcard_emul_mirror_card(vreader);
711
                vreader_insert_card(vreader, vcard);
712
                vcard_free(vcard);
713
            }
714
            vreader_emul->series = series;
715
            vreader_emul->present = 1;
716
            vreader_free(vreader);
717
            PK11_FreeSlot(slot);
718
            continue;
719
        }
720
        if (vreader_emul->present) {
721
            vreader_insert_card(vreader, NULL);
722
        }
723
        vreader_emul->series = 0;
724
        vreader_emul->present = 0;
725
        PK11_FreeSlot(slot);
726
        vreader_free(vreader);
727
    } while (1);
728
}
729

    
730
/* if the card is inserted when we start up, make sure our state is correct */
731
static void
732
vcard_emul_init_series(VReader *vreader, VCard *vcard)
733
{
734
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
735
    PK11SlotInfo *slot = vreader_emul->slot;
736

    
737
    vreader_emul->present = PK11_IsPresent(slot);
738
    vreader_emul->series = PK11_GetSlotSeries(slot);
739
    if (vreader_emul->present == 0) {
740
        vreader_insert_card(vreader, NULL);
741
    }
742
}
743

    
744
/*
745
 * each module has a separate wait call, create a thread for each module that
746
 * we are using.
747
 */
748
static void
749
vcard_emul_new_event_thread(SECMODModule *module)
750
{
751
    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
752
                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
753
                     PR_UNJOINABLE_THREAD, 0);
754
}
755

    
756
static const VCardEmulOptions default_options = {
757
    .nss_db = NULL,
758
    .vreader = NULL,
759
    .vreader_count = 0,
760
    .hw_card_type = VCARD_EMUL_CAC,
761
    .hw_type_params = "",
762
    .use_hw = PR_TRUE
763
};
764

    
765

    
766
/*
767
 *  NSS needs the app to supply a password prompt. In our case the only time
768
 *  the password is supplied is as part of the Login APDU. The actual password
769
 *  is passed in the pw_arg in that case. In all other cases pw_arg should be
770
 *  NULL.
771
 */
772
static char *
773
vcard_emul_get_password(PK11SlotInfo *slot, PRBool retries, void *pw_arg)
774
{
775
    /* if it didn't work the first time, don't keep trying */
776
    if (retries) {
777
        return NULL;
778
    }
779
    /* we are looking up a password when we don't have one in hand */
780
    if (pw_arg == NULL) {
781
        return NULL;
782
    }
783
    /* TODO: we really should verify that were are using the right slot */
784
    return PORT_Strdup(pw_arg);
785
}
786

    
787
/* Force a card removal even if the card is not physically removed */
788
VCardEmulError
789
vcard_emul_force_card_remove(VReader *vreader)
790
{
791
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
792
        return VCARD_EMUL_FAIL; /* card is already removed */
793
    }
794

    
795
    /* OK, remove it */
796
    vreader_insert_card(vreader, NULL);
797
    return VCARD_EMUL_OK;
798
}
799

    
800
/* Re-insert of a card that has been removed by force removal */
801
VCardEmulError
802
vcard_emul_force_card_insert(VReader *vreader)
803
{
804
    VReaderEmul *vreader_emul;
805
    VCard *vcard;
806

    
807
    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
808
        return VCARD_EMUL_FAIL; /* card is already removed */
809
    }
810
    vreader_emul = vreader_get_private(vreader);
811

    
812
    /* if it's a softcard, get the saved vcard from the reader emul structure */
813
    if (vreader_emul->saved_vcard) {
814
        vcard = vcard_reference(vreader_emul->saved_vcard);
815
    } else {
816
        /* it must be a physical card, rebuild it */
817
        if (!PK11_IsPresent(vreader_emul->slot)) {
818
            /* physical card has been removed, not way to reinsert it */
819
            return VCARD_EMUL_FAIL;
820
        }
821
        vcard = vcard_emul_mirror_card(vreader);
822
    }
823
    vreader_insert_card(vreader, vcard);
824
    vcard_free(vcard);
825

    
826
    return VCARD_EMUL_OK;
827
}
828

    
829

    
830
static PRBool
831
module_has_removable_hw_slots(SECMODModule *mod)
832
{
833
    int i;
834
    PRBool ret = PR_FALSE;
835
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
836

    
837
    if (!moduleLock) {
838
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
839
        return ret;
840
    }
841
    SECMOD_GetReadLock(moduleLock);
842
    for (i = 0; i < mod->slotCount; i++) {
843
        PK11SlotInfo *slot = mod->slots[i];
844
        if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
845
            ret = PR_TRUE;
846
            break;
847
        }
848
    }
849
    SECMOD_ReleaseReadLock(moduleLock);
850
    return ret;
851
}
852

    
853
/* Previously we returned FAIL if no readers found. This makes
854
 * no sense when using hardware, since there may be no readers connected
855
 * at the time vcard_emul_init is called, but they will be properly
856
 * recognized later. So Instead return FAIL only if no_hw==1 and no
857
 * vcards can be created (indicates error with certificates provided
858
 * or db), or if any other higher level error (NSS error, missing coolkey). */
859
static int vcard_emul_init_called;
860

    
861
VCardEmulError
862
vcard_emul_init(const VCardEmulOptions *options)
863
{
864
    SECStatus rv;
865
    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
866
    VReader *vreader;
867
    VReaderEmul *vreader_emul;
868
    SECMODListLock *module_lock;
869
    SECMODModuleList *module_list;
870
    SECMODModuleList *mlp;
871
    int i;
872

    
873
    if (vcard_emul_init_called) {
874
        return VCARD_EMUL_INIT_ALREADY_INITED;
875
    }
876
    vcard_emul_init_called = 1;
877
    vreader_init();
878
    vevent_queue_init();
879

    
880
    if (options == NULL) {
881
        options = &default_options;
882
    }
883

    
884
    /* first initialize NSS */
885
    if (options->nss_db) {
886
        rv = NSS_Init(options->nss_db);
887
    } else {
888
        rv = NSS_Init("sql:/etc/pki/nssdb");
889
    }
890
    if (rv != SECSuccess) {
891
        return VCARD_EMUL_FAIL;
892
    }
893
    /* Set password callback function */
894
    PK11_SetPasswordFunc(vcard_emul_get_password);
895

    
896
    /* set up soft cards emulated by software certs rather than physical cards
897
     * */
898
    for (i = 0; i < options->vreader_count; i++) {
899
        int j;
900
        int cert_count;
901
        unsigned char **certs;
902
        int *cert_len;
903
        VCardKey **keys;
904
        PK11SlotInfo *slot;
905

    
906
        slot = PK11_FindSlotByName(options->vreader[i].name);
907
        if (slot == NULL) {
908
            continue;
909
        }
910
        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
911
                                        options->vreader[i].type_params);
912
        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
913
                              vreader_emul_delete);
914
        vreader_add_reader(vreader);
915
        cert_count = options->vreader[i].cert_count;
916

    
917
        ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
918
                                      options->vreader[i].cert_count);
919
        if (ret == PR_FALSE) {
920
            continue;
921
        }
922
        cert_count = 0;
923
        for (j = 0; j < options->vreader[i].cert_count; j++) {
924
            /* we should have a better way of identifying certs than by
925
             * nickname here */
926
            CERTCertificate *cert = PK11_FindCertFromNickname(
927
                                        options->vreader[i].cert_name[j],
928
                                        NULL);
929
            if (cert == NULL) {
930
                continue;
931
            }
932
            certs[cert_count] = cert->derCert.data;
933
            cert_len[cert_count] = cert->derCert.len;
934
            keys[cert_count] = vcard_emul_make_key(slot, cert);
935
            /* this is safe because the key is still holding a cert reference */
936
            CERT_DestroyCertificate(cert);
937
            cert_count++;
938
        }
939
        if (cert_count) {
940
            VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
941
                                                keys, cert_count);
942
            vreader_insert_card(vreader, vcard);
943
            vcard_emul_init_series(vreader, vcard);
944
            /* allow insertion and removal of soft cards */
945
            vreader_emul->saved_vcard = vcard_reference(vcard);
946
            vcard_free(vcard);
947
            vreader_free(vreader);
948
            has_readers = PR_TRUE;
949
        }
950
        qemu_free(certs);
951
        qemu_free(cert_len);
952
        qemu_free(keys);
953
    }
954

    
955
    /* if we aren't suppose to use hw, skip looking up hardware tokens */
956
    if (!options->use_hw) {
957
        nss_emul_init = has_readers;
958
        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
959
    }
960

    
961
    /* make sure we have some PKCS #11 module loaded */
962
    module_lock = SECMOD_GetDefaultModuleListLock();
963
    module_list = SECMOD_GetDefaultModuleList();
964
    need_coolkey_module = !has_readers;
965
    SECMOD_GetReadLock(module_lock);
966
    for (mlp = module_list; mlp; mlp = mlp->next) {
967
        SECMODModule *module = mlp->module;
968
        if (module_has_removable_hw_slots(module)) {
969
            need_coolkey_module = PR_FALSE;
970
            break;
971
        }
972
    }
973
    SECMOD_ReleaseReadLock(module_lock);
974

    
975
    if (need_coolkey_module) {
976
        SECMODModule *module;
977
        module = SECMOD_LoadUserModule(
978
                    (char *)"library=libcoolkeypk11.so name=Coolkey",
979
                    NULL, PR_FALSE);
980
        if (module == NULL) {
981
            return VCARD_EMUL_FAIL;
982
        }
983
        SECMOD_DestroyModule(module); /* free our reference, Module will still
984
                                       * be on the list.
985
                                       * until we destroy it */
986
    }
987

    
988
    /* now examine all the slots, finding which should be readers */
989
    /* We should control this with options. For now we mirror out any
990
     * removable hardware slot */
991
    default_card_type = options->hw_card_type;
992
    default_type_params = strdup(options->hw_type_params);
993

    
994
    SECMOD_GetReadLock(module_lock);
995
    for (mlp = module_list; mlp; mlp = mlp->next) {
996
        SECMODModule *module = mlp->module;
997
        PRBool has_emul_slots = PR_FALSE;
998

    
999
        if (module == NULL) {
1000
                continue;
1001
        }
1002

    
1003
        for (i = 0; i < module->slotCount; i++) {
1004
            PK11SlotInfo *slot = module->slots[i];
1005

    
1006
            /* only map removable HW slots */
1007
            if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
1008
                continue;
1009
            }
1010
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
1011
                                            options->hw_type_params);
1012
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
1013
                                  vreader_emul_delete);
1014
            vreader_add_reader(vreader);
1015

    
1016
            has_readers = PR_TRUE;
1017
            has_emul_slots = PR_TRUE;
1018

    
1019
            if (PK11_IsPresent(slot)) {
1020
                VCard *vcard;
1021
                vcard = vcard_emul_mirror_card(vreader);
1022
                vreader_insert_card(vreader, vcard);
1023
                vcard_emul_init_series(vreader, vcard);
1024
                vcard_free(vcard);
1025
            }
1026
        }
1027
        if (has_emul_slots) {
1028
            vcard_emul_new_event_thread(module);
1029
        }
1030
    }
1031
    SECMOD_ReleaseReadLock(module_lock);
1032
    nss_emul_init = has_readers;
1033

    
1034
    return VCARD_EMUL_OK;
1035
}
1036

    
1037
/* Recreate card insert events for all readers (user should
1038
 * deduce implied reader insert. perhaps do a reader insert as well?)
1039
 */
1040
void
1041
vcard_emul_replay_insertion_events(void)
1042
{
1043
    VReaderListEntry *current_entry;
1044
    VReaderListEntry *next_entry = NULL;
1045
    VReaderList *list = vreader_get_reader_list();
1046

    
1047
    for (current_entry = vreader_list_get_first(list); current_entry;
1048
            current_entry = next_entry) {
1049
        VReader *vreader = vreader_list_get_reader(current_entry);
1050
        next_entry = vreader_list_get_next(current_entry);
1051
        vreader_queue_card_event(vreader);
1052
    }
1053
}
1054

    
1055
/*
1056
 *  Silly little functions to help parsing our argument string
1057
 */
1058
static char *
1059
copy_string(const char *str, int str_len)
1060
{
1061
    char *new_str;
1062

    
1063
    new_str = qemu_malloc(str_len+1);
1064
    memcpy(new_str, str, str_len);
1065
    new_str[str_len] = 0;
1066
    return new_str;
1067
}
1068

    
1069
static int
1070
count_tokens(const char *str, char token, char token_end)
1071
{
1072
    int count = 0;
1073

    
1074
    for (; *str; str++) {
1075
        if (*str == token) {
1076
            count++;
1077
        }
1078
        if (*str == token_end) {
1079
            break;
1080
        }
1081
    }
1082
    return count;
1083
}
1084

    
1085
static const char *
1086
strip(const char *str)
1087
{
1088
    for (; *str && isspace(*str); str++) {
1089
    }
1090
    return str;
1091
}
1092

    
1093
static const char *
1094
find_blank(const char *str)
1095
{
1096
    for (; *str && !isspace(*str); str++) {
1097
    }
1098
    return str;
1099
}
1100

    
1101

    
1102
/*
1103
 *  We really want to use some existing argument parsing library here. That
1104
 *  would give us a consistent look */
1105
static VCardEmulOptions options;
1106
#define READER_STEP 4
1107

    
1108
/* Expects "args" to be at the beginning of a token (ie right after the ','
1109
 * ending the previous token), and puts the next token start in "token",
1110
 * and its length in "token_length". "token" will not be nul-terminated.
1111
 * After calling the macro, "args" will be advanced to the beginning of
1112
 * the next token.
1113
 * This macro may call continue or break.
1114
 */
1115
#define NEXT_TOKEN(token) \
1116
            (token) = args; \
1117
            args = strpbrk(args, ",)"); \
1118
            if (*args == 0) { \
1119
                break; \
1120
            } \
1121
            if (*args == ')') { \
1122
                args++; \
1123
                continue; \
1124
            } \
1125
            (token##_length) = args - (token); \
1126
            args = strip(args+1);
1127

    
1128
VCardEmulOptions *
1129
vcard_emul_options(const char *args)
1130
{
1131
    int reader_count = 0;
1132
    VCardEmulOptions *opts;
1133

    
1134
    /* Allow the future use of allocating the options structure on the fly */
1135
    memcpy(&options, &default_options, sizeof(options));
1136
    opts = &options;
1137

    
1138
    do {
1139
        args = strip(args); /* strip off the leading spaces */
1140
        if (*args == ',') {
1141
            continue;
1142
        }
1143
        /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
1144
         *       cert_2,cert_3...) */
1145
        if (strncmp(args, "soft=", 5) == 0) {
1146
            const char *name;
1147
            size_t name_length;
1148
            const char *vname;
1149
            size_t vname_length;
1150
            const char *type_params;
1151
            size_t type_params_length;
1152
            char type_str[100];
1153
            VCardEmulType type;
1154
            int count, i;
1155
            VirtualReaderOptions *vreaderOpt = NULL;
1156

    
1157
            args = strip(args + 5);
1158
            if (*args != '(') {
1159
                continue;
1160
            }
1161
            args = strip(args+1);
1162

    
1163
            NEXT_TOKEN(name)
1164
            NEXT_TOKEN(vname)
1165
            NEXT_TOKEN(type_params)
1166
            type_params_length = MIN(type_params_length, sizeof(type_str)-1);
1167
            strncpy(type_str, type_params, type_params_length);
1168
            type_str[type_params_length] = 0;
1169
            type = vcard_emul_type_from_string(type_str);
1170

    
1171
            NEXT_TOKEN(type_params)
1172

    
1173
            if (*args == 0) {
1174
                break;
1175
            }
1176

    
1177
            if (opts->vreader_count >= reader_count) {
1178
                reader_count += READER_STEP;
1179
                vreaderOpt = realloc(opts->vreader,
1180
                                reader_count * sizeof(*vreaderOpt));
1181
                if (vreaderOpt == NULL) {
1182
                    return opts; /* we're done */
1183
                }
1184
            }
1185
            opts->vreader = vreaderOpt;
1186
            vreaderOpt = &vreaderOpt[opts->vreader_count];
1187
            vreaderOpt->name = copy_string(name, name_length);
1188
            vreaderOpt->vname = copy_string(vname, vname_length);
1189
            vreaderOpt->card_type = type;
1190
            vreaderOpt->type_params =
1191
                copy_string(type_params, type_params_length);
1192
            count = count_tokens(args, ',', ')') + 1;
1193
            vreaderOpt->cert_count = count;
1194
            vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
1195
            for (i = 0; i < count; i++) {
1196
                const char *cert = args;
1197
                args = strpbrk(args, ",)");
1198
                vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
1199
                args = strip(args+1);
1200
            }
1201
            if (*args == ')') {
1202
                args++;
1203
            }
1204
            opts->vreader_count++;
1205
        /* use_hw= */
1206
        } else if (strncmp(args, "use_hw=", 7) == 0) {
1207
            args = strip(args+7);
1208
            if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
1209
                opts->use_hw = PR_FALSE;
1210
            } else {
1211
                opts->use_hw = PR_TRUE;
1212
            }
1213
            args = find_blank(args);
1214
        /* hw_type= */
1215
        } else if (strncmp(args, "hw_type=", 8) == 0) {
1216
            args = strip(args+8);
1217
            opts->hw_card_type = vcard_emul_type_from_string(args);
1218
            args = find_blank(args);
1219
        /* hw_params= */
1220
        } else if (strncmp(args, "hw_params=", 10) == 0) {
1221
            const char *params;
1222
            args = strip(args+10);
1223
            params = args;
1224
            args = find_blank(args);
1225
            opts->hw_type_params = copy_string(params, args-params);
1226
        /* db="/data/base/path" */
1227
        } else if (strncmp(args, "db=", 3) == 0) {
1228
            const char *db;
1229
            args = strip(args+3);
1230
            if (*args != '"') {
1231
                continue;
1232
            }
1233
            args++;
1234
            db = args;
1235
            args = strpbrk(args, "\"\n");
1236
            opts->nss_db = copy_string(db, args-db);
1237
            if (*args != 0) {
1238
                args++;
1239
            }
1240
        } else {
1241
            args = find_blank(args);
1242
        }
1243
    } while (*args != 0);
1244

    
1245
    return opts;
1246
}
1247

    
1248
void
1249
vcard_emul_usage(void)
1250
{
1251
   fprintf(stderr,
1252
"emul args: comma separated list of the following arguments\n"
1253
" db={nss_database}               (default sql:/etc/pki/nssdb)\n"
1254
" use_hw=[yes|no]                 (default yes)\n"
1255
" hw_type={card_type_to_emulate}  (default CAC)\n"
1256
" hw_param={param_for_card}       (default \"\")\n"
1257
" soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
1258
"       {cert1},{cert2},{cert3}    (default none)\n"
1259
"\n"
1260
"  {nss_database}          The location of the NSS cert & key database\n"
1261
"  {card_type_to_emulate}  What card interface to present to the guest\n"
1262
"  {param_for_card}        Card interface specific parameters\n"
1263
"  {slot_name}             NSS slot that contains the certs\n"
1264
"  {vreader_name}          Virutal reader name to present to the guest\n"
1265
"  {certN}                 Nickname of the certificate n on the virtual card\n"
1266
"\n"
1267
"These parameters come as a single string separated by blanks or newlines."
1268
"\n"
1269
"Unless use_hw is set to no, all tokens that look like removable hardware\n"
1270
"tokens will be presented to the guest using the emulator specified by\n"
1271
"hw_type, and parameters of hw_param.\n"
1272
"\n"
1273
"If more one or more soft= parameters are specified, these readers will be\n"
1274
"presented to the guest\n");
1275
}