Coverage Report

Created: 2025-07-27 06:08

/src/nss/lib/pk11wrap/pk11nobj.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
/*
5
 * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects,
6
 * etc).
7
 */
8
9
#include <stddef.h>
10
11
#include "secport.h"
12
#include "seccomon.h"
13
#include "secmod.h"
14
#include "secmodi.h"
15
#include "secmodti.h"
16
#include "pkcs11.h"
17
#include "pk11func.h"
18
#include "cert.h"
19
#include "certi.h"
20
#include "secitem.h"
21
#include "sechash.h"
22
#include "secoid.h"
23
24
#include "certdb.h"
25
#include "secerr.h"
26
27
#include "pki3hack.h"
28
#include "dev3hack.h"
29
30
#include "devm.h"
31
#include "pki.h"
32
#include "pkim.h"
33
34
extern const NSSError NSS_ERROR_NOT_FOUND;
35
36
PRBool
37
pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
38
0
{
39
0
    return nssTrust_HandleTrustForCERTCert(cert, trust);
40
0
}
41
42
static SECStatus
43
pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
44
0
{
45
0
    SECItem derCrl;
46
0
    CERTCrlHeadNode *head = (CERTCrlHeadNode *)arg;
47
0
    CERTCrlNode *new_node = NULL;
48
0
    CK_ATTRIBUTE fetchCrl[3] = {
49
0
        { CKA_VALUE, NULL, 0 },
50
0
        { CKA_NSS_KRL, NULL, 0 },
51
0
        { CKA_NSS_URL, NULL, 0 },
52
0
    };
53
0
    const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]);
54
0
    CK_RV crv;
55
0
    SECStatus rv = SECFailure;
56
57
0
    crv = PK11_GetAttributes(head->arena, slot, crlID, fetchCrl, fetchCrlSize);
58
0
    if (CKR_OK != crv) {
59
0
        PORT_SetError(PK11_MapError(crv));
60
0
        goto loser;
61
0
    }
62
63
0
    if (!fetchCrl[1].pValue) {
64
0
        PORT_SetError(SEC_ERROR_CRL_INVALID);
65
0
        goto loser;
66
0
    }
67
68
0
    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
69
0
    if (new_node == NULL) {
70
0
        goto loser;
71
0
    }
72
73
0
    if (*((CK_BBOOL *)fetchCrl[1].pValue))
74
0
        new_node->type = SEC_KRL_TYPE;
75
0
    else
76
0
        new_node->type = SEC_CRL_TYPE;
77
78
0
    derCrl.type = siBuffer;
79
0
    derCrl.data = (unsigned char *)fetchCrl[0].pValue;
80
0
    derCrl.len = fetchCrl[0].ulValueLen;
81
0
    new_node->crl = CERT_DecodeDERCrl(head->arena, &derCrl, new_node->type);
82
0
    if (new_node->crl == NULL) {
83
0
        goto loser;
84
0
    }
85
86
0
    if (fetchCrl[2].pValue) {
87
0
        int nnlen = fetchCrl[2].ulValueLen;
88
0
        new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen + 1);
89
0
        if (!new_node->crl->url) {
90
0
            goto loser;
91
0
        }
92
0
        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
93
0
        new_node->crl->url[nnlen] = 0;
94
0
    } else {
95
0
        new_node->crl->url = NULL;
96
0
    }
97
98
0
    new_node->next = NULL;
99
0
    if (head->last) {
100
0
        head->last->next = new_node;
101
0
        head->last = new_node;
102
0
    } else {
103
0
        head->first = head->last = new_node;
104
0
    }
105
0
    rv = SECSuccess;
106
107
0
loser:
108
0
    return (rv);
109
0
}
110
111
/*
112
 * Return a list of all the CRLs .
113
 * CRLs are allocated in the list's arena.
114
 */
115
SECStatus
116
PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx)
117
0
{
118
0
    pk11TraverseSlot creater;
119
0
    CK_ATTRIBUTE theTemplate[2];
120
0
    CK_ATTRIBUTE *attrs;
121
0
    CK_OBJECT_CLASS certClass = CKO_NSS_CRL;
122
0
    CK_BBOOL isKrl = CK_FALSE;
123
124
0
    attrs = theTemplate;
125
0
    PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
126
0
    attrs++;
127
0
    if (type != -1) {
128
0
        isKrl = (CK_BBOOL)(type == SEC_KRL_TYPE);
129
0
        PK11_SETATTRS(attrs, CKA_NSS_KRL, &isKrl, sizeof(isKrl));
130
0
        attrs++;
131
0
    }
132
133
0
    creater.callback = pk11_CollectCrls;
134
0
    creater.callbackArg = (void *)nodes;
135
0
    creater.findTemplate = theTemplate;
136
0
    creater.templateCount = (attrs - theTemplate);
137
138
0
    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
139
0
}
140
141
struct crlOptionsStr {
142
    CERTCrlHeadNode *head;
143
    PRInt32 decodeOptions;
144
};
145
146
typedef struct crlOptionsStr crlOptions;
147
148
static SECStatus
149
pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
150
                          void *arg)
151
0
{
152
0
    SECItem *derCrl = NULL;
153
0
    crlOptions *options = (crlOptions *)arg;
154
0
    CERTCrlHeadNode *head = options->head;
155
0
    CERTCrlNode *new_node = NULL;
156
0
    CK_ATTRIBUTE fetchCrl[3] = {
157
0
        { CKA_VALUE, NULL, 0 },
158
0
        { CKA_NSS_KRL, NULL, 0 },
159
0
        { CKA_NSS_URL, NULL, 0 },
160
0
    };
161
0
    const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]);
162
0
    CK_RV crv;
163
0
    SECStatus rv = SECFailure;
164
0
    PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
165
                                  successfully */
166
0
    int i;
167
168
0
    crv = PK11_GetAttributes(NULL, slot, crlID, fetchCrl, fetchCrlSize);
169
0
    if (CKR_OK != crv) {
170
0
        PORT_SetError(PK11_MapError(crv));
171
0
        goto loser;
172
0
    }
173
174
0
    if (!fetchCrl[1].pValue) {
175
        /* reject KRLs */
176
0
        PORT_SetError(SEC_ERROR_CRL_INVALID);
177
0
        goto loser;
178
0
    }
179
180
0
    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
181
0
                                              sizeof(CERTCrlNode));
182
0
    if (new_node == NULL) {
183
0
        goto loser;
184
0
    }
185
186
0
    new_node->type = SEC_CRL_TYPE;
187
188
0
    derCrl = SECITEM_AllocItem(NULL, NULL, 0);
189
0
    if (!derCrl) {
190
0
        goto loser;
191
0
    }
192
0
    derCrl->type = siBuffer;
193
0
    derCrl->data = (unsigned char *)fetchCrl[0].pValue;
194
0
    derCrl->len = fetchCrl[0].ulValueLen;
195
0
    new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, new_node->type,
196
0
                                               options->decodeOptions);
197
0
    if (new_node->crl == NULL) {
198
0
        goto loser;
199
0
    }
200
0
    adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
201
                          we won't need to free it upon exit */
202
203
0
    if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
204
        /* copy the URL if there is one */
205
0
        int nnlen = fetchCrl[2].ulValueLen;
206
0
        new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena,
207
0
                                                     nnlen + 1);
208
0
        if (!new_node->crl->url) {
209
0
            goto loser;
210
0
        }
211
0
        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
212
0
        new_node->crl->url[nnlen] = 0;
213
0
    } else {
214
0
        new_node->crl->url = NULL;
215
0
    }
216
217
0
    new_node->next = NULL;
218
0
    if (head->last) {
219
0
        head->last->next = new_node;
220
0
        head->last = new_node;
221
0
    } else {
222
0
        head->first = head->last = new_node;
223
0
    }
224
0
    rv = SECSuccess;
225
0
    new_node->crl->slot = PK11_ReferenceSlot(slot);
226
0
    new_node->crl->pkcs11ID = crlID;
227
228
0
loser:
229
    /* free attributes that weren't adopted by the CRL */
230
0
    for (i = 1; i < fetchCrlSize; i++) {
231
0
        if (fetchCrl[i].pValue) {
232
0
            PORT_Free(fetchCrl[i].pValue);
233
0
        }
234
0
    }
235
    /* free the DER if the CRL object didn't adopt it */
236
0
    if (fetchCrl[0].pValue && PR_FALSE == adopted) {
237
0
        PORT_Free(fetchCrl[0].pValue);
238
0
    }
239
0
    if (derCrl && !adopted) {
240
        /* clear the data fields, which we already took care of above */
241
0
        derCrl->data = NULL;
242
0
        derCrl->len = 0;
243
        /* free the memory for the SECItem structure itself */
244
0
        SECITEM_FreeItem(derCrl, PR_TRUE);
245
0
    }
246
0
    return (rv);
247
0
}
248
249
/*
250
 * Return a list of CRLs matching specified issuer and type
251
 * CRLs are not allocated in the list's arena, but rather in their own,
252
 * arena, so that they can be used individually in the CRL cache .
253
 * CRLs are always partially decoded for efficiency.
254
 */
255
SECStatus
256
pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem *issuer,
257
                  void *wincx)
258
0
{
259
0
    pk11TraverseSlot creater;
260
0
    CK_ATTRIBUTE theTemplate[2];
261
0
    CK_ATTRIBUTE *attrs;
262
0
    CK_OBJECT_CLASS crlClass = CKO_NSS_CRL;
263
0
    crlOptions options;
264
265
0
    attrs = theTemplate;
266
0
    PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass));
267
0
    attrs++;
268
269
0
    options.head = nodes;
270
271
    /* - do a partial decoding - we don't need to decode the entries while fetching
272
       - don't copy the DER for optimal performance - CRL can be very large
273
       - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
274
       - keep bad CRL objects. The CRL cache is interested in them, for
275
         security purposes. Bad CRL objects are a sign of something amiss.
276
     */
277
278
0
    options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
279
0
                            CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
280
0
    if (issuer) {
281
0
        PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len);
282
0
        attrs++;
283
0
    }
284
285
0
    creater.callback = pk11_RetrieveCrlsCallback;
286
0
    creater.callbackArg = (void *)&options;
287
0
    creater.findTemplate = theTemplate;
288
0
    creater.templateCount = (attrs - theTemplate);
289
290
0
    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
291
0
}
292
293
/*
294
 * return the crl associated with a derSubjectName
295
 */
296
SECItem *
297
PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
298
                   SECItem *name, int type, char **pUrl)
299
0
{
300
0
    NSSCRL **crls, **crlp, *crl = NULL;
301
0
    NSSDER subject;
302
0
    SECItem *rvItem;
303
0
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
304
0
    char *url = NULL;
305
306
0
    PORT_SetError(0);
307
0
    NSSITEM_FROM_SECITEM(&subject, name);
308
0
    if (*slot) {
309
0
        nssCryptokiObject **instances;
310
0
        nssPKIObjectCollection *collection;
311
0
        nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
312
0
        NSSToken *token = PK11Slot_GetNSSToken(*slot);
313
0
        if (!token) {
314
0
            goto loser;
315
0
        }
316
0
        collection = nssCRLCollection_Create(td, NULL);
317
0
        if (!collection) {
318
0
            (void)nssToken_Destroy(token);
319
0
            goto loser;
320
0
        }
321
0
        instances = nssToken_FindCRLsBySubject(token, NULL, &subject,
322
0
                                               tokenOnly, 0, NULL);
323
0
        (void)nssToken_Destroy(token);
324
0
        nssPKIObjectCollection_AddInstances(collection, instances, 0);
325
0
        nss_ZFreeIf(instances);
326
0
        crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
327
0
        nssPKIObjectCollection_Destroy(collection);
328
0
    } else {
329
0
        crls = nssTrustDomain_FindCRLsBySubject(td, &subject);
330
0
    }
331
0
    if ((!crls) || (*crls == NULL)) {
332
0
        if (crls) {
333
0
            nssCRLArray_Destroy(crls);
334
0
        }
335
0
        if (NSS_GetError() == NSS_ERROR_NOT_FOUND) {
336
0
            PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
337
0
        }
338
0
        goto loser;
339
0
    }
340
0
    for (crlp = crls; *crlp; crlp++) {
341
0
        if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) ||
342
0
            ((*crlp)->isKRL && type != SEC_CRL_TYPE)) {
343
0
            crl = nssCRL_AddRef(*crlp);
344
0
            break;
345
0
        }
346
0
    }
347
0
    nssCRLArray_Destroy(crls);
348
0
    if (!crl) {
349
        /* CRL collection was found, but no interesting CRL's were on it.
350
         * Not an error */
351
0
        PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
352
0
        goto loser;
353
0
    }
354
0
    if (crl->url) {
355
0
        url = PORT_Strdup(crl->url);
356
0
        if (!url) {
357
0
            goto loser;
358
0
        }
359
0
    }
360
0
    rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size);
361
0
    if (!rvItem) {
362
0
        goto loser;
363
0
    }
364
0
    memcpy(rvItem->data, crl->encoding.data, crl->encoding.size);
365
0
    *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot);
366
0
    *crlHandle = crl->object.instances[0]->handle;
367
0
    *pUrl = url;
368
0
    nssCRL_Destroy(crl);
369
0
    return rvItem;
370
371
0
loser:
372
0
    if (url)
373
0
        PORT_Free(url);
374
0
    if (crl)
375
0
        nssCRL_Destroy(crl);
376
0
    if (PORT_GetError() == 0) {
377
0
        PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
378
0
    }
379
0
    return NULL;
380
0
}
381
382
CK_OBJECT_HANDLE
383
PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name,
384
            char *url, int type)
385
0
{
386
0
    NSSItem derCRL, derSubject;
387
0
    NSSToken *token;
388
0
    nssCryptokiObject *object;
389
0
    PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE;
390
0
    CK_OBJECT_HANDLE rvH;
391
392
0
    NSSITEM_FROM_SECITEM(&derSubject, name);
393
0
    NSSITEM_FROM_SECITEM(&derCRL, crl);
394
0
    token = PK11Slot_GetNSSToken(slot);
395
0
    if (!token) {
396
0
        PORT_SetError(SEC_ERROR_NO_TOKEN);
397
0
        return CK_INVALID_HANDLE;
398
0
    }
399
0
    object = nssToken_ImportCRL(token, NULL,
400
0
                                &derSubject, &derCRL, isKRL, url, PR_TRUE);
401
0
    (void)nssToken_Destroy(token);
402
403
0
    if (object) {
404
0
        rvH = object->handle;
405
0
        nssCryptokiObject_Destroy(object);
406
0
    } else {
407
0
        rvH = CK_INVALID_HANDLE;
408
0
        PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED);
409
0
    }
410
0
    return rvH;
411
0
}
412
413
/*
414
 * delete a crl.
415
 */
416
SECStatus
417
SEC_DeletePermCRL(CERTSignedCrl *crl)
418
0
{
419
0
    PRStatus status;
420
0
    nssCryptokiObject *object;
421
0
    NSSToken *token;
422
0
    PK11SlotInfo *slot = crl->slot;
423
424
0
    if (slot == NULL) {
425
0
        PORT_Assert(slot);
426
        /* shouldn't happen */
427
0
        PORT_SetError(SEC_ERROR_CRL_INVALID);
428
0
        return SECFailure;
429
0
    }
430
431
0
    token = PK11Slot_GetNSSToken(slot);
432
0
    if (!token) {
433
0
        return SECFailure;
434
0
    }
435
0
    object = nss_ZNEW(NULL, nssCryptokiObject);
436
0
    if (!object) {
437
0
        (void)nssToken_Destroy(token);
438
0
        return SECFailure;
439
0
    }
440
0
    object->token = token; /* object takes ownership */
441
0
    object->handle = crl->pkcs11ID;
442
0
    object->isTokenObject = PR_TRUE;
443
444
0
    status = nssToken_DeleteStoredObject(object);
445
446
0
    nssCryptokiObject_Destroy(object);
447
0
    return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
448
0
}
449
450
/* search with email with and without NULL
451
 * The sql database accepts the email with a NULL as it's written,
452
 * the dbm database strips the NULL on write so won't match if
453
 * it's there on find */
454
static CK_OBJECT_HANDLE
455
pk11_FindSMimeObjectByTemplate(PK11SlotInfo *slot,
456
                               CK_ATTRIBUTE *theTemplate, size_t tsize)
457
0
{
458
0
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
459
0
    CK_ATTRIBUTE *last;
460
461
0
    PORT_Assert(tsize != 0);
462
463
0
    smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize);
464
0
    if (smimeh != CK_INVALID_HANDLE) {
465
0
        return smimeh;
466
0
    }
467
0
    last = &theTemplate[tsize - 1];
468
0
    if ((last->type == CKA_NSS_EMAIL) && (last->ulValueLen != 0)) {
469
0
        CK_ULONG save_len = last->ulValueLen;
470
0
        last->ulValueLen--;
471
0
        smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize);
472
0
        last->ulValueLen = save_len; /* restore the original */
473
0
        return smimeh;
474
0
    }
475
0
    return CK_INVALID_HANDLE;
476
0
}
477
478
/*
479
 * return the certificate associated with a derCert
480
 */
481
SECItem *
482
PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
483
                      SECItem *name, SECItem **profileTime)
484
0
{
485
0
    CK_OBJECT_CLASS smimeClass = CKO_NSS_SMIME;
486
0
    CK_ATTRIBUTE theTemplate[] = {
487
0
        { CKA_CLASS, NULL, 0 },
488
0
        { CKA_SUBJECT, NULL, 0 },
489
0
        { CKA_NSS_EMAIL, NULL, 0 },
490
0
    };
491
0
    CK_ATTRIBUTE smimeData[] = {
492
0
        { CKA_SUBJECT, NULL, 0 },
493
0
        { CKA_VALUE, NULL, 0 },
494
0
    };
495
    /* if you change the array, change the variable below as well */
496
0
    const size_t tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
497
0
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
498
0
    CK_ATTRIBUTE *attrs = theTemplate;
499
0
    CK_RV crv;
500
0
    SECItem *emailProfile = NULL;
501
502
0
    if (!emailAddr || !emailAddr[0]) {
503
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
504
0
        return NULL;
505
0
    }
506
507
0
    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass));
508
0
    attrs++;
509
0
    PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len);
510
0
    attrs++;
511
0
    PK11_SETATTRS(attrs, CKA_NSS_EMAIL, emailAddr, strlen(emailAddr) + 1);
512
0
    attrs++;
513
514
0
    if (*slot) {
515
0
        smimeh = pk11_FindSMimeObjectByTemplate(*slot, theTemplate, tsize);
516
0
    } else {
517
0
        PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
518
0
                                               PR_FALSE, PR_TRUE, NULL);
519
0
        PK11SlotListElement *le;
520
521
0
        if (!list) {
522
0
            return NULL;
523
0
        }
524
        /* loop through all the slots */
525
0
        for (le = list->head; le; le = le->next) {
526
0
            smimeh = pk11_FindSMimeObjectByTemplate(le->slot, theTemplate, tsize);
527
0
            if (smimeh != CK_INVALID_HANDLE) {
528
0
                *slot = PK11_ReferenceSlot(le->slot);
529
0
                break;
530
0
            }
531
0
        }
532
0
        PK11_FreeSlotList(list);
533
0
    }
534
535
0
    if (smimeh == CK_INVALID_HANDLE) {
536
0
        PORT_SetError(SEC_ERROR_NO_KRL);
537
0
        return NULL;
538
0
    }
539
540
0
    if (profileTime) {
541
0
        PK11_SETATTRS(smimeData, CKA_NSS_SMIME_TIMESTAMP, NULL, 0);
542
0
    }
543
544
0
    crv = PK11_GetAttributes(NULL, *slot, smimeh, smimeData, 2);
545
0
    if (crv != CKR_OK) {
546
0
        PORT_SetError(PK11_MapError(crv));
547
0
        goto loser;
548
0
    }
549
550
0
    if (!profileTime) {
551
0
        SECItem profileSubject;
552
553
0
        profileSubject.data = (unsigned char *)smimeData[0].pValue;
554
0
        profileSubject.len = smimeData[0].ulValueLen;
555
0
        if (!SECITEM_ItemsAreEqual(&profileSubject, name)) {
556
0
            goto loser;
557
0
        }
558
0
    }
559
560
0
    emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
561
0
    if (emailProfile == NULL) {
562
0
        goto loser;
563
0
    }
564
565
0
    emailProfile->data = (unsigned char *)smimeData[1].pValue;
566
0
    emailProfile->len = smimeData[1].ulValueLen;
567
568
0
    if (profileTime) {
569
0
        *profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
570
0
        if (*profileTime) {
571
0
            (*profileTime)->data = (unsigned char *)smimeData[0].pValue;
572
0
            (*profileTime)->len = smimeData[0].ulValueLen;
573
0
        }
574
0
    }
575
576
0
loser:
577
0
    if (emailProfile == NULL) {
578
0
        if (smimeData[1].pValue) {
579
0
            PORT_Free(smimeData[1].pValue);
580
0
        }
581
0
    }
582
0
    if (profileTime == NULL || *profileTime == NULL) {
583
0
        if (smimeData[0].pValue) {
584
0
            PORT_Free(smimeData[0].pValue);
585
0
        }
586
0
    }
587
0
    return emailProfile;
588
0
}
589
590
SECStatus
591
PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
592
                      SECItem *emailProfile, SECItem *profileTime)
593
0
{
594
0
    CK_OBJECT_CLASS smimeClass = CKO_NSS_SMIME;
595
0
    CK_BBOOL ck_true = CK_TRUE;
596
0
    CK_ATTRIBUTE theTemplate[] = {
597
0
        { CKA_CLASS, NULL, 0 },
598
0
        { CKA_TOKEN, NULL, 0 },
599
0
        { CKA_SUBJECT, NULL, 0 },
600
0
        { CKA_NSS_EMAIL, NULL, 0 },
601
0
        { CKA_NSS_SMIME_TIMESTAMP, NULL, 0 },
602
0
        { CKA_VALUE, NULL, 0 }
603
0
    };
604
    /* if you change the array, change the variable below as well */
605
0
    int realSize = 0;
606
0
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
607
0
    CK_ATTRIBUTE *attrs = theTemplate;
608
0
    CK_SESSION_HANDLE rwsession;
609
0
    PK11SlotInfo *free_slot = NULL;
610
0
    CK_RV crv;
611
0
#ifdef DEBUG
612
0
    int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
613
0
#endif
614
615
0
    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass));
616
0
    attrs++;
617
0
    PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true));
618
0
    attrs++;
619
0
    PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len);
620
0
    attrs++;
621
0
    PK11_SETATTRS(attrs, CKA_NSS_EMAIL,
622
0
                  emailAddr, PORT_Strlen(emailAddr) + 1);
623
0
    attrs++;
624
0
    if (profileTime) {
625
0
        PK11_SETATTRS(attrs, CKA_NSS_SMIME_TIMESTAMP, profileTime->data,
626
0
                      profileTime->len);
627
0
        attrs++;
628
0
        PK11_SETATTRS(attrs, CKA_VALUE, emailProfile->data,
629
0
                      emailProfile->len);
630
0
        attrs++;
631
0
    }
632
0
    realSize = attrs - theTemplate;
633
0
    PORT_Assert(realSize <= tsize);
634
635
0
    if (slot == NULL) {
636
0
        free_slot = slot = PK11_GetInternalKeySlot();
637
        /* we need to free the key slot in the end!!! */
638
0
    }
639
640
0
    rwsession = PK11_GetRWSession(slot);
641
0
    if (rwsession == CK_INVALID_HANDLE) {
642
0
        PORT_SetError(SEC_ERROR_READ_ONLY);
643
0
        if (free_slot) {
644
0
            PK11_FreeSlot(free_slot);
645
0
        }
646
0
        return SECFailure;
647
0
    }
648
649
0
    crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, theTemplate, realSize, &smimeh);
650
0
    if (crv != CKR_OK) {
651
0
        PORT_SetError(PK11_MapError(crv));
652
0
    }
653
654
0
    PK11_RestoreROSession(slot, rwsession);
655
656
0
    if (free_slot) {
657
0
        PK11_FreeSlot(free_slot);
658
0
    }
659
0
    return SECSuccess;
660
0
}
661
662
CERTSignedCrl *crl_storeCRL(PK11SlotInfo *slot, char *url,
663
                            CERTSignedCrl *newCrl, SECItem *derCrl, int type);
664
665
/* import the CRL into the token */
666
667
CERTSignedCrl *
668
PK11_ImportCRL(PK11SlotInfo *slot, SECItem *derCRL, char *url,
669
               int type, void *wincx, PRInt32 importOptions, PLArenaPool *arena,
670
               PRInt32 decodeoptions)
671
0
{
672
0
    CERTSignedCrl *newCrl, *crl;
673
0
    SECStatus rv;
674
0
    CERTCertificate *caCert = NULL;
675
676
0
    newCrl = crl = NULL;
677
678
0
    do {
679
0
        newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type,
680
0
                                            decodeoptions);
681
0
        if (newCrl == NULL) {
682
0
            if (type == SEC_CRL_TYPE) {
683
                /* only promote error when the error code is too generic */
684
0
                if (PORT_GetError() == SEC_ERROR_BAD_DER)
685
0
                    PORT_SetError(SEC_ERROR_CRL_INVALID);
686
0
            } else {
687
0
                PORT_SetError(SEC_ERROR_KRL_INVALID);
688
0
            }
689
0
            break;
690
0
        }
691
692
0
        if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)) {
693
0
            CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
694
0
            PR_ASSERT(handle != NULL);
695
0
            caCert = CERT_FindCertByName(handle,
696
0
                                         &newCrl->crl.derName);
697
0
            if (caCert == NULL) {
698
0
                PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
699
0
                break;
700
0
            }
701
702
            /* If caCert is a v3 certificate, make sure that it can be used for
703
               crl signing purpose */
704
0
            rv = CERT_CheckCertUsage(caCert, KU_CRL_SIGN);
705
0
            if (rv != SECSuccess) {
706
0
                break;
707
0
            }
708
709
0
            rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
710
0
                                       PR_Now(), wincx);
711
0
            if (rv != SECSuccess) {
712
0
                if (type == SEC_CRL_TYPE) {
713
0
                    PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
714
0
                } else {
715
0
                    PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
716
0
                }
717
0
                break;
718
0
            }
719
0
        }
720
721
0
        crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
722
723
0
    } while (0);
724
725
0
    if (crl == NULL) {
726
0
        SEC_DestroyCrl(newCrl);
727
0
    }
728
0
    if (caCert) {
729
0
        CERT_DestroyCertificate(caCert);
730
0
    }
731
0
    return (crl);
732
0
}