comparison nss/lib/dev/ckhelper.c @ 0:1e5118fa0cb1

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