1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
38
static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.34 $ $Date: 2005/04/04 18:46:23 $";
43
#endif /* NSSCKEPV_H */
51
#endif /* CKHELPER_H */
53
extern const NSSError NSS_ERROR_DEVICE_ERROR;
55
static const CK_BBOOL s_true = CK_TRUE;
56
NSS_IMPLEMENT_DATA const NSSItem
57
g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
59
static const CK_BBOOL s_false = CK_FALSE;
60
NSS_IMPLEMENT_DATA const NSSItem
61
g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
63
static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
64
NSS_IMPLEMENT_DATA const NSSItem
65
g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
67
static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
68
NSS_IMPLEMENT_DATA const NSSItem
69
g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
71
static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
72
NSS_IMPLEMENT_DATA const NSSItem
73
g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
77
CK_ATTRIBUTE_TYPE aType
83
case CKA_NETSCAPE_EMAIL:
93
NSS_IMPLEMENT PRStatus
94
nssCKObject_GetAttributes (
95
CK_OBJECT_HANDLE object,
96
CK_ATTRIBUTE_PTR obj_template,
103
nssArenaMark *mark = NULL;
104
CK_SESSION_HANDLE hSession;
108
PRBool alloced = PR_FALSE;
109
void *epv = nssSlot_GetCryptokiEPV(slot);
110
hSession = session->handle;
112
mark = nssArena_Mark(arenaOpt);
117
nssSession_EnterMonitor(session);
118
/* XXX kinda hacky, if the storage size is already in the first template
119
* item, then skip the alloc portion
121
if (obj_template[0].ulValueLen == 0) {
122
/* Get the storage size needed for each attribute */
123
ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
124
object, obj_template, count);
125
if (ckrv != CKR_OK &&
126
ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
127
ckrv != CKR_ATTRIBUTE_SENSITIVE)
129
nssSession_ExitMonitor(session);
130
nss_SetError(NSS_ERROR_DEVICE_ERROR);
133
/* Allocate memory for each attribute. */
134
for (i=0; i<count; i++) {
135
CK_ULONG ulValueLen = obj_template[i].ulValueLen;
136
if (ulValueLen == 0) continue;
137
if (ulValueLen == (CK_ULONG) -1) {
138
obj_template[i].ulValueLen = 0;
141
if (is_string_attribute(obj_template[i].type)) {
144
obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
145
if (!obj_template[i].pValue) {
146
nssSession_ExitMonitor(session);
152
/* Obtain the actual attribute values. */
153
ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
154
object, obj_template, count);
155
nssSession_ExitMonitor(session);
156
if (ckrv != CKR_OK &&
157
ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
158
ckrv != CKR_ATTRIBUTE_SENSITIVE)
160
nss_SetError(NSS_ERROR_DEVICE_ERROR);
163
if (alloced && arenaOpt) {
164
nssrv = nssArena_Unmark(arenaOpt, mark);
165
if (nssrv != PR_SUCCESS) {
170
if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
171
(ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
172
/* old tokens would keep the length of '0' and not deal with any
173
* of the attributes we passed. For those tokens read them one at
175
for (i=0; i < count; i++) {
176
if ((obj_template[i].ulValueLen == 0)
177
|| (obj_template[i].ulValueLen == -1)) {
178
obj_template[i].ulValueLen=0;
179
(void) nssCKObject_GetAttributes(object,&obj_template[i], 1,
180
arenaOpt, session, slot);
188
/* release all arena memory allocated before the failure. */
189
(void)nssArena_Release(arenaOpt, mark);
192
/* free each heap object that was allocated before the failure. */
193
for (j=0; j<i; j++) {
194
nss_ZFreeIf(obj_template[j].pValue);
201
NSS_IMPLEMENT PRStatus
202
nssCKObject_GetAttributeItem (
203
CK_OBJECT_HANDLE object,
204
CK_ATTRIBUTE_TYPE attribute,
211
CK_ATTRIBUTE attr = { 0, NULL, 0 };
213
attr.type = attribute;
214
nssrv = nssCKObject_GetAttributes(object, &attr, 1,
215
arenaOpt, session, slot);
216
if (nssrv != PR_SUCCESS) {
219
rvItem->data = (void *)attr.pValue;
220
rvItem->size = (PRUint32)attr.ulValueLen;
225
nssCKObject_IsAttributeTrue (
226
CK_OBJECT_HANDLE object,
227
CK_ATTRIBUTE_TYPE attribute,
234
CK_ATTRIBUTE_PTR attr;
235
CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
237
void *epv = nssSlot_GetCryptokiEPV(slot);
239
NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
240
nssSession_EnterMonitor(session);
241
ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
243
nssSession_ExitMonitor(session);
244
if (ckrv != CKR_OK) {
245
*rvStatus = PR_FAILURE;
248
*rvStatus = PR_SUCCESS;
249
return (PRBool)(bool == CK_TRUE);
252
NSS_IMPLEMENT PRStatus
253
nssCKObject_SetAttributes (
254
CK_OBJECT_HANDLE object,
255
CK_ATTRIBUTE_PTR obj_template,
262
void *epv = nssSlot_GetCryptokiEPV(slot);
263
nssSession_EnterMonitor(session);
264
ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
265
obj_template, count);
266
nssSession_ExitMonitor(session);
267
if (ckrv == CKR_OK) {
275
nssCKObject_IsTokenObjectTemplate (
276
CK_ATTRIBUTE_PTR objectTemplate,
281
for (ul=0; ul<otsize; ul++) {
282
if (objectTemplate[ul].type == CKA_TOKEN) {
283
return (*((CK_BBOOL*)objectTemplate[ul].pValue) == CK_TRUE);
289
static NSSCertificateType
290
nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
292
CK_CERTIFICATE_TYPE ckCertType;
293
if (!attrib->pValue) {
294
/* default to PKIX */
295
return NSSCertificateType_PKIX;
297
ckCertType = *((CK_ULONG *)attrib->pValue);
298
switch (ckCertType) {
300
return NSSCertificateType_PKIX;
304
return NSSCertificateType_Unknown;
307
/* incoming pointers must be valid */
308
NSS_IMPLEMENT PRStatus
309
nssCryptokiCertificate_GetAttributes (
310
nssCryptokiObject *certObject,
311
nssSession *sessionOpt,
313
NSSCertificateType *certTypeOpt,
325
CK_ULONG template_size;
326
CK_ATTRIBUTE_PTR attr;
327
CK_ATTRIBUTE cert_template[6];
328
/* Set up a template of all options chosen by caller */
329
NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
331
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
334
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
337
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
340
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
343
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
346
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
348
NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
349
if (template_size == 0) {
350
/* caller didn't want anything */
354
status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
355
certObject, CKO_CERTIFICATE,
356
cert_template, template_size);
357
if (status != PR_SUCCESS) {
359
session = sessionOpt ?
361
nssToken_GetDefaultSession(certObject->token);
363
slot = nssToken_GetSlot(certObject->token);
364
status = nssCKObject_GetAttributes(certObject->handle,
365
cert_template, template_size,
366
arenaOpt, session, slot);
367
nssSlot_Destroy(slot);
368
if (status != PR_SUCCESS) {
375
*certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++;
378
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++;
381
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++;
384
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++;
387
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++;
390
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++;
395
#ifdef PURE_STAN_BUILD
396
static NSSKeyPairType
397
nss_key_pair_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
399
CK_KEY_TYPE ckKeyType;
400
PR_ASSERT(attrib->pValue);
401
ckKeyType = *((CK_ULONG *)attrib->pValue);
403
case CKK_RSA: return NSSKeyPairType_RSA;
404
case CKK_DSA: return NSSKeyPairType_DSA;
407
return NSSKeyPairType_Unknown;
410
NSS_IMPLEMENT PRStatus
411
nssCryptokiPrivateKey_GetAttributes (
412
nssCryptokiObject *keyObject,
413
nssSession *sessionOpt,
415
NSSKeyPairType *keyTypeOpt,
423
CK_ULONG template_size;
424
CK_ATTRIBUTE_PTR attr;
425
CK_ATTRIBUTE key_template[2];
426
/* Set up a template of all options chosen by caller */
427
NSS_CK_TEMPLATE_START(key_template, attr, template_size);
429
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE);
432
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
434
NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size);
435
if (template_size == 0) {
436
/* caller didn't want anything */
440
session = sessionOpt ?
442
nssToken_GetDefaultSession(keyObject->token);
444
slot = nssToken_GetSlot(keyObject->token);
445
status = nssCKObject_GetAttributes(keyObject->handle,
446
key_template, template_size,
447
arenaOpt, session, slot);
448
nssSlot_Destroy(slot);
449
if (status != PR_SUCCESS) {
455
*keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++;
458
NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++;
463
NSS_IMPLEMENT PRStatus
464
nssCryptokiPublicKey_GetAttributes (
465
nssCryptokiObject *keyObject,
466
nssSession *sessionOpt,
468
NSSKeyPairType *keyTypeOpt,
476
CK_ULONG template_size;
477
CK_ATTRIBUTE_PTR attr;
478
CK_ATTRIBUTE key_template[2];
479
/* Set up a template of all options chosen by caller */
480
NSS_CK_TEMPLATE_START(key_template, attr, template_size);
482
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE);
485
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
487
NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size);
488
if (template_size == 0) {
489
/* caller didn't want anything */
493
session = sessionOpt ?
495
nssToken_GetDefaultSession(keyObject->token);
497
slot = nssToken_GetSlot(keyObject->token);
498
status = nssCKObject_GetAttributes(keyObject->handle,
499
key_template, template_size,
500
arenaOpt, session, slot);
501
nssSlot_Destroy(slot);
502
if (status != PR_SUCCESS) {
508
*keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++;
511
NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++;
515
#endif /* PURE_STAN_BUILD */
524
case CKT_NETSCAPE_UNTRUSTED: t = nssTrustLevel_NotTrusted; break;
525
case CKT_NETSCAPE_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator;
527
case CKT_NETSCAPE_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break;
528
case CKT_NETSCAPE_TRUSTED: t = nssTrustLevel_Trusted; break;
529
case CKT_NETSCAPE_VALID: t = nssTrustLevel_Valid; break;
530
case CKT_NETSCAPE_MUST_VERIFY:
531
case CKT_NETSCAPE_TRUST_UNKNOWN:
533
t = nssTrustLevel_Unknown; break;
538
NSS_IMPLEMENT PRStatus
539
nssCryptokiTrust_GetAttributes (
540
nssCryptokiObject *trustObject,
541
nssSession *sessionOpt,
543
nssTrustLevel *serverAuth,
544
nssTrustLevel *clientAuth,
545
nssTrustLevel *codeSigning,
546
nssTrustLevel *emailProtection,
547
PRBool *stepUpApproved
553
CK_BBOOL isToken = PR_FALSE;
554
CK_BBOOL stepUp = PR_FALSE;
555
CK_TRUST saTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
556
CK_TRUST caTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
557
CK_TRUST epTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
558
CK_TRUST csTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
559
CK_ATTRIBUTE_PTR attr;
560
CK_ATTRIBUTE trust_template[7];
563
/* Use the trust object to find the trust settings */
564
NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
565
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
566
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust);
567
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust);
568
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust);
569
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust);
570
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp);
571
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash);
572
NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
574
status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
577
trust_template, trust_size);
578
if (status != PR_SUCCESS) {
579
session = sessionOpt ?
581
nssToken_GetDefaultSession(trustObject->token);
583
slot = nssToken_GetSlot(trustObject->token);
584
status = nssCKObject_GetAttributes(trustObject->handle,
585
trust_template, trust_size,
586
NULL, session, slot);
587
nssSlot_Destroy(slot);
588
if (status != PR_SUCCESS) {
593
*serverAuth = get_nss_trust(saTrust);
594
*clientAuth = get_nss_trust(caTrust);
595
*emailProtection = get_nss_trust(epTrust);
596
*codeSigning = get_nss_trust(csTrust);
597
*stepUpApproved = stepUp;
601
NSS_IMPLEMENT PRStatus
602
nssCryptokiCRL_GetAttributes (
603
nssCryptokiObject *crlObject,
604
nssSession *sessionOpt,
606
NSSItem *encodingOpt,
616
CK_ATTRIBUTE_PTR attr;
617
CK_ATTRIBUTE crl_template[7];
621
NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
623
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
626
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
629
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL);
632
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL);
635
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
637
NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
639
status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
642
crl_template, crl_size);
643
if (status != PR_SUCCESS) {
644
session = sessionOpt ?
646
nssToken_GetDefaultSession(crlObject->token);
648
slot = nssToken_GetSlot(crlObject->token);
649
status = nssCKObject_GetAttributes(crlObject->handle,
650
crl_template, crl_size,
651
arenaOpt, session, slot);
652
nssSlot_Destroy(slot);
653
if (status != PR_SUCCESS) {
660
NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); i++;
663
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++;
666
NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++;
669
NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++;
672
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); i++;
677
NSS_IMPLEMENT PRStatus
678
nssCryptokiPrivateKey_SetCertificate (
679
nssCryptokiObject *keyObject,
680
nssSession *sessionOpt,
687
CK_ATTRIBUTE_PTR attr;
688
CK_ATTRIBUTE key_template[3];
690
void *epv = nssToken_GetCryptokiEPV(keyObject->token);
692
NSSToken *token = keyObject->token;
693
nssSession *defaultSession = nssToken_GetDefaultSession(token);
694
PRBool createdSession = PR_FALSE;
696
NSS_CK_TEMPLATE_START(key_template, attr, key_size);
697
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
698
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
699
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
700
NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
703
if (!nssSession_IsReadWrite(sessionOpt)) {
706
session = sessionOpt;
708
} else if (nssSession_IsReadWrite(defaultSession)) {
709
session = defaultSession;
711
NSSSlot *slot = nssToken_GetSlot(token);
712
session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
713
createdSession = PR_TRUE;
714
nssSlot_Destroy(slot);
717
ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
722
if (createdSession) {
723
nssSession_Destroy(session);
726
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;