Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/dev/ckhelper.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
#include "pkcs11.h"
6
7
#ifndef DEVM_H
8
#include "devm.h"
9
#endif /* DEVM_H */
10
11
#ifndef CKHELPER_H
12
#include "ckhelper.h"
13
#endif /* CKHELPER_H */
14
15
extern const NSSError NSS_ERROR_DEVICE_ERROR;
16
17
static const CK_BBOOL s_true = CK_TRUE;
18
NSS_IMPLEMENT_DATA const NSSItem
19
    g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
20
21
static const CK_BBOOL s_false = CK_FALSE;
22
NSS_IMPLEMENT_DATA const NSSItem
23
    g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
24
25
static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
26
NSS_IMPLEMENT_DATA const NSSItem
27
    g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
28
29
static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
30
NSS_IMPLEMENT_DATA const NSSItem
31
    g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
32
33
static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
34
NSS_IMPLEMENT_DATA const NSSItem
35
    g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
36
37
static PRBool
38
is_string_attribute(
39
    CK_ATTRIBUTE_TYPE aType)
40
0
{
41
0
    PRBool isString;
42
0
    switch (aType) {
43
0
        case CKA_LABEL:
44
0
        case CKA_NSS_EMAIL:
45
0
            isString = PR_TRUE;
46
0
            break;
47
0
        default:
48
0
            isString = PR_FALSE;
49
0
            break;
50
0
    }
51
0
    return isString;
52
0
}
53
54
NSS_IMPLEMENT PRStatus
55
nssCKObject_GetAttributes(
56
    CK_OBJECT_HANDLE object,
57
    CK_ATTRIBUTE_PTR obj_template,
58
    CK_ULONG count,
59
    NSSArena *arenaOpt,
60
    nssSession *session,
61
    NSSSlot *slot)
62
0
{
63
0
    nssArenaMark *mark = NULL;
64
0
    CK_SESSION_HANDLE hSession;
65
0
    CK_ULONG i = 0;
66
0
    CK_RV ckrv;
67
0
    PRStatus nssrv;
68
0
    PRBool alloced = PR_FALSE;
69
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
70
0
    hSession = session->handle;
71
0
    if (arenaOpt) {
72
0
        mark = nssArena_Mark(arenaOpt);
73
0
        if (!mark) {
74
0
            goto loser;
75
0
        }
76
0
    }
77
0
    nssSession_EnterMonitor(session);
78
0
    /* XXX kinda hacky, if the storage size is already in the first template
79
0
     * item, then skip the alloc portion
80
0
     */
81
0
    if (obj_template[0].ulValueLen == 0) {
82
0
        /* Get the storage size needed for each attribute */
83
0
        ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
84
0
                                               object, obj_template, count);
85
0
        if (ckrv != CKR_OK &&
86
0
            ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
87
0
            ckrv != CKR_ATTRIBUTE_SENSITIVE) {
88
0
            nssSession_ExitMonitor(session);
89
0
            nss_SetError(NSS_ERROR_DEVICE_ERROR);
90
0
            goto loser;
91
0
        }
92
0
        /* Allocate memory for each attribute. */
93
0
        for (i = 0; i < count; i++) {
94
0
            CK_ULONG ulValueLen = obj_template[i].ulValueLen;
95
0
            if (ulValueLen == 0 || ulValueLen == (CK_ULONG)-1) {
96
0
                obj_template[i].pValue = NULL;
97
0
                obj_template[i].ulValueLen = 0;
98
0
                continue;
99
0
            }
100
0
            if (is_string_attribute(obj_template[i].type)) {
101
0
                ulValueLen++;
102
0
            }
103
0
            obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
104
0
            if (!obj_template[i].pValue) {
105
0
                nssSession_ExitMonitor(session);
106
0
                goto loser;
107
0
            }
108
0
        }
109
0
        alloced = PR_TRUE;
110
0
    }
111
0
    /* Obtain the actual attribute values. */
112
0
    ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
113
0
                                           object, obj_template, count);
114
0
    nssSession_ExitMonitor(session);
115
0
    if (ckrv != CKR_OK &&
116
0
        ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
117
0
        ckrv != CKR_ATTRIBUTE_SENSITIVE) {
118
0
        nss_SetError(NSS_ERROR_DEVICE_ERROR);
119
0
        goto loser;
120
0
    }
121
0
    if (alloced && arenaOpt) {
122
0
        nssrv = nssArena_Unmark(arenaOpt, mark);
123
0
        if (nssrv != PR_SUCCESS) {
124
0
            goto loser;
125
0
        }
126
0
    }
127
0
128
0
    if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
129
0
                      (ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
130
0
        /* old tokens would keep the length of '0' and not deal with any
131
0
         * of the attributes we passed. For those tokens read them one at
132
0
         * a time */
133
0
        for (i = 0; i < count; i++) {
134
0
            if ((obj_template[i].ulValueLen == 0) ||
135
0
                (obj_template[i].ulValueLen == -1)) {
136
0
                obj_template[i].ulValueLen = 0;
137
0
                (void)nssCKObject_GetAttributes(object, &obj_template[i], 1,
138
0
                                                arenaOpt, session, slot);
139
0
            }
140
0
        }
141
0
    }
142
0
    return PR_SUCCESS;
143
0
loser:
144
0
    if (alloced) {
145
0
        if (arenaOpt) {
146
0
            /* release all arena memory allocated before the failure. */
147
0
            (void)nssArena_Release(arenaOpt, mark);
148
0
        } else {
149
0
            CK_ULONG j;
150
0
            /* free each heap object that was allocated before the failure. */
151
0
            for (j = 0; j < i; j++) {
152
0
                nss_ZFreeIf(obj_template[j].pValue);
153
0
            }
154
0
        }
155
0
    }
156
0
    return PR_FAILURE;
157
0
}
158
159
NSS_IMPLEMENT PRStatus
160
nssCKObject_GetAttributeItem(
161
    CK_OBJECT_HANDLE object,
162
    CK_ATTRIBUTE_TYPE attribute,
163
    NSSArena *arenaOpt,
164
    nssSession *session,
165
    NSSSlot *slot,
166
    NSSItem *rvItem)
167
0
{
168
0
    CK_ATTRIBUTE attr = { 0, NULL, 0 };
169
0
    PRStatus nssrv;
170
0
    attr.type = attribute;
171
0
    nssrv = nssCKObject_GetAttributes(object, &attr, 1,
172
0
                                      arenaOpt, session, slot);
173
0
    if (nssrv != PR_SUCCESS) {
174
0
        return nssrv;
175
0
    }
176
0
    rvItem->data = (void *)attr.pValue;
177
0
    rvItem->size = (PRUint32)attr.ulValueLen;
178
0
    return PR_SUCCESS;
179
0
}
180
181
NSS_IMPLEMENT PRBool
182
nssCKObject_IsAttributeTrue(
183
    CK_OBJECT_HANDLE object,
184
    CK_ATTRIBUTE_TYPE attribute,
185
    nssSession *session,
186
    NSSSlot *slot,
187
    PRStatus *rvStatus)
188
0
{
189
0
    CK_BBOOL bool;
190
0
    CK_ATTRIBUTE_PTR attr;
191
0
    CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
192
0
    CK_RV ckrv;
193
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
194
0
    attr = &atemplate;
195
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
196
0
    nssSession_EnterMonitor(session);
197
0
    ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
198
0
                                           &atemplate, 1);
199
0
    nssSession_ExitMonitor(session);
200
0
    if (ckrv != CKR_OK) {
201
0
        *rvStatus = PR_FAILURE;
202
0
        return PR_FALSE;
203
0
    }
204
0
    *rvStatus = PR_SUCCESS;
205
0
    return (PRBool)(bool == CK_TRUE);
206
0
}
207
208
NSS_IMPLEMENT PRStatus
209
nssCKObject_SetAttributes(
210
    CK_OBJECT_HANDLE object,
211
    CK_ATTRIBUTE_PTR obj_template,
212
    CK_ULONG count,
213
    nssSession *session,
214
    NSSSlot *slot)
215
0
{
216
0
    CK_RV ckrv;
217
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
218
0
    nssSession_EnterMonitor(session);
219
0
    ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
220
0
                                           obj_template, count);
221
0
    nssSession_ExitMonitor(session);
222
0
    if (ckrv == CKR_OK) {
223
0
        return PR_SUCCESS;
224
0
    } else {
225
0
        return PR_FAILURE;
226
0
    }
227
0
}
228
229
NSS_IMPLEMENT PRBool
230
nssCKObject_IsTokenObjectTemplate(
231
    CK_ATTRIBUTE_PTR objectTemplate,
232
    CK_ULONG otsize)
233
0
{
234
0
    CK_ULONG ul;
235
0
    for (ul = 0; ul < otsize; ul++) {
236
0
        if (objectTemplate[ul].type == CKA_TOKEN) {
237
0
            return (*((CK_BBOOL *)objectTemplate[ul].pValue) == CK_TRUE);
238
0
        }
239
0
    }
240
0
    return PR_FALSE;
241
0
}
242
243
static NSSCertificateType
244
nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
245
0
{
246
0
    CK_CERTIFICATE_TYPE ckCertType;
247
0
    if (!attrib->pValue) {
248
0
        /* default to PKIX */
249
0
        return NSSCertificateType_PKIX;
250
0
    }
251
0
    ckCertType = *((CK_ULONG *)attrib->pValue);
252
0
    switch (ckCertType) {
253
0
        case CKC_X_509:
254
0
            return NSSCertificateType_PKIX;
255
0
        default:
256
0
            break;
257
0
    }
258
0
    return NSSCertificateType_Unknown;
259
0
}
260
261
/* incoming pointers must be valid */
262
NSS_IMPLEMENT PRStatus
263
nssCryptokiCertificate_GetAttributes(
264
    nssCryptokiObject *certObject,
265
    nssSession *sessionOpt,
266
    NSSArena *arenaOpt,
267
    NSSCertificateType *certTypeOpt,
268
    NSSItem *idOpt,
269
    NSSDER *encodingOpt,
270
    NSSDER *issuerOpt,
271
    NSSDER *serialOpt,
272
    NSSDER *subjectOpt)
273
0
{
274
0
    PRStatus status;
275
0
    PRUint32 i;
276
0
    nssSession *session;
277
0
    NSSSlot *slot;
278
0
    CK_ULONG template_size;
279
0
    CK_ATTRIBUTE_PTR attr;
280
0
    CK_ATTRIBUTE cert_template[6];
281
0
    /* Set up a template of all options chosen by caller */
282
0
    NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
283
0
    if (certTypeOpt) {
284
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
285
0
    }
286
0
    if (idOpt) {
287
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
288
0
    }
289
0
    if (encodingOpt) {
290
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
291
0
    }
292
0
    if (issuerOpt) {
293
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
294
0
    }
295
0
    if (serialOpt) {
296
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
297
0
    }
298
0
    if (subjectOpt) {
299
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
300
0
    }
301
0
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
302
0
    if (template_size == 0) {
303
0
        /* caller didn't want anything */
304
0
        return PR_SUCCESS;
305
0
    }
306
0
307
0
    status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
308
0
                                                certObject, CKO_CERTIFICATE,
309
0
                                                cert_template, template_size);
310
0
    if (status != PR_SUCCESS) {
311
0
312
0
        session = sessionOpt ? sessionOpt
313
0
                             : nssToken_GetDefaultSession(certObject->token);
314
0
        if (!session) {
315
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
316
0
            return PR_FAILURE;
317
0
        }
318
0
319
0
        slot = nssToken_GetSlot(certObject->token);
320
0
        status = nssCKObject_GetAttributes(certObject->handle,
321
0
                                           cert_template, template_size,
322
0
                                           arenaOpt, session, slot);
323
0
        nssSlot_Destroy(slot);
324
0
        if (status != PR_SUCCESS) {
325
0
            return status;
326
0
        }
327
0
    }
328
0
329
0
    i = 0;
330
0
    if (certTypeOpt) {
331
0
        *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]);
332
0
        i++;
333
0
    }
334
0
    if (idOpt) {
335
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt);
336
0
        i++;
337
0
    }
338
0
    if (encodingOpt) {
339
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt);
340
0
        i++;
341
0
    }
342
0
    if (issuerOpt) {
343
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt);
344
0
        i++;
345
0
    }
346
0
    if (serialOpt) {
347
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt);
348
0
        i++;
349
0
    }
350
0
    if (subjectOpt) {
351
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt);
352
0
        i++;
353
0
    }
354
0
    return PR_SUCCESS;
355
0
}
356
357
static nssTrustLevel
358
get_nss_trust(
359
    CK_TRUST ckt)
360
0
{
361
0
    nssTrustLevel t;
362
0
    switch (ckt) {
363
0
        case CKT_NSS_NOT_TRUSTED:
364
0
            t = nssTrustLevel_NotTrusted;
365
0
            break;
366
0
        case CKT_NSS_TRUSTED_DELEGATOR:
367
0
            t = nssTrustLevel_TrustedDelegator;
368
0
            break;
369
0
        case CKT_NSS_VALID_DELEGATOR:
370
0
            t = nssTrustLevel_ValidDelegator;
371
0
            break;
372
0
        case CKT_NSS_TRUSTED:
373
0
            t = nssTrustLevel_Trusted;
374
0
            break;
375
0
        case CKT_NSS_MUST_VERIFY_TRUST:
376
0
            t = nssTrustLevel_MustVerify;
377
0
            break;
378
0
        case CKT_NSS_TRUST_UNKNOWN:
379
0
        default:
380
0
            t = nssTrustLevel_Unknown;
381
0
            break;
382
0
    }
383
0
    return t;
384
0
}
385
386
NSS_IMPLEMENT PRStatus
387
nssCryptokiTrust_GetAttributes(
388
    nssCryptokiObject *trustObject,
389
    nssSession *sessionOpt,
390
    NSSItem *sha1_hash,
391
    nssTrustLevel *serverAuth,
392
    nssTrustLevel *clientAuth,
393
    nssTrustLevel *codeSigning,
394
    nssTrustLevel *emailProtection,
395
    PRBool *stepUpApproved)
396
0
{
397
0
    PRStatus status;
398
0
    NSSSlot *slot;
399
0
    nssSession *session;
400
0
    CK_BBOOL isToken = PR_FALSE;
401
0
    CK_BBOOL stepUp = PR_FALSE;
402
0
    CK_TRUST saTrust = CKT_NSS_TRUST_UNKNOWN;
403
0
    CK_TRUST caTrust = CKT_NSS_TRUST_UNKNOWN;
404
0
    CK_TRUST epTrust = CKT_NSS_TRUST_UNKNOWN;
405
0
    CK_TRUST csTrust = CKT_NSS_TRUST_UNKNOWN;
406
0
    CK_ATTRIBUTE_PTR attr;
407
0
    CK_ATTRIBUTE trust_template[7];
408
0
    CK_ATTRIBUTE_PTR sha1_hash_attr;
409
0
    CK_ULONG trust_size;
410
0
411
0
    /* Use the trust object to find the trust settings */
412
0
    NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
413
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
414
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust);
415
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust);
416
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust);
417
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust);
418
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp);
419
0
    sha1_hash_attr = attr;
420
0
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash);
421
0
    NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
422
0
423
0
    status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
424
0
                                                trustObject,
425
0
                                                CKO_NSS_TRUST,
426
0
                                                trust_template, trust_size);
427
0
    if (status != PR_SUCCESS) {
428
0
        session = sessionOpt ? sessionOpt
429
0
                             : nssToken_GetDefaultSession(trustObject->token);
430
0
        if (!session) {
431
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
432
0
            return PR_FAILURE;
433
0
        }
434
0
435
0
        slot = nssToken_GetSlot(trustObject->token);
436
0
        status = nssCKObject_GetAttributes(trustObject->handle,
437
0
                                           trust_template, trust_size,
438
0
                                           NULL, session, slot);
439
0
        nssSlot_Destroy(slot);
440
0
        if (status != PR_SUCCESS) {
441
0
            return status;
442
0
        }
443
0
    }
444
0
445
0
    if (sha1_hash_attr->ulValueLen == -1) {
446
0
        /* The trust object does not have the CKA_CERT_SHA1_HASH attribute. */
447
0
        sha1_hash_attr->ulValueLen = 0;
448
0
    }
449
0
    sha1_hash->size = sha1_hash_attr->ulValueLen;
450
0
    *serverAuth = get_nss_trust(saTrust);
451
0
    *clientAuth = get_nss_trust(caTrust);
452
0
    *emailProtection = get_nss_trust(epTrust);
453
0
    *codeSigning = get_nss_trust(csTrust);
454
0
    *stepUpApproved = stepUp;
455
0
    return PR_SUCCESS;
456
0
}
457
458
NSS_IMPLEMENT PRStatus
459
nssCryptokiCRL_GetAttributes(
460
    nssCryptokiObject *crlObject,
461
    nssSession *sessionOpt,
462
    NSSArena *arenaOpt,
463
    NSSItem *encodingOpt,
464
    NSSItem *subjectOpt,
465
    CK_ULONG *crl_class,
466
    NSSUTF8 **urlOpt,
467
    PRBool *isKRLOpt)
468
0
{
469
0
    PRStatus status;
470
0
    NSSSlot *slot;
471
0
    nssSession *session;
472
0
    CK_ATTRIBUTE_PTR attr;
473
0
    CK_ATTRIBUTE crl_template[7];
474
0
    CK_ULONG crl_size;
475
0
    PRUint32 i;
476
0
477
0
    NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
478
0
    if (crl_class) {
479
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
480
0
    }
481
0
    if (encodingOpt) {
482
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
483
0
    }
484
0
    if (urlOpt) {
485
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL);
486
0
    }
487
0
    if (isKRLOpt) {
488
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL);
489
0
    }
490
0
    if (subjectOpt) {
491
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
492
0
    }
493
0
    NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
494
0
495
0
    status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
496
0
                                                crlObject,
497
0
                                                CKO_NSS_CRL,
498
0
                                                crl_template, crl_size);
499
0
    if (status != PR_SUCCESS) {
500
0
        session = sessionOpt ? sessionOpt
501
0
                             : nssToken_GetDefaultSession(crlObject->token);
502
0
        if (session == NULL) {
503
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
504
0
            return PR_FAILURE;
505
0
        }
506
0
507
0
        slot = nssToken_GetSlot(crlObject->token);
508
0
        status = nssCKObject_GetAttributes(crlObject->handle,
509
0
                                           crl_template, crl_size,
510
0
                                           arenaOpt, session, slot);
511
0
        nssSlot_Destroy(slot);
512
0
        if (status != PR_SUCCESS) {
513
0
            return status;
514
0
        }
515
0
    }
516
0
517
0
    i = 0;
518
0
    if (crl_class) {
519
0
        NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class);
520
0
        i++;
521
0
    }
522
0
    if (encodingOpt) {
523
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt);
524
0
        i++;
525
0
    }
526
0
    if (urlOpt) {
527
0
        NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt);
528
0
        i++;
529
0
    }
530
0
    if (isKRLOpt) {
531
0
        NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt);
532
0
        i++;
533
0
    }
534
0
    if (subjectOpt) {
535
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt);
536
0
        i++;
537
0
    }
538
0
    return PR_SUCCESS;
539
0
}
540
541
NSS_IMPLEMENT PRStatus
542
nssCryptokiPrivateKey_SetCertificate(
543
    nssCryptokiObject *keyObject,
544
    nssSession *sessionOpt,
545
    const NSSUTF8 *nickname,
546
    NSSItem *id,
547
    NSSDER *subject)
548
0
{
549
0
    CK_RV ckrv;
550
0
    CK_ATTRIBUTE_PTR attr;
551
0
    CK_ATTRIBUTE key_template[3];
552
0
    CK_ULONG key_size;
553
0
    void *epv = nssToken_GetCryptokiEPV(keyObject->token);
554
0
    nssSession *session;
555
0
    NSSToken *token = keyObject->token;
556
0
    nssSession *defaultSession = nssToken_GetDefaultSession(token);
557
0
    PRBool createdSession = PR_FALSE;
558
0
559
0
    NSS_CK_TEMPLATE_START(key_template, attr, key_size);
560
0
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
561
0
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
562
0
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
563
0
    NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
564
0
565
0
    if (sessionOpt) {
566
0
        if (!nssSession_IsReadWrite(sessionOpt)) {
567
0
            return PR_FAILURE;
568
0
        }
569
0
        session = sessionOpt;
570
0
    } else if (defaultSession && nssSession_IsReadWrite(defaultSession)) {
571
0
        session = defaultSession;
572
0
    } else {
573
0
        NSSSlot *slot = nssToken_GetSlot(token);
574
0
        session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
575
0
        nssSlot_Destroy(slot);
576
0
        if (!session) {
577
0
            return PR_FAILURE;
578
0
        }
579
0
        createdSession = PR_TRUE;
580
0
    }
581
0
582
0
    ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
583
0
                                           keyObject->handle,
584
0
                                           key_template,
585
0
                                           key_size);
586
0
587
0
    if (createdSession) {
588
0
        nssSession_Destroy(session);
589
0
    }
590
0
591
0
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
592
0
}