Statistics
| Branch: | Revision:

root / libcacard / vcard_emul_nss.c @ 1b902f7d

History | View | Annotate | Download (37.6 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 **)g_malloc(sizeof(unsigned char *)*cert_count);
98
    *cert_lenp = (int *)g_malloc(sizeof(int)*cert_count);
99
    *keysp = (VCardKey **)g_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 *)g_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 = g_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
        g_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 = g_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
    g_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 *)g_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
        g_free(vreader_emul->type_params);
477
    }
478
    g_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
    g_free(certs);
662
    g_free(cert_len);
663
    g_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
        /*
686
         * XXX - the latency value doesn't matter one bit. you only get no
687
         * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
688
         * hard coded in coolkey.  And it isn't coolkey's fault - the timeout
689
         * value we pass get's dropped on the floor before C_WaitForSlotEvent
690
         * is called.
691
         */
692
        slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
693
        if (slot == NULL) {
694
            /* this could be just a no event indication */
695
            if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
696
                continue;
697
            }
698
            break;
699
        }
700
        vreader = vcard_emul_find_vreader_from_slot(slot);
701
        if (vreader == NULL) {
702
            /* new vreader */
703
            vreader_emul = vreader_emul_new(slot, default_card_type,
704
                                            default_type_params);
705
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
706
                                  vreader_emul_delete);
707
            PK11_FreeSlot(slot);
708
            slot = NULL;
709
            vreader_add_reader(vreader);
710
            vreader_free(vreader);
711
            continue;
712
        }
713
        /* card remove/insert */
714
        vreader_emul = vreader_get_private(vreader);
715
        if (PK11_IsPresent(slot)) {
716
            int series = PK11_GetSlotSeries(slot);
717
            if (series != vreader_emul->series) {
718
                if (vreader_emul->present) {
719
                    vreader_insert_card(vreader, NULL);
720
                }
721
                vcard = vcard_emul_mirror_card(vreader);
722
                vreader_insert_card(vreader, vcard);
723
                vcard_free(vcard);
724
            }
725
            vreader_emul->series = series;
726
            vreader_emul->present = 1;
727
            vreader_free(vreader);
728
            PK11_FreeSlot(slot);
729
            continue;
730
        }
731
        if (vreader_emul->present) {
732
            vreader_insert_card(vreader, NULL);
733
        }
734
        vreader_emul->series = 0;
735
        vreader_emul->present = 0;
736
        PK11_FreeSlot(slot);
737
        vreader_free(vreader);
738
    } while (1);
739
}
740

    
741
/* if the card is inserted when we start up, make sure our state is correct */
742
static void
743
vcard_emul_init_series(VReader *vreader, VCard *vcard)
744
{
745
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
746
    PK11SlotInfo *slot = vreader_emul->slot;
747

    
748
    vreader_emul->present = PK11_IsPresent(slot);
749
    vreader_emul->series = PK11_GetSlotSeries(slot);
750
    if (vreader_emul->present == 0) {
751
        vreader_insert_card(vreader, NULL);
752
    }
753
}
754

    
755
/*
756
 * each module has a separate wait call, create a thread for each module that
757
 * we are using.
758
 */
759
static void
760
vcard_emul_new_event_thread(SECMODModule *module)
761
{
762
    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
763
                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
764
                     PR_UNJOINABLE_THREAD, 0);
765
}
766

    
767
static const VCardEmulOptions default_options = {
768
    .nss_db = NULL,
769
    .vreader = NULL,
770
    .vreader_count = 0,
771
    .hw_card_type = VCARD_EMUL_CAC,
772
    .hw_type_params = "",
773
    .use_hw = PR_TRUE
774
};
775

    
776

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

    
798
/* Force a card removal even if the card is not physically removed */
799
VCardEmulError
800
vcard_emul_force_card_remove(VReader *vreader)
801
{
802
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
803
        return VCARD_EMUL_FAIL; /* card is already removed */
804
    }
805

    
806
    /* OK, remove it */
807
    vreader_insert_card(vreader, NULL);
808
    return VCARD_EMUL_OK;
809
}
810

    
811
/* Re-insert of a card that has been removed by force removal */
812
VCardEmulError
813
vcard_emul_force_card_insert(VReader *vreader)
814
{
815
    VReaderEmul *vreader_emul;
816
    VCard *vcard;
817

    
818
    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
819
        return VCARD_EMUL_FAIL; /* card is already removed */
820
    }
821
    vreader_emul = vreader_get_private(vreader);
822

    
823
    /* if it's a softcard, get the saved vcard from the reader emul structure */
824
    if (vreader_emul->saved_vcard) {
825
        vcard = vcard_reference(vreader_emul->saved_vcard);
826
    } else {
827
        /* it must be a physical card, rebuild it */
828
        if (!PK11_IsPresent(vreader_emul->slot)) {
829
            /* physical card has been removed, not way to reinsert it */
830
            return VCARD_EMUL_FAIL;
831
        }
832
        vcard = vcard_emul_mirror_card(vreader);
833
    }
834
    vreader_insert_card(vreader, vcard);
835
    vcard_free(vcard);
836

    
837
    return VCARD_EMUL_OK;
838
}
839

    
840

    
841
static PRBool
842
module_has_removable_hw_slots(SECMODModule *mod)
843
{
844
    int i;
845
    PRBool ret = PR_FALSE;
846
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
847

    
848
    if (!moduleLock) {
849
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
850
        return ret;
851
    }
852
    SECMOD_GetReadLock(moduleLock);
853
    for (i = 0; i < mod->slotCount; i++) {
854
        PK11SlotInfo *slot = mod->slots[i];
855
        if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
856
            ret = PR_TRUE;
857
            break;
858
        }
859
    }
860
    SECMOD_ReleaseReadLock(moduleLock);
861
    return ret;
862
}
863

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

    
872
VCardEmulError
873
vcard_emul_init(const VCardEmulOptions *options)
874
{
875
    SECStatus rv;
876
    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
877
    VReader *vreader;
878
    VReaderEmul *vreader_emul;
879
    SECMODListLock *module_lock;
880
    SECMODModuleList *module_list;
881
    SECMODModuleList *mlp;
882
    int i;
883

    
884
    if (vcard_emul_init_called) {
885
        return VCARD_EMUL_INIT_ALREADY_INITED;
886
    }
887
    vcard_emul_init_called = 1;
888
    vreader_init();
889
    vevent_queue_init();
890

    
891
    if (options == NULL) {
892
        options = &default_options;
893
    }
894

    
895
    /* first initialize NSS */
896
    if (options->nss_db) {
897
        rv = NSS_Init(options->nss_db);
898
    } else {
899
        rv = NSS_Init("sql:/etc/pki/nssdb");
900
    }
901
    if (rv != SECSuccess) {
902
        return VCARD_EMUL_FAIL;
903
    }
904
    /* Set password callback function */
905
    PK11_SetPasswordFunc(vcard_emul_get_password);
906

    
907
    /* set up soft cards emulated by software certs rather than physical cards
908
     * */
909
    for (i = 0; i < options->vreader_count; i++) {
910
        int j;
911
        int cert_count;
912
        unsigned char **certs;
913
        int *cert_len;
914
        VCardKey **keys;
915
        PK11SlotInfo *slot;
916

    
917
        slot = PK11_FindSlotByName(options->vreader[i].name);
918
        if (slot == NULL) {
919
            continue;
920
        }
921
        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
922
                                        options->vreader[i].type_params);
923
        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
924
                              vreader_emul_delete);
925
        vreader_add_reader(vreader);
926
        cert_count = options->vreader[i].cert_count;
927

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

    
966
    /* if we aren't suppose to use hw, skip looking up hardware tokens */
967
    if (!options->use_hw) {
968
        nss_emul_init = has_readers;
969
        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
970
    }
971

    
972
    /* make sure we have some PKCS #11 module loaded */
973
    module_lock = SECMOD_GetDefaultModuleListLock();
974
    module_list = SECMOD_GetDefaultModuleList();
975
    need_coolkey_module = !has_readers;
976
    SECMOD_GetReadLock(module_lock);
977
    for (mlp = module_list; mlp; mlp = mlp->next) {
978
        SECMODModule *module = mlp->module;
979
        if (module_has_removable_hw_slots(module)) {
980
            need_coolkey_module = PR_FALSE;
981
            break;
982
        }
983
    }
984
    SECMOD_ReleaseReadLock(module_lock);
985

    
986
    if (need_coolkey_module) {
987
        SECMODModule *module;
988
        module = SECMOD_LoadUserModule(
989
                    (char *)"library=libcoolkeypk11.so name=Coolkey",
990
                    NULL, PR_FALSE);
991
        if (module == NULL) {
992
            return VCARD_EMUL_FAIL;
993
        }
994
        SECMOD_DestroyModule(module); /* free our reference, Module will still
995
                                       * be on the list.
996
                                       * until we destroy it */
997
    }
998

    
999
    /* now examine all the slots, finding which should be readers */
1000
    /* We should control this with options. For now we mirror out any
1001
     * removable hardware slot */
1002
    default_card_type = options->hw_card_type;
1003
    default_type_params = strdup(options->hw_type_params);
1004

    
1005
    SECMOD_GetReadLock(module_lock);
1006
    for (mlp = module_list; mlp; mlp = mlp->next) {
1007
        SECMODModule *module = mlp->module;
1008
        PRBool has_emul_slots = PR_FALSE;
1009

    
1010
        if (module == NULL) {
1011
                continue;
1012
        }
1013

    
1014
        for (i = 0; i < module->slotCount; i++) {
1015
            PK11SlotInfo *slot = module->slots[i];
1016

    
1017
            /* only map removable HW slots */
1018
            if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
1019
                continue;
1020
            }
1021
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
1022
                                            options->hw_type_params);
1023
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
1024
                                  vreader_emul_delete);
1025
            vreader_add_reader(vreader);
1026

    
1027
            has_readers = PR_TRUE;
1028
            has_emul_slots = PR_TRUE;
1029

    
1030
            if (PK11_IsPresent(slot)) {
1031
                VCard *vcard;
1032
                vcard = vcard_emul_mirror_card(vreader);
1033
                vreader_insert_card(vreader, vcard);
1034
                vcard_emul_init_series(vreader, vcard);
1035
                vcard_free(vcard);
1036
            }
1037
        }
1038
        if (has_emul_slots) {
1039
            vcard_emul_new_event_thread(module);
1040
        }
1041
    }
1042
    SECMOD_ReleaseReadLock(module_lock);
1043
    nss_emul_init = has_readers;
1044

    
1045
    return VCARD_EMUL_OK;
1046
}
1047

    
1048
/* Recreate card insert events for all readers (user should
1049
 * deduce implied reader insert. perhaps do a reader insert as well?)
1050
 */
1051
void
1052
vcard_emul_replay_insertion_events(void)
1053
{
1054
    VReaderListEntry *current_entry;
1055
    VReaderListEntry *next_entry = NULL;
1056
    VReaderList *list = vreader_get_reader_list();
1057

    
1058
    for (current_entry = vreader_list_get_first(list); current_entry;
1059
            current_entry = next_entry) {
1060
        VReader *vreader = vreader_list_get_reader(current_entry);
1061
        next_entry = vreader_list_get_next(current_entry);
1062
        vreader_queue_card_event(vreader);
1063
    }
1064
}
1065

    
1066
/*
1067
 *  Silly little functions to help parsing our argument string
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 = g_strndup(name, name_length);
1188
            vreaderOpt->vname = g_strndup(vname, vname_length);
1189
            vreaderOpt->card_type = type;
1190
            vreaderOpt->type_params =
1191
                g_strndup(type_params, type_params_length);
1192
            count = count_tokens(args, ',', ')') + 1;
1193
            vreaderOpt->cert_count = count;
1194
            vreaderOpt->cert_name = (char **)g_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] = g_strndup(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 = g_strndup(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 = g_strndup(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}          Virtual 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
}