Statistics
| Branch: | Revision:

root / libcacard / vcard_emul_nss.c @ 6f06f178

History | View | Annotate | Download (38 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

    
1009
        /* Ignore the internal module */
1010
        if (module == NULL || module == SECMOD_GetInternalModule()) {
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
            if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
1022
                /*
1023
                 * coolkey <= 1.1.0-20 emulates this reader if it can't find
1024
                 * any hardware readers. This causes problems, warn user of
1025
                 * problems.
1026
                 */
1027
                fprintf(stderr, "known bad coolkey version - see "
1028
                        "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
1029
                continue;
1030
            }
1031
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
1032
                                            options->hw_type_params);
1033
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
1034
                                  vreader_emul_delete);
1035
            vreader_add_reader(vreader);
1036

    
1037
            if (PK11_IsPresent(slot)) {
1038
                VCard *vcard;
1039
                vcard = vcard_emul_mirror_card(vreader);
1040
                vreader_insert_card(vreader, vcard);
1041
                vcard_emul_init_series(vreader, vcard);
1042
                vcard_free(vcard);
1043
            }
1044
        }
1045
        vcard_emul_new_event_thread(module);
1046
    }
1047
    SECMOD_ReleaseReadLock(module_lock);
1048
    nss_emul_init = PR_TRUE;
1049

    
1050
    return VCARD_EMUL_OK;
1051
}
1052

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

    
1063
    for (current_entry = vreader_list_get_first(list); current_entry;
1064
            current_entry = next_entry) {
1065
        VReader *vreader = vreader_list_get_reader(current_entry);
1066
        next_entry = vreader_list_get_next(current_entry);
1067
        vreader_queue_card_event(vreader);
1068
    }
1069
}
1070

    
1071
/*
1072
 *  Silly little functions to help parsing our argument string
1073
 */
1074
static int
1075
count_tokens(const char *str, char token, char token_end)
1076
{
1077
    int count = 0;
1078

    
1079
    for (; *str; str++) {
1080
        if (*str == token) {
1081
            count++;
1082
        }
1083
        if (*str == token_end) {
1084
            break;
1085
        }
1086
    }
1087
    return count;
1088
}
1089

    
1090
static const char *
1091
strip(const char *str)
1092
{
1093
    for (; *str && isspace(*str); str++) {
1094
    }
1095
    return str;
1096
}
1097

    
1098
static const char *
1099
find_blank(const char *str)
1100
{
1101
    for (; *str && !isspace(*str); str++) {
1102
    }
1103
    return str;
1104
}
1105

    
1106

    
1107
/*
1108
 *  We really want to use some existing argument parsing library here. That
1109
 *  would give us a consistent look */
1110
static VCardEmulOptions options;
1111
#define READER_STEP 4
1112

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

    
1133
VCardEmulOptions *
1134
vcard_emul_options(const char *args)
1135
{
1136
    int reader_count = 0;
1137
    VCardEmulOptions *opts;
1138

    
1139
    /* Allow the future use of allocating the options structure on the fly */
1140
    memcpy(&options, &default_options, sizeof(options));
1141
    opts = &options;
1142

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

    
1162
            args = strip(args + 5);
1163
            if (*args != '(') {
1164
                continue;
1165
            }
1166
            args = strip(args+1);
1167

    
1168
            NEXT_TOKEN(name)
1169
            NEXT_TOKEN(vname)
1170
            NEXT_TOKEN(type_params)
1171
            type_params_length = MIN(type_params_length, sizeof(type_str)-1);
1172
            strncpy(type_str, type_params, type_params_length);
1173
            type_str[type_params_length] = 0;
1174
            type = vcard_emul_type_from_string(type_str);
1175

    
1176
            NEXT_TOKEN(type_params)
1177

    
1178
            if (*args == 0) {
1179
                break;
1180
            }
1181

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

    
1250
    return opts;
1251
}
1252

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