Statistics
| Branch: | Revision:

root / libcacard / vcard_emul_nss.c @ 010debef

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

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

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

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

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

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

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

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

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

    
658
    /* now create the card */
659
    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
660
}
661

    
662
static VCardEmulType default_card_type = VCARD_EMUL_NONE;
663
static const char *default_type_params = "";
664

    
665
/*
666
 * This thread looks for card and reader insertions and puts events on the
667
 * event queue
668
 */
669
static void
670
vcard_emul_event_thread(void *arg)
671
{
672
    PK11SlotInfo *slot;
673
    VReader *vreader;
674
    VReaderEmul *vreader_emul;
675
    VCard *vcard;
676
    SECMODModule *module = (SECMODModule *)arg;
677

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

    
724
/* if the card is inserted when we start up, make sure our state is correct */
725
static void
726
vcard_emul_init_series(VReader *vreader, VCard *vcard)
727
{
728
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
729
    PK11SlotInfo *slot = vreader_emul->slot;
730

    
731
    vreader_emul->present = PK11_IsPresent(slot);
732
    vreader_emul->series = PK11_GetSlotSeries(slot);
733
    if (vreader_emul->present == 0) {
734
        vreader_insert_card(vreader, NULL);
735
    }
736
}
737

    
738
/*
739
 * each module has a separate wait call, create a thread for each module that
740
 * we are using.
741
 */
742
static void
743
vcard_emul_new_event_thread(SECMODModule *module)
744
{
745
    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
746
                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
747
                     PR_UNJOINABLE_THREAD, 0);
748
}
749

    
750
static const VCardEmulOptions default_options = {
751
    .nss_db = NULL,
752
    .vreader = NULL,
753
    .vreader_count = 0,
754
    .hw_card_type = VCARD_EMUL_CAC,
755
    .hw_type_params = "",
756
    .use_hw = PR_TRUE
757
};
758

    
759

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

    
781
/* Force a card removal even if the card is not physically removed */
782
VCardEmulError
783
vcard_emul_force_card_remove(VReader *vreader)
784
{
785
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
786
        return VCARD_EMUL_FAIL; /* card is already removed */
787
    }
788

    
789
    /* OK, remove it */
790
    vreader_insert_card(vreader, NULL);
791
    return VCARD_EMUL_OK;
792
}
793

    
794
/* Re-insert of a card that has been removed by force removal */
795
VCardEmulError
796
vcard_emul_force_card_insert(VReader *vreader)
797
{
798
    VReaderEmul *vreader_emul;
799
    VCard *vcard;
800

    
801
    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
802
        return VCARD_EMUL_FAIL; /* card is already removed */
803
    }
804
    vreader_emul = vreader_get_private(vreader);
805

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

    
820
    return VCARD_EMUL_OK;
821
}
822

    
823

    
824
static PRBool
825
module_has_removable_hw_slots(SECMODModule *mod)
826
{
827
    int i;
828
    PRBool ret = PR_FALSE;
829
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
830

    
831
    if (!moduleLock) {
832
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
833
        return ret;
834
    }
835
    SECMOD_GetReadLock(moduleLock);
836
    for (i = 0; i < mod->slotCount; i++) {
837
        PK11SlotInfo *slot = mod->slots[i];
838
        if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
839
            ret = PR_TRUE;
840
            break;
841
        }
842
    }
843
    SECMOD_ReleaseReadLock(moduleLock);
844
    return ret;
845
}
846

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

    
855
VCardEmulError
856
vcard_emul_init(const VCardEmulOptions *options)
857
{
858
    SECStatus rv;
859
    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
860
    VReader *vreader;
861
    VReaderEmul *vreader_emul;
862
    SECMODListLock *module_lock;
863
    SECMODModuleList *module_list;
864
    SECMODModuleList *mlp;
865
    int i;
866

    
867
    if (vcard_emul_init_called) {
868
        return VCARD_EMUL_INIT_ALREADY_INITED;
869
    }
870
    vcard_emul_init_called = 1;
871
    vreader_init();
872
    vevent_queue_init();
873

    
874
    if (options == NULL) {
875
        options = &default_options;
876
    }
877

    
878
    /* first initialize NSS */
879
    if (options->nss_db) {
880
        rv = NSS_Init(options->nss_db);
881
    } else {
882
        rv = NSS_Init("sql:/etc/pki/nssdb");
883
    }
884
    if (rv != SECSuccess) {
885
        return VCARD_EMUL_FAIL;
886
    }
887
    /* Set password callback function */
888
    PK11_SetPasswordFunc(vcard_emul_get_password);
889

    
890
    /* set up soft cards emulated by software certs rather than physical cards
891
     * */
892
    for (i = 0; i < options->vreader_count; i++) {
893
        int j;
894
        int cert_count;
895
        unsigned char **certs;
896
        int *cert_len;
897
        VCardKey **keys;
898
        PK11SlotInfo *slot;
899

    
900
        slot = PK11_FindSlotByName(options->vreader[i].name);
901
        if (slot == NULL) {
902
            continue;
903
        }
904
        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
905
                                        options->vreader[i].type_params);
906
        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
907
                              vreader_emul_delete);
908
        vreader_add_reader(vreader);
909
        cert_count = options->vreader[i].cert_count;
910

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

    
946
    /* if we aren't suppose to use hw, skip looking up hardware tokens */
947
    if (!options->use_hw) {
948
        nss_emul_init = has_readers;
949
        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
950
    }
951

    
952
    /* make sure we have some PKCS #11 module loaded */
953
    module_lock = SECMOD_GetDefaultModuleListLock();
954
    module_list = SECMOD_GetDefaultModuleList();
955
    need_coolkey_module = !has_readers;
956
    SECMOD_GetReadLock(module_lock);
957
    for (mlp = module_list; mlp; mlp = mlp->next) {
958
        SECMODModule *module = mlp->module;
959
        if (module_has_removable_hw_slots(module)) {
960
            need_coolkey_module = PR_FALSE;
961
            break;
962
        }
963
    }
964
    SECMOD_ReleaseReadLock(module_lock);
965

    
966
    if (need_coolkey_module) {
967
        SECMODModule *module;
968
        module = SECMOD_LoadUserModule(
969
                    (char *)"library=libcoolkeypk11.so name=Coolkey",
970
                    NULL, PR_FALSE);
971
        if (module == NULL) {
972
            return VCARD_EMUL_FAIL;
973
        }
974
        SECMOD_DestroyModule(module); /* free our reference, Module will still
975
                                       * be on the list.
976
                                       * until we destroy it */
977
    }
978

    
979
    /* now examine all the slots, finding which should be readers */
980
    /* We should control this with options. For now we mirror out any
981
     * removable hardware slot */
982
    default_card_type = options->hw_card_type;
983
    default_type_params = strdup(options->hw_type_params);
984

    
985
    SECMOD_GetReadLock(module_lock);
986
    for (mlp = module_list; mlp; mlp = mlp->next) {
987
        SECMODModule *module = mlp->module;
988
        PRBool has_emul_slots = PR_FALSE;
989

    
990
        if (module == NULL) {
991
                continue;
992
        }
993

    
994
        for (i = 0; i < module->slotCount; i++) {
995
            PK11SlotInfo *slot = module->slots[i];
996

    
997
            /* only map removable HW slots */
998
            if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
999
                continue;
1000
            }
1001
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
1002
                                            options->hw_type_params);
1003
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
1004
                                  vreader_emul_delete);
1005
            vreader_add_reader(vreader);
1006

    
1007
            has_readers = PR_TRUE;
1008
            has_emul_slots = PR_TRUE;
1009

    
1010
            if (PK11_IsPresent(slot)) {
1011
                VCard *vcard;
1012
                vcard = vcard_emul_mirror_card(vreader);
1013
                vreader_insert_card(vreader, vcard);
1014
                vcard_emul_init_series(vreader, vcard);
1015
                vcard_free(vcard);
1016
            }
1017
        }
1018
        if (has_emul_slots) {
1019
            vcard_emul_new_event_thread(module);
1020
        }
1021
    }
1022
    SECMOD_ReleaseReadLock(module_lock);
1023
    nss_emul_init = has_readers;
1024

    
1025
    return VCARD_EMUL_OK;
1026
}
1027

    
1028
/* Recreate card insert events for all readers (user should
1029
 * deduce implied reader insert. perhaps do a reader insert as well?)
1030
 */
1031
void
1032
vcard_emul_replay_insertion_events(void)
1033
{
1034
    VReaderListEntry *current_entry;
1035
    VReaderListEntry *next_entry = NULL;
1036
    VReaderList *list = vreader_get_reader_list();
1037

    
1038
    for (current_entry = vreader_list_get_first(list); current_entry;
1039
            current_entry = next_entry) {
1040
        VReader *vreader = vreader_list_get_reader(current_entry);
1041
        next_entry = vreader_list_get_next(current_entry);
1042
        vreader_queue_card_event(vreader);
1043
    }
1044
}
1045

    
1046
/*
1047
 *  Silly little functions to help parsing our argument string
1048
 */
1049
static char *
1050
copy_string(const char *str, int str_len)
1051
{
1052
    char *new_str;
1053

    
1054
    new_str = qemu_malloc(str_len+1);
1055
    memcpy(new_str, str, str_len);
1056
    new_str[str_len] = 0;
1057
    return new_str;
1058
}
1059

    
1060
static int
1061
count_tokens(const char *str, char token, char token_end)
1062
{
1063
    int count = 0;
1064

    
1065
    for (; *str; str++) {
1066
        if (*str == token) {
1067
            count++;
1068
        }
1069
        if (*str == token_end) {
1070
            break;
1071
        }
1072
    }
1073
    return count;
1074
}
1075

    
1076
static const char *
1077
strip(const char *str)
1078
{
1079
    for (; *str && isspace(*str); str++) {
1080
    }
1081
    return str;
1082
}
1083

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

    
1092

    
1093
/*
1094
 *  We really want to use some existing argument parsing library here. That
1095
 *  would give us a consistent look */
1096
static VCardEmulOptions options;
1097
#define READER_STEP 4
1098

    
1099
VCardEmulOptions *
1100
vcard_emul_options(const char *args)
1101
{
1102
    int reader_count = 0;
1103
    VCardEmulOptions *opts;
1104
    char type_str[100];
1105
    int type_len;
1106

    
1107
    /* Allow the future use of allocating the options structure on the fly */
1108
    memcpy(&options, &default_options, sizeof(options));
1109
    opts = &options;
1110

    
1111
    do {
1112
        args = strip(args); /* strip off the leading spaces */
1113
        if (*args == ',') {
1114
            continue;
1115
        }
1116
        /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
1117
         *       cert_2,cert_3...) */
1118
        if (strncmp(args, "soft=", 5) == 0) {
1119
            const char *name;
1120
            const char *vname;
1121
            const char *type_params;
1122
            VCardEmulType type;
1123
            int name_length, vname_length, type_params_length, count, i;
1124
            VirtualReaderOptions *vreaderOpt = NULL;
1125

    
1126
            args = strip(args + 5);
1127
            if (*args != '(') {
1128
                continue;
1129
            }
1130
            name = args;
1131
            args = strpbrk(args + 1, ",)");
1132
            if (*args == 0) {
1133
                break;
1134
            }
1135
            if (*args == ')') {
1136
                args++;
1137
                continue;
1138
            }
1139
            args = strip(args+1);
1140
            name_length = args - name - 2;
1141
            vname = args;
1142
            args = strpbrk(args + 1, ",)");
1143
            if (*args == 0) {
1144
                break;
1145
            }
1146
            if (*args == ')') {
1147
                args++;
1148
                continue;
1149
            }
1150
            vname_length = args - name - 2;
1151
            args = strip(args+1);
1152
            type_len = strpbrk(args, ",)") - args;
1153
            assert(sizeof(type_str) > type_len);
1154
            strncpy(type_str, args, type_len);
1155
            type_str[type_len] = 0;
1156
            type = vcard_emul_type_from_string(type_str);
1157
            args = strpbrk(args, ",)");
1158
            if (*args == 0) {
1159
                break;
1160
            }
1161
            if (*args == ')') {
1162
                args++;
1163
                continue;
1164
            }
1165
            args = strip(args++);
1166
            type_params = args;
1167
            args = strpbrk(args + 1, ",)");
1168
            if (*args == 0) {
1169
                break;
1170
            }
1171
            if (*args == ')') {
1172
                args++;
1173
                continue;
1174
            }
1175
            type_params_length = args - name;
1176
            args = strip(args++);
1177
            if (*args == 0) {
1178
                break;
1179
            }
1180

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

    
1248
    return opts;
1249
}
1250

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