Coverage Report

Created: 2023-03-26 06:05

/src/libcacard/src/vcard_emul_nss.c
Line
Count
Source (jump to first uncovered line)
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 file in the top-level directory.
11
 */
12
#include "config.h"
13
14
#include <glib.h>
15
16
#include "common.h"
17
18
/*
19
 * NSS headers
20
 */
21
22
/* avoid including prototypes.h that redefines uint32 */
23
#define NO_NSPR_10_SUPPORT
24
25
#include <nss.h>
26
#include <pk11pub.h>
27
#include <cert.h>
28
#include <keyhi.h>
29
#include <secmod.h>
30
#include <prthread.h>
31
#include <secerr.h>
32
#include <secoid.h>
33
#include <secmodt.h>
34
#include <sechash.h>
35
36
#include "vcard.h"
37
#include "card_7816t.h"
38
#include "vcard_emul.h"
39
#include "vreader.h"
40
#include "vevent.h"
41
42
#include "vcardt_internal.h"
43
#if defined(ENABLE_PCSC)
44
#include "capcsc.h"
45
#endif
46
47
48
typedef enum {
49
    VCardEmulUnknown = -1,
50
    VCardEmulFalse = 0,
51
    VCardEmulTrue = 1
52
} VCardEmulTriState;
53
54
struct VCardKeyStruct {
55
    CERTCertificate *cert;
56
    PK11SlotInfo *slot;
57
    VCardEmulTriState failedX509;
58
};
59
60
61
typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
62
63
struct VReaderEmulStruct {
64
    PK11SlotInfo *slot;
65
    VCardEmulType default_type;
66
    char *type_params;
67
    PRBool present;
68
    int     series;
69
    VCard *saved_vcard;
70
};
71
72
/*
73
 *  NSS Specific options
74
 */
75
struct VirtualReaderOptionsStruct {
76
    char *name;
77
    char *vname;
78
    VCardEmulType card_type;
79
    char *type_params;
80
    char **cert_name;
81
    int cert_count;
82
};
83
84
enum {
85
    USE_HW_NO,
86
    USE_HW_YES,
87
    USE_HW_REMOVABLE,
88
};
89
90
struct VCardEmulOptionsStruct {
91
    char *nss_db;
92
    VirtualReaderOptions *vreader;
93
    int vreader_count;
94
    VCardEmulType hw_card_type;
95
    char *hw_type_params;
96
    int use_hw;
97
};
98
99
static int nss_emul_init;
100
101
/* if we have more that just the slot, define
102
 * VCardEmulStruct here */
103
104
/*
105
 * allocate the set of arrays for certs, cert_len, key
106
 */
107
static void
108
vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
109
                        VCardKey ***keysp, int cert_count)
110
2
{
111
2
    *certsp = g_new(unsigned char *, cert_count);
112
2
    *cert_lenp = g_new(int, cert_count);
113
2
    *keysp = g_new(VCardKey *, cert_count);
114
2
}
115
116
/*
117
 * Emulator specific card information
118
 */
119
typedef struct CardEmulCardStruct CardEmulPrivate;
120
121
static VCardEmul *
122
vcard_emul_new_card(PK11SlotInfo *slot)
123
2
{
124
2
    PK11_ReferenceSlot(slot);
125
    /* currently we don't need anything other than the slot */
126
2
    return (VCardEmul *)slot;
127
2
}
128
129
static void
130
vcard_emul_delete_card(VCardEmul *vcard_emul)
131
2
{
132
2
    PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
133
2
    if (slot == NULL) {
134
0
        return;
135
0
    }
136
2
    PK11_FreeSlot(slot);
137
2
}
138
139
static PK11SlotInfo *
140
vcard_emul_card_get_slot(VCard *card)
141
8.94k
{
142
    /* note, the card is holding the reference, no need to get another one */
143
8.94k
    return (PK11SlotInfo *)vcard_get_private(card);
144
8.94k
}
145
146
147
/*
148
 * key functions
149
 */
150
/* private constructure */
151
static VCardKey *
152
vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
153
6
{
154
6
    VCardKey *key;
155
156
6
    key = g_new(VCardKey, 1);
157
6
    key->slot = PK11_ReferenceSlot(slot);
158
6
    key->cert = CERT_DupCertificate(cert);
159
6
    key->failedX509 = VCardEmulUnknown;
160
6
    return key;
161
6
}
162
163
/* destructor */
164
void
165
vcard_emul_delete_key(VCardKey *key)
166
6
{
167
6
    if (!nss_emul_init || (key == NULL)) {
168
0
        return;
169
0
    }
170
6
    if (key->cert) {
171
6
        CERT_DestroyCertificate(key->cert);
172
6
    }
173
6
    if (key->slot) {
174
6
        PK11_FreeSlot(key->slot);
175
6
    }
176
6
    g_free(key);
177
6
}
178
179
/*
180
 * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
181
 */
182
static SECKEYPrivateKey *
183
vcard_emul_get_nss_key(VCardKey *key)
184
4.47k
{
185
    /* NOTE: if we aren't logged into the token, this could return NULL */
186
4.47k
    return PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
187
4.47k
}
188
189
/*
190
 * Map NSS errors to 7816 errors
191
 */
192
static vcard_7816_status_t
193
vcard_emul_map_error(int error)
194
470
{
195
470
    switch (error) {
196
0
    case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
197
0
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
198
0
    case SEC_ERROR_BAD_DATA:
199
0
    case SEC_ERROR_OUTPUT_LEN:
200
0
    case SEC_ERROR_INPUT_LEN:
201
446
    case SEC_ERROR_INVALID_ARGS:
202
446
    case SEC_ERROR_INVALID_ALGORITHM:
203
446
    case SEC_ERROR_NO_KEY:
204
446
    case SEC_ERROR_INVALID_KEY:
205
446
    case SEC_ERROR_DECRYPTION_DISALLOWED:
206
470
    case SEC_ERROR_PKCS11_GENERAL_ERROR:
207
470
        return VCARD7816_STATUS_ERROR_DATA_INVALID;
208
0
    case SEC_ERROR_NO_MEMORY:
209
0
        return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
210
0
    default:
211
0
        g_debug("error %x", 0x2000 + error);
212
0
        g_warn_if_reached();
213
470
    }
214
0
    return VCARD7816_STATUS_EXC_ERROR_CHANGE;
215
470
}
216
217
/* get RSA bits */
218
int
219
vcard_emul_rsa_bits(VCardKey *key)
220
6
{
221
6
    SECKEYPublicKey *pub_key;
222
6
    int bits = -1;
223
224
6
    if (key == NULL) {
225
        /* couldn't get the key, indicate that we aren't logged in */
226
0
        return -1;
227
0
    }
228
6
    pub_key = CERT_ExtractPublicKey(key->cert);
229
6
    if (pub_key == NULL) {
230
        /* couldn't get the key, indicate that we aren't logged in */
231
0
        return -1;
232
0
    }
233
234
6
    bits = SECKEY_PublicKeyStrengthInBits(pub_key);
235
6
    SECKEY_DestroyPublicKey(pub_key);
236
6
    return bits;
237
6
}
238
239
/* RSA sign/decrypt with the key, signature happens 'in place' */
240
vcard_7816_status_t
241
vcard_emul_rsa_op(VCard *card, VCardKey *key,
242
                  unsigned char *buffer, int buffer_size)
243
4.47k
{
244
4.47k
    SECKEYPrivateKey *priv_key;
245
4.47k
    unsigned signature_len;
246
4.47k
    PK11SlotInfo *slot;
247
4.47k
    SECStatus rv;
248
4.47k
    unsigned char buf[2048];
249
4.47k
    unsigned char *bp = NULL;
250
4.47k
    int pad_len;
251
4.47k
    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
252
253
4.47k
    assert(buffer_size >= 0);
254
4.47k
    if ((!nss_emul_init) || (key == NULL)) {
255
        /* couldn't get the key, indicate that we aren't logged in */
256
0
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
257
0
    }
258
4.47k
    priv_key = vcard_emul_get_nss_key(key);
259
4.47k
    if (priv_key == NULL) {
260
        /* couldn't get the key, indicate that we aren't logged in */
261
0
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
262
0
    }
263
4.47k
    slot = vcard_emul_card_get_slot(card);
264
265
    /*
266
     * this is only true of the rsa signature
267
     */
268
4.47k
    signature_len = PK11_SignatureLen(priv_key);
269
4.47k
    if ((unsigned)buffer_size != signature_len) {
270
1.53k
        ret = VCARD7816_STATUS_ERROR_DATA_INVALID;
271
1.53k
        goto cleanup;
272
1.53k
    }
273
    /* be able to handle larger keys if necessary */
274
2.93k
    bp = &buf[0];
275
2.93k
    if (sizeof(buf) < signature_len) {
276
0
        bp = g_malloc(signature_len);
277
0
    }
278
279
    /*
280
     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
281
     * choke when they try to do the actual operations. Try to detect
282
     * those cases and treat them as if the token didn't claim support for
283
     * X_509.
284
     */
285
2.93k
    if (key->failedX509 != VCardEmulTrue
286
2.93k
                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
287
1.51k
        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
288
1.51k
                                 buffer, buffer_size);
289
1.51k
        if (rv == SECSuccess) {
290
1.06k
            assert((unsigned)buffer_size == signature_len);
291
1.06k
            memcpy(buffer, bp, signature_len);
292
1.06k
            key->failedX509 = VCardEmulFalse;
293
1.06k
            goto cleanup;
294
1.06k
        }
295
        /*
296
         * we've had a successful X509 operation, this failure must be
297
         * something else
298
         */
299
448
        if (key->failedX509 == VCardEmulFalse) {
300
446
            ret = vcard_emul_map_error(PORT_GetError());
301
446
            goto cleanup;
302
446
        }
303
        /*
304
         * key->failedX509 must be Unknown at this point, try the
305
         * non-x_509 case
306
         */
307
448
    }
308
    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
309
    /* is this a PKCS #1 formatted signature? */
310
1.42k
    if ((buffer[0] == 0) && (buffer[1] == 1)) {
311
347
        int i;
312
313
2.37k
        for (i = 2; i < buffer_size; i++) {
314
            /* rsa signature pad */
315
2.37k
            if (buffer[i] != 0xff) {
316
347
                break;
317
347
            }
318
2.37k
        }
319
347
        if ((i < buffer_size) && (buffer[i] == 0)) {
320
            /* yes, we have a properly formatted PKCS #1 signature */
321
            /*
322
             * NOTE: even if we accidentally got an encrypt buffer, which
323
             * through sheer luck started with 00, 01, ff, 00, it won't matter
324
             * because the resulting Sign operation will effectively decrypt
325
             * the real buffer.
326
             */
327
130
            SECItem signature;
328
130
            SECItem hash;
329
330
130
            i++;
331
130
            hash.data = &buffer[i];
332
130
            hash.len = buffer_size - i;
333
130
            signature.data = bp;
334
130
            signature.len = signature_len;
335
130
            rv = PK11_Sign(priv_key,  &signature, &hash);
336
130
            if (rv != SECSuccess) {
337
24
                ret = vcard_emul_map_error(PORT_GetError());
338
24
                goto cleanup;
339
24
            }
340
106
            assert((unsigned)buffer_size == signature.len);
341
106
            memcpy(buffer, bp, signature.len);
342
            /*
343
             * we got here because either the X509 attempt failed, or the
344
             * token couldn't do the X509 operation, in either case stay
345
             * with the PKCS version for future operations on this key
346
             */
347
106
            key->failedX509 = VCardEmulTrue;
348
106
            goto cleanup;
349
106
        }
350
347
    }
351
    /* We can not do raw RSA operation and the bytes do not look like PKCS#1.5
352
     * Assuming it is deciphering operation.
353
     */
354
1.29k
    rv = PK11_PrivDecryptPKCS1(priv_key, bp, &signature_len, buffer_size, buffer, buffer_size);
355
1.29k
    if (rv != SECSuccess) {
356
        /* The assumption was wrong. Give up */
357
0
        ret = vcard_emul_map_error(PORT_GetError());
358
0
        goto cleanup;
359
0
    }
360
1.29k
    pad_len = buffer_size - signature_len;
361
1.29k
    if (pad_len < 4) {
362
0
        ret = VCARD7816_STATUS_ERROR_GENERAL;
363
0
        goto cleanup;
364
0
    }
365
    /*
366
     * OK now we've decrypted the payload, package it up in PKCS #1 for the
367
     * upper layer.
368
     */
369
1.29k
    buffer[0] = 0;
370
1.29k
    buffer[1] = 2; /* RSA_encrypt  */
371
1.29k
    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
372
    /*
373
     * padding for PKCS #1 encrypted data is a string of random bytes. The
374
     * random bytes protect against potential decryption attacks against RSA.
375
     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
376
     * them. This shouldn't matter to the upper level code which should just
377
     * strip this code out anyway, so We'll pad with a constant 3.
378
     */
379
1.29k
    memset(&buffer[2], 0x03, pad_len);
380
1.29k
    pad_len += 2; /* index to the end of the pad */
381
1.29k
    buffer[pad_len] = 0;
382
1.29k
    pad_len++; /* index to the start of the data */
383
1.29k
    memcpy(&buffer[pad_len], bp, signature_len);
384
    /*
385
     * we got here because either the X509 attempt failed, or the
386
     * token couldn't do the X509 operation, in either case stay
387
     * with the PKCS version for future operations on this key
388
     */
389
1.29k
    key->failedX509 = VCardEmulTrue;
390
4.47k
cleanup:
391
4.47k
    if (bp != buf) {
392
1.53k
        g_free(bp);
393
1.53k
    }
394
4.47k
    SECKEY_DestroyPrivateKey(priv_key);
395
4.47k
    return ret;
396
1.29k
}
397
398
/*
399
 * Login functions
400
 */
401
/* return the number of login attempts still possible on the card. if unknown,
402
 * return -1 */
403
int
404
vcard_emul_get_login_count(G_GNUC_UNUSED VCard *card)
405
0
{
406
0
    return -1;
407
0
}
408
409
/* login into the card, return the 7816 status word (sw2 || sw1) */
410
vcard_7816_status_t
411
vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
412
827
{
413
827
    PK11SlotInfo *slot;
414
827
    unsigned char *pin_string;
415
827
    int i;
416
827
    SECStatus rv;
417
418
827
    if (!nss_emul_init) {
419
0
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
420
0
    }
421
827
    slot = vcard_emul_card_get_slot(card);
422
     /* We depend on the PKCS #11 module internal login state here because we
423
      * create a separate process to handle each guest instance. If we needed
424
      * to handle multiple guests from one process, then we would need to keep
425
      * a lot of extra state in our card structure
426
      * */
427
827
    pin_string = g_malloc(pin_len+1);
428
827
    memcpy(pin_string, pin, pin_len);
429
827
    pin_string[pin_len] = 0;
430
431
    /* handle CAC expanded pins correctly */
432
1.88k
    for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
433
1.05k
        pin_string[i] = 0;
434
1.05k
    }
435
436
    /* If using an emulated card, make sure to log out of any already logged in
437
     * session. */
438
827
    vcard_emul_logout(card);
439
440
827
    rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
441
827
    memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
442
                                        to be snooped */
443
827
    g_free(pin_string);
444
827
    if (rv == SECSuccess) {
445
827
        return VCARD7816_STATUS_SUCCESS;
446
827
    }
447
    /* map the error from port get error */
448
0
    return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
449
827
}
450
451
int
452
vcard_emul_is_logged_in(VCard *card)
453
2.57k
{
454
2.57k
    PK11SlotInfo *slot;
455
456
2.57k
    if (!nss_emul_init) {
457
0
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
458
0
    }
459
460
2.57k
    slot = vcard_emul_card_get_slot(card);
461
     /* We depend on the PKCS #11 module internal login state here because we
462
      * create a separate process to handle each guest instance. If we needed
463
      * to handle multiple guests from one process, then we would need to keep
464
      * a lot of extra state in our card structure
465
      */
466
467
    /* If we do not need log in, we present the token as "logged in" */
468
2.57k
    if (PK11_NeedLogin(slot) == PR_FALSE) {
469
2.57k
        return 1;
470
2.57k
    }
471
472
    /* For the tokens that require login, delegate to NSS to figure out the
473
     * login status */
474
0
    return !!PK11_IsLoggedIn(slot, NULL);
475
2.57k
}
476
477
void
478
vcard_emul_logout(VCard *card)
479
827
{
480
827
    PK11SlotInfo *slot;
481
482
827
    if (!nss_emul_init) {
483
0
        return;
484
0
    }
485
486
827
    slot = vcard_emul_card_get_slot(card);
487
827
    if (PK11_IsLoggedIn(slot, NULL)) {
488
0
        PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
489
0
    }
490
827
}
491
492
void
493
vcard_emul_reset(VCard *card, G_GNUC_UNUSED VCardPower power)
494
0
{
495
    /*
496
     * if we reset the card (either power on or power off), we lose our login
497
     * state
498
     */
499
0
    vcard_emul_logout(card);
500
501
    /* TODO: we may also need to send insertion/removal events? */
502
0
}
503
504
static VReader *
505
vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
506
0
{
507
0
    VReaderList *reader_list = vreader_get_reader_list();
508
0
    VReaderListEntry *current_entry;
509
510
0
    if (reader_list == NULL) {
511
0
        return NULL;
512
0
    }
513
0
    for (current_entry = vreader_list_get_first(reader_list); current_entry;
514
0
                        current_entry = vreader_list_get_next(current_entry)) {
515
0
        VReader *reader = vreader_list_get_reader(current_entry);
516
0
        VReaderEmul *reader_emul = vreader_get_private(reader);
517
0
        if (reader_emul->slot == slot) {
518
0
            vreader_list_delete(reader_list);
519
0
            return reader;
520
0
        }
521
0
        vreader_free(reader);
522
0
    }
523
524
0
    vreader_list_delete(reader_list);
525
0
    return NULL;
526
0
}
527
528
/*
529
 * create a new reader emul
530
 */
531
static VReaderEmul *
532
vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
533
2
{
534
2
    VReaderEmul *new_reader_emul;
535
536
2
    new_reader_emul = g_new(VReaderEmul, 1);
537
538
2
    new_reader_emul->slot = PK11_ReferenceSlot(slot);
539
2
    new_reader_emul->default_type = type;
540
2
    new_reader_emul->type_params = g_strdup(params);
541
2
    new_reader_emul->present = PR_FALSE;
542
2
    new_reader_emul->series = 0;
543
2
    new_reader_emul->saved_vcard = NULL;
544
2
    return new_reader_emul;
545
2
}
546
547
static void
548
vreader_emul_delete(VReaderEmul *vreader_emul)
549
2
{
550
2
    if (vreader_emul == NULL) {
551
0
        return;
552
0
    }
553
2
    vcard_free(vreader_emul->saved_vcard);
554
2
    if (vreader_emul->slot) {
555
2
        PK11_FreeSlot(vreader_emul->slot);
556
2
    }
557
2
    g_free(vreader_emul->type_params);
558
2
    g_free(vreader_emul);
559
2
}
560
561
/*
562
 *  TODO: move this to emulater non-specific file
563
 */
564
static VCardEmulType
565
vcard_emul_get_type(VReader *vreader)
566
2
{
567
2
    VReaderEmul *vreader_emul;
568
569
2
    vreader_emul = vreader_get_private(vreader);
570
2
    if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
571
2
        return vreader_emul->default_type;
572
2
    }
573
574
0
    return vcard_emul_type_select(vreader);
575
2
}
576
/*
577
 *  TODO: move this to emulater non-specific file
578
 */
579
static const char *
580
vcard_emul_get_type_params(VReader *vreader)
581
2
{
582
2
    VReaderEmul *vreader_emul;
583
584
2
    vreader_emul = vreader_get_private(vreader);
585
2
    if (vreader_emul && vreader_emul->type_params) {
586
2
        return vreader_emul->type_params;
587
2
    }
588
589
0
    return "";
590
2
}
591
592
/* pull the slot out of the reader private data */
593
static PK11SlotInfo *
594
vcard_emul_reader_get_slot(VReader *vreader)
595
2
{
596
2
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
597
2
    if (vreader_emul == NULL) {
598
0
        return NULL;
599
0
    }
600
2
    return vreader_emul->slot;
601
2
}
602
603
/*
604
 *  Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
605
 *  historical bytes for any software emulated card. The remaining bytes can be
606
 *  used to indicate the actual emulator
607
 */
608
static unsigned char *nss_atr;
609
static int nss_atr_len;
610
611
void
612
vcard_emul_get_atr(G_GNUC_UNUSED VCard *card, unsigned char *atr, int *atr_len)
613
0
{
614
0
    int len;
615
0
    assert(atr != NULL);
616
617
0
    if (nss_atr == NULL) {
618
0
        nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
619
0
    }
620
0
    len = MIN(nss_atr_len, *atr_len);
621
0
    memcpy(atr, nss_atr, len);
622
0
    *atr_len = len;
623
0
}
624
625
static SECStatus
626
vcard_emul_create_serial(VCard *card, unsigned char *data, int len)
627
2
{
628
2
    HASH_HashType hashType;
629
2
    HASHContext *hashContext = NULL;
630
2
    unsigned char digest[32];
631
2
    unsigned int digestLen = 0;
632
633
2
    hashType = HASH_GetHashTypeByOidTag(SEC_OID_SHA256);
634
2
    hashContext = HASH_Create(hashType);
635
2
    if (hashContext == NULL) {
636
0
        return SECFailure;
637
0
    }
638
639
2
    HASH_Begin(hashContext);
640
2
    HASH_Update(hashContext, data, len);
641
2
    HASH_End(hashContext, digest, &digestLen, 32);
642
2
    HASH_Destroy(hashContext);
643
644
2
    vcard_set_serial(card, digest, (size_t) digestLen);
645
646
2
    return SECSuccess;
647
2
}
648
649
/*
650
 * create a new card from certs and keys
651
 */
652
static VCard *
653
vcard_emul_make_card(VReader *reader,
654
                     unsigned char * const *certs, int *cert_len,
655
                     VCardKey *keys[], int cert_count)
656
2
{
657
2
    VCardEmul *vcard_emul;
658
2
    VCard *vcard;
659
2
    PK11SlotInfo *slot;
660
2
    VCardEmulType type;
661
2
    const char *params;
662
663
2
    g_debug("%s: called", __func__);
664
665
2
    type = vcard_emul_get_type(reader);
666
667
    /* ignore the inserted card */
668
2
    if (type == VCARD_EMUL_NONE) {
669
0
        return NULL;
670
0
    }
671
2
    slot = vcard_emul_reader_get_slot(reader);
672
2
    if (slot == NULL) {
673
0
        return NULL;
674
0
    }
675
676
2
    params = vcard_emul_get_type_params(reader);
677
    /* params these can be NULL */
678
679
2
    vcard_emul = vcard_emul_new_card(slot);
680
2
    if (vcard_emul == NULL) {
681
0
        return NULL;
682
0
    }
683
2
    vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
684
2
    if (vcard == NULL) {
685
0
        vcard_emul_delete_card(vcard_emul);
686
0
        return NULL;
687
0
    }
688
689
2
    if (cert_count > 0) {
690
2
        vcard_emul_create_serial(vcard, certs[0], cert_len[0]);
691
2
    }
692
693
2
    vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
694
2
    return vcard;
695
2
}
696
697
698
/*
699
 * 'clone' a physical card as a virtual card
700
 */
701
static VCard *
702
vcard_emul_mirror_card(VReader *vreader)
703
0
{
704
    /*
705
     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
706
     * us the real certs until we log in.
707
     */
708
0
    PK11GenericObject *firstObj, *thisObj;
709
0
    int cert_count, i;
710
0
    unsigned char **certs;
711
0
    SECItem **ids;
712
0
    int *cert_len;
713
0
    VCardKey **keys;
714
0
    PK11SlotInfo *slot;
715
0
    VCard *card;
716
717
0
    g_debug("%s: called", __func__);
718
719
0
    slot = vcard_emul_reader_get_slot(vreader);
720
0
    if (slot == NULL) {
721
0
        return NULL;
722
0
    }
723
724
0
    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
725
0
    if (firstObj == NULL) {
726
0
        return NULL;
727
0
    }
728
729
    /* count the certs */
730
0
    cert_count = 0;
731
0
    for (thisObj = firstObj; thisObj;
732
0
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
733
0
        cert_count++;
734
0
    }
735
736
    /* allocate the arrays */
737
0
    vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
738
0
    ids = g_new(SECItem *, cert_count);
739
740
    /* fill in the arrays */
741
0
    cert_count = i = 0;
742
0
    for (thisObj = firstObj; thisObj;
743
0
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
744
0
        SECItem derCert, *id;
745
0
        CERTCertificate *cert;
746
0
        SECStatus rv;
747
748
0
        g_debug("%s: Found certificate", __func__);
749
0
        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
750
0
                                   CKA_VALUE, &derCert);
751
0
        if (rv != SECSuccess) {
752
0
            continue;
753
0
        }
754
        /* Read ID and try to sort by this to get reproducible results
755
         * in case of underlying pkcs11 module does not provide it */
756
0
        id = SECITEM_AllocItem(NULL, NULL, 0);
757
0
        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj, CKA_ID, id);
758
0
        if (rv != SECSuccess) {
759
0
            SECITEM_FreeItem(&derCert, PR_FALSE);
760
0
            SECITEM_FreeItem(id, PR_TRUE);
761
0
            continue;
762
0
        }
763
        /* create floating temp cert. This gives us a cert structure even if
764
         * the token isn't logged in */
765
0
        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
766
0
                                       NULL, PR_FALSE, PR_TRUE);
767
0
        SECITEM_FreeItem(&derCert, PR_FALSE);
768
0
        if (cert == NULL) {
769
0
            SECITEM_FreeItem(id, PR_TRUE);
770
0
            continue;
771
0
        }
772
773
0
        for (i = 0; i < cert_count; i++) {
774
0
            if (SECITEM_CompareItem(id, ids[i]) < SECEqual) {
775
                /* Make space for the item here, move the rest of the items */
776
0
                memmove(&certs[i + 1], &certs[i], (cert_count - i) * sizeof(certs[0]));
777
0
                memmove(&cert_len[i + 1], &cert_len[i], (cert_count - i) * sizeof(cert_len[0]));
778
0
                memmove(&keys[i + 1], &keys[i], (cert_count - i) * sizeof(keys[0]));
779
0
                memmove(&ids[i + 1], &ids[i], (cert_count - i) * sizeof(ids[0]));
780
0
                break;
781
0
            }
782
0
        }
783
0
        certs[i] = cert->derCert.data;
784
0
        cert_len[i] = cert->derCert.len;
785
0
        keys[i] = vcard_emul_make_key(slot, cert);
786
0
        ids[i] = id;
787
0
        cert_count++;
788
0
        CERT_DestroyCertificate(cert); /* key obj still has a reference */
789
0
    }
790
0
    PK11_DestroyGenericObjects(firstObj);
791
    /* No longer needed */
792
0
    for (i = 0; i < cert_count; i++) {
793
0
        SECITEM_FreeItem(ids[i], PR_TRUE);
794
0
    }
795
0
    g_free(ids);
796
797
    /* now create the card */
798
0
    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
799
0
    g_free(certs);
800
0
    g_free(cert_len);
801
0
    g_free(keys);
802
803
0
    return card;
804
0
}
805
806
static VCardEmulType default_card_type = VCARD_EMUL_NONE;
807
static const char *default_type_params = "";
808
809
/*
810
 * This thread looks for card and reader insertions and puts events on the
811
 * event queue
812
 */
813
static void
814
vcard_emul_event_thread(void *arg)
815
0
{
816
0
    PK11SlotInfo *slot;
817
0
    VReader *vreader;
818
0
    VReaderEmul *vreader_emul;
819
0
    VCard *vcard;
820
0
    SECMODModule *module = (SECMODModule *)arg;
821
822
0
    do {
823
        /*
824
         * XXX - the latency value doesn't matter one bit. you only get no
825
         * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
826
         * hard coded in coolkey.  And it isn't coolkey's fault - the timeout
827
         * value we pass get's dropped on the floor before C_WaitForSlotEvent
828
         * is called.
829
         */
830
0
        slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
831
0
        if (slot == NULL) {
832
            /* this could be just a no event indication */
833
0
            if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
834
0
                continue;
835
0
            }
836
0
            break;
837
0
        }
838
0
        vreader = vcard_emul_find_vreader_from_slot(slot);
839
0
        if (vreader == NULL) {
840
            /* new vreader */
841
0
            vreader_emul = vreader_emul_new(slot, default_card_type,
842
0
                                            default_type_params);
843
0
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
844
0
                                  vreader_emul_delete);
845
0
            PK11_FreeSlot(slot);
846
0
            slot = NULL;
847
0
            vreader_add_reader(vreader);
848
0
            vreader_free(vreader);
849
0
            continue;
850
0
        }
851
        /* card remove/insert */
852
0
        vreader_emul = vreader_get_private(vreader);
853
0
        if (PK11_IsPresent(slot)) {
854
0
            int series = PK11_GetSlotSeries(slot);
855
0
            if (series != vreader_emul->series) {
856
0
                if (vreader_emul->present) {
857
0
                    vreader_insert_card(vreader, NULL);
858
0
                }
859
0
                vcard = vcard_emul_mirror_card(vreader);
860
0
                vreader_insert_card(vreader, vcard);
861
0
                vcard_free(vcard);
862
0
            }
863
0
            vreader_emul->series = series;
864
0
            vreader_emul->present = 1;
865
0
            vreader_free(vreader);
866
0
            PK11_FreeSlot(slot);
867
0
            continue;
868
0
        }
869
0
        if (vreader_emul->present) {
870
0
            vreader_insert_card(vreader, NULL);
871
0
        }
872
0
        vreader_emul->series = 0;
873
0
        vreader_emul->present = 0;
874
0
        PK11_FreeSlot(slot);
875
0
        vreader_free(vreader);
876
0
    } while (1);
877
0
}
878
879
/* if the card is inserted when we start up, make sure our state is correct */
880
static void
881
vcard_emul_init_series(VReader *vreader, G_GNUC_UNUSED VCard *vcard)
882
2
{
883
2
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
884
2
    PK11SlotInfo *slot = vreader_emul->slot;
885
886
2
    vreader_emul->present = PK11_IsPresent(slot);
887
2
    vreader_emul->series = PK11_GetSlotSeries(slot);
888
2
    if (vreader_emul->present == 0) {
889
0
        vreader_insert_card(vreader, NULL);
890
0
    }
891
2
}
892
893
/*
894
 * each module has a separate wait call, create a thread for each module that
895
 * we are using.
896
 */
897
static void
898
vcard_emul_new_event_thread(SECMODModule *module)
899
0
{
900
0
    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
901
0
                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
902
0
                     PR_UNJOINABLE_THREAD, 0);
903
0
}
904
905
static const VCardEmulOptions default_options = {
906
    .nss_db = NULL,
907
    .vreader = NULL,
908
    .vreader_count = 0,
909
    .hw_card_type = VCARD_EMUL_CAC,
910
    .hw_type_params = NULL,
911
    .use_hw = USE_HW_YES,
912
};
913
914
915
/*
916
 *  NSS needs the app to supply a password prompt. In our case the only time
917
 *  the password is supplied is as part of the Login APDU. The actual password
918
 *  is passed in the pw_arg in that case. In all other cases pw_arg should be
919
 *  NULL.
920
 */
921
static char *
922
vcard_emul_get_password(G_GNUC_UNUSED PK11SlotInfo *slot, PRBool retries, void *pw_arg)
923
0
{
924
    /* if it didn't work the first time, don't keep trying */
925
0
    if (retries) {
926
0
        return NULL;
927
0
    }
928
    /* we are looking up a password when we don't have one in hand */
929
0
    if (pw_arg == NULL) {
930
0
        return NULL;
931
0
    }
932
    /* TODO: we really should verify that were are using the right slot */
933
0
    return PORT_Strdup(pw_arg);
934
0
}
935
936
/* Force a card removal even if the card is not physically removed */
937
VCardEmulError
938
vcard_emul_force_card_remove(VReader *vreader)
939
0
{
940
0
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
941
0
        return VCARD_EMUL_FAIL; /* card is already removed */
942
0
    }
943
944
    /* OK, remove it */
945
0
    vreader_insert_card(vreader, NULL);
946
0
    return VCARD_EMUL_OK;
947
0
}
948
949
/* Re-insert of a card that has been removed by force removal */
950
VCardEmulError
951
vcard_emul_force_card_insert(VReader *vreader)
952
0
{
953
0
    VReaderEmul *vreader_emul;
954
0
    VCard *vcard;
955
956
0
    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
957
0
        return VCARD_EMUL_FAIL; /* card is already removed */
958
0
    }
959
0
    vreader_emul = vreader_get_private(vreader);
960
961
    /* if it's a softcard, get the saved vcard from the reader emul structure */
962
0
    if (vreader_emul->saved_vcard) {
963
0
        vcard = vcard_reference(vreader_emul->saved_vcard);
964
0
    } else {
965
        /* it must be a physical card, rebuild it */
966
0
        if (!PK11_IsPresent(vreader_emul->slot)) {
967
            /* physical card has been removed, not way to reinsert it */
968
0
            return VCARD_EMUL_FAIL;
969
0
        }
970
0
        vcard = vcard_emul_mirror_card(vreader);
971
0
    }
972
0
    vreader_insert_card(vreader, vcard);
973
0
    vcard_free(vcard);
974
975
0
    return VCARD_EMUL_OK;
976
0
}
977
978
/* Previously we returned FAIL if no readers found. This makes
979
 * no sense when using hardware, since there may be no readers connected
980
 * at the time vcard_emul_init is called, but they will be properly
981
 * recognized later. So Instead return FAIL only if no_hw==1 and no
982
 * vcards can be created (indicates error with certificates provided
983
 * or db), or if any other higher level error (NSS error, missing coolkey). */
984
static int vcard_emul_init_called;
985
static NSSInitContext *nss_ctx = NULL;
986
987
VCardEmulError
988
vcard_emul_init(const VCardEmulOptions *options)
989
2
{
990
2
    PRBool has_readers = PR_FALSE;
991
2
    VReader *vreader;
992
2
    VReaderEmul *vreader_emul;
993
2
    SECMODListLock *module_lock;
994
2
    SECMODModuleList *module_list;
995
2
    SECMODModuleList *mlp;
996
2
    int i;
997
2
    gchar *path = NULL;
998
2
    const gchar *nss_db;
999
1000
2
    g_debug("%s: called", __func__);
1001
1002
2
    if (vcard_emul_init_called) {
1003
0
        return VCARD_EMUL_INIT_ALREADY_INITED;
1004
0
    }
1005
2
    vcard_emul_init_called = 1;
1006
2
    vreader_init();
1007
2
    vevent_queue_init();
1008
1009
2
    if (options == NULL) {
1010
0
        options = &default_options;
1011
0
    }
1012
1013
#if defined(ENABLE_PCSC)
1014
    if (options->use_hw && options->hw_card_type == VCARD_EMUL_PASSTHRU) {
1015
        if (options->vreader_count > 0) {
1016
            fprintf(stderr, "Error: you cannot use a soft card and "
1017
                            "a passthru card simultaneously.\n");
1018
            return VCARD_EMUL_FAIL;
1019
        }
1020
1021
        if (capcsc_init()) {
1022
            fprintf(stderr, "Error initializing PCSC interface.\n");
1023
            return VCARD_EMUL_FAIL;
1024
        }
1025
1026
        g_debug("%s: returning with passthrough initialized", __func__);
1027
        return VCARD_EMUL_OK;
1028
    }
1029
#endif
1030
1031
    /* first initialize NSS */
1032
2
    nss_db = options->nss_db;
1033
2
    if (nss_db == NULL) {
1034
0
#ifndef _WIN32
1035
0
        nss_db = "/etc/pki/nssdb";
1036
#else
1037
        const gchar * const *config_dirs = g_get_system_config_dirs();
1038
        if (config_dirs == NULL || config_dirs[0] == NULL) {
1039
            return VCARD_EMUL_FAIL;
1040
        }
1041
1042
        path = g_build_filename(config_dirs[0], "pki", "nssdb", NULL);
1043
        nss_db = path;
1044
#endif
1045
0
    }
1046
1047
2
    nss_ctx = NSS_InitContext(nss_db, "", "", "", NULL, NSS_INIT_READONLY);
1048
2
    if (nss_ctx == NULL) {
1049
0
        g_debug("%s: NSS_InitContext failed. Does the DB directory '%s' exist?",
1050
0
                __func__, nss_db);
1051
0
        g_free(path);
1052
0
        return VCARD_EMUL_FAIL;
1053
0
    }
1054
2
    g_free(path);
1055
2
    path = NULL;
1056
1057
    /* Set password callback function */
1058
2
    PK11_SetPasswordFunc(vcard_emul_get_password);
1059
1060
    /* set up soft cards emulated by software certs rather than physical cards
1061
     * */
1062
4
    for (i = 0; i < options->vreader_count; i++) {
1063
2
        int j;
1064
2
        int cert_count;
1065
2
        unsigned char **certs;
1066
2
        int *cert_len;
1067
2
        VCardKey **keys;
1068
2
        PK11SlotInfo *slot;
1069
1070
2
        slot = PK11_FindSlotByName(options->vreader[i].name);
1071
2
        if (slot == NULL) {
1072
0
            continue;
1073
0
        }
1074
2
        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
1075
2
                                        options->vreader[i].type_params);
1076
2
        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
1077
2
                              vreader_emul_delete);
1078
2
        vreader_add_reader(vreader);
1079
1080
2
        vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
1081
2
                                options->vreader[i].cert_count);
1082
1083
2
        cert_count = 0;
1084
8
        for (j = 0; j < options->vreader[i].cert_count; j++) {
1085
            /* we should have a better way of identifying certs than by
1086
             * nickname here */
1087
6
            CERTCertificate *cert = PK11_FindCertFromNickname(
1088
6
                                        options->vreader[i].cert_name[j],
1089
6
                                        NULL);
1090
6
            if (cert == NULL) {
1091
0
                continue;
1092
0
            }
1093
6
            certs[cert_count] = cert->derCert.data;
1094
6
            cert_len[cert_count] = cert->derCert.len;
1095
6
            keys[cert_count] = vcard_emul_make_key(slot, cert);
1096
            /* this is safe because the key is still holding a cert reference */
1097
6
            CERT_DestroyCertificate(cert);
1098
6
            cert_count++;
1099
6
        }
1100
2
        if (cert_count) {
1101
2
            VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
1102
2
                                                keys, cert_count);
1103
2
            vreader_insert_card(vreader, vcard);
1104
2
            vcard_emul_init_series(vreader, vcard);
1105
            /* allow insertion and removal of soft cards */
1106
2
            vreader_emul->saved_vcard = vcard_reference(vcard);
1107
2
            vcard_free(vcard);
1108
2
            vreader_free(vreader);
1109
2
            has_readers = PR_TRUE;
1110
2
        }
1111
2
        PK11_FreeSlot(slot);
1112
2
        g_free(certs);
1113
2
        g_free(cert_len);
1114
2
        g_free(keys);
1115
2
    }
1116
1117
    /* if we aren't suppose to use hw, skip looking up hardware tokens */
1118
2
    if (!options->use_hw) {
1119
2
        nss_emul_init = has_readers;
1120
2
        g_debug("%s: returning: Not using HW", __func__);
1121
2
        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
1122
2
    }
1123
1124
    /* make sure we have some PKCS #11 module loaded */
1125
0
    module_lock = SECMOD_GetDefaultModuleListLock();
1126
0
    module_list = SECMOD_GetDefaultModuleList();
1127
1128
    /* now examine all the slots, finding which should be readers */
1129
    /* We should control this with options. For now we mirror out any
1130
     * removable hardware slot */
1131
0
    default_card_type = options->hw_card_type;
1132
0
    default_type_params = g_strdup(options->hw_type_params);
1133
1134
0
    SECMOD_GetReadLock(module_lock);
1135
0
    for (mlp = module_list; mlp; mlp = mlp->next) {
1136
0
        SECMODModule *module = mlp->module;
1137
1138
        /* Ignore the internal module */
1139
0
        if (module == NULL || module == SECMOD_GetInternalModule()) {
1140
0
            continue;
1141
0
        }
1142
1143
0
        g_debug("%s: Listing modules, trying %s", __func__, module->commonName);
1144
0
        for (i = 0; i < module->slotCount; i++) {
1145
0
            PK11SlotInfo *slot = module->slots[i];
1146
1147
            /* only map removable HW slots */
1148
0
            if (slot == NULL || !PK11_IsRemovable(slot) ||
1149
0
                (options->use_hw == USE_HW_YES && !PK11_IsHW(slot))) {
1150
0
                continue;
1151
0
            }
1152
0
            if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
1153
                /*
1154
                 * coolkey <= 1.1.0-20 emulates this reader if it can't find
1155
                 * any hardware readers. This causes problems, warn user of
1156
                 * problems.
1157
                 */
1158
0
                fprintf(stderr, "known bad coolkey version - see "
1159
0
                        "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
1160
0
                continue;
1161
0
            }
1162
0
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
1163
0
                                            options->hw_type_params);
1164
0
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
1165
0
                                  vreader_emul_delete);
1166
0
            vreader_add_reader(vreader);
1167
0
            g_debug("%s: Added reader from slot %s", __func__,
1168
0
                    PK11_GetSlotName(slot));
1169
1170
0
            if (PK11_IsPresent(slot)) {
1171
0
                VCard *vcard;
1172
0
                vcard = vcard_emul_mirror_card(vreader);
1173
0
                vreader_insert_card(vreader, vcard);
1174
0
                vcard_emul_init_series(vreader, vcard);
1175
0
                g_debug("%s: Added card to the reader %s", __func__,
1176
0
                        vreader_get_name(vreader));
1177
0
                vcard_free(vcard);
1178
0
            }
1179
0
            vreader_free(vreader);
1180
0
        }
1181
0
        vcard_emul_new_event_thread(module);
1182
0
    }
1183
0
    SECMOD_ReleaseReadLock(module_lock);
1184
0
    nss_emul_init = PR_TRUE;
1185
1186
0
    return VCARD_EMUL_OK;
1187
2
}
1188
1189
/* Recreate card insert events for all readers (user should
1190
 * deduce implied reader insert. perhaps do a reader insert as well?)
1191
 */
1192
void
1193
vcard_emul_replay_insertion_events(void)
1194
0
{
1195
0
    VReaderListEntry *current_entry;
1196
0
    VReaderListEntry *next_entry;
1197
0
    VReaderList *list = vreader_get_reader_list();
1198
1199
0
    for (current_entry = vreader_list_get_first(list); current_entry;
1200
0
            current_entry = next_entry) {
1201
0
        VReader *vreader = vreader_list_get_reader(current_entry);
1202
0
        next_entry = vreader_list_get_next(current_entry);
1203
0
        vreader_queue_card_event(vreader);
1204
0
    }
1205
1206
0
    vreader_list_delete(list);
1207
0
}
1208
1209
VCardEmulError
1210
vcard_emul_finalize(void)
1211
2
{
1212
2
    SECStatus rv;
1213
1214
2
    rv = NSS_ShutdownContext(nss_ctx);
1215
2
    if (rv != SECSuccess) {
1216
0
        g_debug("%s: NSS_ShutdownContext failed.", __func__);
1217
0
        return VCARD_EMUL_FAIL;
1218
0
    }
1219
2
    nss_ctx = NULL;
1220
1221
2
    return VCARD_EMUL_OK;
1222
2
}
1223
1224
/*
1225
 *  Silly little functions to help parsing our argument string
1226
 */
1227
static int
1228
count_tokens(const char *str, char token, char token_end)
1229
2
{
1230
2
    int count = 0;
1231
1232
36
    for (; *str; str++) {
1233
36
        if (*str == token) {
1234
4
            count++;
1235
4
        }
1236
36
        if (*str == token_end) {
1237
2
            break;
1238
2
        }
1239
36
    }
1240
2
    return count;
1241
2
}
1242
1243
static const char *
1244
strip(const char *str)
1245
28
{
1246
32
    for (; *str && isspace(*str); str++) {
1247
4
    }
1248
28
    return str;
1249
28
}
1250
1251
static const char *
1252
find_blank(const char *str)
1253
2
{
1254
6
    for (; *str && !isspace(*str); str++) {
1255
4
    }
1256
2
    return str;
1257
2
}
1258
1259
1260
/*
1261
 *  We really want to use some existing argument parsing library here. That
1262
 *  would give us a consistent look */
1263
static VCardEmulOptions options;
1264
2
#define READER_STEP 4
1265
1266
/* Expects "args" to be at the beginning of a token (ie right after the ','
1267
 * ending the previous token), and puts the next token start in "token",
1268
 * and its length in "token_length". "token" will not be nul-terminated.
1269
 * After calling the macro, "args" will be advanced to the beginning of
1270
 * the next token.
1271
 */
1272
#define NEXT_TOKEN(token) \
1273
8
            (token) = args; \
1274
8
            args = strpbrk(args, ",)"); \
1275
8
            if (args == NULL || *args == 0 || *args == ')') { \
1276
0
                fprintf(stderr, "Error: invalid soft specification.\n"); \
1277
0
                goto fail; \
1278
0
            } \
1279
8
            (token##_length) = args - (token); \
1280
8
            args = strip(args+1);
1281
1282
VCardEmulOptions *
1283
vcard_emul_options(const char *args)
1284
2
{
1285
2
    int i, j, reader_count = 0;
1286
2
    VCardEmulOptions *opts;
1287
1288
    /* Allow the future use of allocating the options structure on the fly */
1289
2
    memcpy(&options, &default_options, sizeof(options));
1290
2
    opts = &options;
1291
1292
6
    do {
1293
6
        args = strip(args); /* strip off the leading spaces */
1294
6
        if (*args == ',') {
1295
0
            args++;
1296
0
            continue;
1297
0
        }
1298
        /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
1299
         *       cert_2,cert_3...) */
1300
6
        if (strncmp(args, "soft=", 5) == 0) {
1301
2
            const char *name;
1302
2
            size_t name_length;
1303
2
            const char *vname;
1304
2
            size_t vname_length;
1305
2
            const char *type_params;
1306
2
            size_t type_params_length;
1307
2
            char type_str[100];
1308
2
            VCardEmulType type;
1309
2
            int count;
1310
2
            VirtualReaderOptions *vreaderOpt;
1311
1312
2
            args = strip(args + 5);
1313
2
            if (*args != '(') {
1314
0
                fprintf(stderr, "Error: invalid soft specification.\n");
1315
0
                goto fail;
1316
0
            }
1317
2
            args = strip(args+1);
1318
1319
2
            NEXT_TOKEN(name)
1320
2
            NEXT_TOKEN(vname)
1321
2
            NEXT_TOKEN(type_params)
1322
2
            type_params_length = MIN(type_params_length, sizeof(type_str)-1);
1323
2
            memcpy(type_str, type_params, type_params_length);
1324
2
            type_str[type_params_length] = '\0';
1325
2
            type = vcard_emul_type_from_string(type_str);
1326
2
            if (type == VCARD_EMUL_NONE) {
1327
0
                fprintf(stderr, "Error: invalid smartcard type '%s'.\n",
1328
0
                        type_str);
1329
0
                goto fail;
1330
0
            }
1331
1332
4
            NEXT_TOKEN(type_params)
1333
1334
4
            if (*args == 0) {
1335
0
                fprintf(stderr, "Error: missing cert specification.\n");
1336
0
                goto fail;
1337
0
            }
1338
1339
2
            if (opts->vreader_count >= reader_count) {
1340
2
                reader_count += READER_STEP;
1341
2
                opts->vreader = g_renew(VirtualReaderOptions, opts->vreader,
1342
2
                                        reader_count);
1343
2
            }
1344
2
            vreaderOpt = &opts->vreader[opts->vreader_count];
1345
2
            vreaderOpt->name = g_strndup(name, name_length);
1346
2
            vreaderOpt->vname = g_strndup(vname, vname_length);
1347
2
            vreaderOpt->card_type = type;
1348
2
            vreaderOpt->type_params =
1349
2
                g_strndup(type_params, type_params_length);
1350
2
            count = count_tokens(args, ',', ')') + 1;
1351
2
            vreaderOpt->cert_count = count;
1352
2
            vreaderOpt->cert_name = g_new(char *, count);
1353
8
            for (i = 0; i < count; i++) {
1354
6
                const char *cert = args;
1355
6
                args = strpbrk(args, ",)");
1356
6
                vreaderOpt->cert_name[i] = g_strndup(cert, args - cert);
1357
6
                args = strip(args+1);
1358
6
            }
1359
2
            if (*args == ')') {
1360
0
                args++;
1361
0
            }
1362
2
            opts->vreader_count++;
1363
        /* use_hw= */
1364
4
        } else if (strncmp(args, "use_hw=", 7) == 0) {
1365
2
            args = strip(args+7);
1366
2
            if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
1367
2
                opts->use_hw = USE_HW_NO;
1368
2
            } else if (strncmp(args, "removable", 9) == 0) {
1369
0
                opts->use_hw = USE_HW_REMOVABLE;
1370
0
            } else {
1371
0
                opts->use_hw = USE_HW_YES;
1372
0
            }
1373
2
            args = find_blank(args);
1374
        /* hw_type= */
1375
2
        } else if (strncmp(args, "hw_type=", 8) == 0) {
1376
0
            args = strip(args+8);
1377
0
            opts->hw_card_type = vcard_emul_type_from_string(args);
1378
0
            if (opts->hw_card_type == VCARD_EMUL_NONE) {
1379
0
                fprintf(stderr, "Error: invalid smartcard type '%s'.\n",
1380
0
                        args);
1381
0
                goto fail;
1382
0
            }
1383
0
            args = find_blank(args);
1384
        /* hw_params= */
1385
2
        } else if (strncmp(args, "hw_params=", 10) == 0) {
1386
0
            const char *params;
1387
1388
0
            if (opts->hw_type_params != NULL) {
1389
0
                fprintf(stderr, "Error: redefinition of hw_params= is not allowed.\n");
1390
0
                goto fail;
1391
0
            }
1392
0
            args = strip(args+10);
1393
0
            params = args;
1394
0
            args = find_blank(args);
1395
0
            opts->hw_type_params = g_strndup(params, args-params);
1396
        /* db="/data/base/path" */
1397
2
        } else if (strncmp(args, "db=", 3) == 0) {
1398
2
            const char *db;
1399
1400
2
            if (opts->nss_db != NULL) {
1401
0
                fprintf(stderr, "Error: redefinition of db= is not allowed.\n");
1402
0
                goto fail;
1403
0
            }
1404
2
            args = strip(args+3);
1405
2
            if (*args != '"') {
1406
0
                fprintf(stderr, "Error: you must quote the file path.\n");
1407
0
                goto fail;
1408
0
            }
1409
2
            args++;
1410
2
            db = args;
1411
2
            args = strpbrk(args, "\"\n");
1412
2
            if (args == NULL) {
1413
0
                fprintf(stderr, "Error: invalid db argument.\n");
1414
0
                goto fail;
1415
0
            }
1416
2
            opts->nss_db = g_strndup(db, args-db);
1417
2
            if (*args != 0) {
1418
2
                args++;
1419
2
            }
1420
2
        } else if (strncmp(args, "nssemul", 7) == 0) {
1421
0
            opts->hw_card_type = VCARD_EMUL_CAC;
1422
0
            opts->use_hw = USE_HW_YES;
1423
0
            args = find_blank(args + 7);
1424
#if defined(ENABLE_PCSC)
1425
        } else if (strncmp(args, "passthru", 8) == 0) {
1426
            opts->hw_card_type = VCARD_EMUL_PASSTHRU;
1427
            opts->use_hw = USE_HW_YES;
1428
            args = find_blank(args + 8);
1429
#endif
1430
0
        } else {
1431
0
            fprintf(stderr, "Error: Unknown smartcard specification.\n");
1432
0
            goto fail;
1433
0
        }
1434
6
    } while (*args != 0);
1435
1436
2
    return opts;
1437
1438
0
fail:
1439
    /* Clean up what was allocated above on failure */
1440
0
    for (i = 0; i < opts->vreader_count; i++) {
1441
0
        g_free(opts->vreader[i].name);
1442
0
        g_free(opts->vreader[i].vname);
1443
0
        g_free(opts->vreader[i].type_params);
1444
0
        for (j = 0; j < opts->vreader[i].cert_count; j++) {
1445
0
            g_free(opts->vreader[i].cert_name[j]);
1446
0
        }
1447
0
        g_free(opts->vreader[i].cert_name);
1448
0
    }
1449
0
    g_free(opts->vreader);
1450
0
    g_free(opts->hw_type_params);
1451
0
    g_free(opts->nss_db);
1452
0
    return NULL;
1453
2
}
1454
1455
unsigned char *
1456
vcard_emul_read_object(VCard *card, const char *label,
1457
    unsigned int *ret_len)
1458
249
{
1459
249
    PK11SlotInfo *slot;
1460
249
    PK11GenericObject *obj, *firstObj, *myObj = NULL;
1461
249
    SECItem result;
1462
249
    SECStatus r;
1463
249
    unsigned char *ret;
1464
1465
249
    slot = vcard_emul_card_get_slot(card);
1466
1467
249
    firstObj = PK11_FindGenericObjects(slot, CKO_DATA);
1468
249
    g_debug("%s: Search for generic objects: got %p", __func__, firstObj);
1469
249
    for (obj = firstObj; obj; obj = PK11_GetNextGenericObject(obj)) {
1470
0
        int found = 0;
1471
0
        r = PK11_ReadRawAttribute(PK11_TypeGeneric, obj,
1472
0
            CKA_LABEL, &result);
1473
0
        if (r != SECSuccess) {
1474
0
            PK11_DestroyGenericObjects(firstObj);
1475
0
            return NULL;
1476
0
        }
1477
1478
0
        if (strlen(label) == result.len
1479
0
            && memcmp(label, result.data, result.len) == 0)
1480
0
            found = 1;
1481
1482
0
        PORT_Free(result.data);
1483
0
        result.data = NULL;
1484
1485
0
        if (found) {
1486
0
            PK11_UnlinkGenericObject(obj);
1487
0
            myObj = obj;
1488
0
            break;
1489
0
        }
1490
0
    }
1491
249
    PK11_DestroyGenericObjects(firstObj);
1492
1493
249
    if (!myObj)
1494
249
        return NULL;
1495
1496
0
    r = PK11_ReadRawAttribute(PK11_TypeGeneric, myObj,
1497
0
        CKA_VALUE, &result);
1498
0
    PK11_DestroyGenericObject(myObj);
1499
0
    if (r != SECSuccess)
1500
0
        return NULL;
1501
1502
0
    *ret_len = result.len;
1503
0
    ret = g_memdup2(result.data, result.len);
1504
0
    PORT_Free(result.data);
1505
0
    return ret;
1506
0
}
1507
1508
void
1509
vcard_emul_usage(void)
1510
0
{
1511
0
   fprintf(stderr,
1512
0
"emul args: comma separated list of the following arguments\n"
1513
0
" db={nss_database}               (default sql:/etc/pki/nssdb)\n"
1514
0
" use_hw=[yes|no|removable]       (default yes)\n"
1515
0
" hw_type={card_type_to_emulate}  (default CAC)\n"
1516
0
" hw_params={param_for_card}      (default \"\")\n"
1517
0
" nssemul                         (alias for use_hw=yes, hw_type=CAC)\n"
1518
#if defined(ENABLE_PCSC)
1519
" passthru                        (alias for use_hw=yes, hw_type=PASSTHRU)\n"
1520
#endif
1521
0
" soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
1522
0
"       {cert1},{cert2},{cert3}    (default none)\n"
1523
0
"\n"
1524
0
"  {nss_database}          The location of the NSS cert & key database\n"
1525
0
"  {card_type_to_emulate}  What card interface to present to the guest\n"
1526
0
"  {param_for_card}        Card interface specific parameters\n"
1527
0
"  {slot_name}             NSS slot that contains the certs\n"
1528
0
"  {vreader_name}          Virtual reader name to present to the guest\n"
1529
0
"  {certN}                 Nickname of the certificate n on the virtual card\n"
1530
0
"\n"
1531
0
"These parameters come as a single string separated by blanks or newlines."
1532
0
"\n"
1533
0
"Unless use_hw is set to no, all tokens that look like removable hardware\n"
1534
0
"tokens will be presented to the guest using the emulator specified by\n"
1535
0
"hw_type, and parameters of hw_params. If use_hw is set to 'removable', "
1536
0
"present any removable token.\n"
1537
0
"\n"
1538
0
"If more one or more soft= parameters are specified, these readers will be\n"
1539
0
"presented to the guest\n"
1540
#if defined(ENABLE_PCSC)
1541
"\n"
1542
"If a hw_type of PASSTHRU is given, a connection will be made to the hardware\n"
1543
"using libpcscslite.  Note that in that case, no soft cards are permitted.\n"
1544
#endif
1545
0
);
1546
0
}
1547
/* vim: set ts=4 sw=4 tw=0 noet expandtab: */