/src/nss-nspr/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 | | /* XXX kinda hacky, if the storage size is already in the first template |
79 | | * item, then skip the alloc portion |
80 | | */ |
81 | 0 | if (obj_template[0].ulValueLen == 0) { |
82 | | /* 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 | | /* 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 | | /* 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 | | |
128 | 0 | if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) || |
129 | 0 | (ckrv == CKR_ATTRIBUTE_SENSITIVE))) { |
130 | | /* old tokens would keep the length of '0' and not deal with any |
131 | | * of the attributes we passed. For those tokens read them one at |
132 | | * 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 | | /* release all arena memory allocated before the failure. */ |
147 | 0 | (void)nssArena_Release(arenaOpt, mark); |
148 | 0 | } else { |
149 | 0 | CK_ULONG j; |
150 | | /* 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 | | /* 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 | | /* 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 | | /* caller didn't want anything */ |
304 | 0 | return PR_SUCCESS; |
305 | 0 | } |
306 | | |
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 | |
|
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 | | |
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 | | |
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 | | /* default values if the trust is record does not exist. In the highly |
402 | | * unlikely case that these change, be sure to update softoken's |
403 | | * 'sftkdb_isNullTrust()' function */ |
404 | 0 | CK_BBOOL stepUp = PR_FALSE; |
405 | 0 | CK_TRUST saTrust = CKT_NSS_TRUST_UNKNOWN; |
406 | 0 | CK_TRUST caTrust = CKT_NSS_TRUST_UNKNOWN; |
407 | 0 | CK_TRUST epTrust = CKT_NSS_TRUST_UNKNOWN; |
408 | 0 | CK_TRUST csTrust = CKT_NSS_TRUST_UNKNOWN; |
409 | 0 | CK_ATTRIBUTE_PTR attr; |
410 | 0 | CK_ATTRIBUTE trust_template[7]; |
411 | 0 | CK_ATTRIBUTE_PTR sha1_hash_attr; |
412 | 0 | CK_ULONG trust_size; |
413 | | |
414 | | /* Use the trust object to find the trust settings */ |
415 | 0 | NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); |
416 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); |
417 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); |
418 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); |
419 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); |
420 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); |
421 | 0 | NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp); |
422 | 0 | sha1_hash_attr = attr; |
423 | 0 | NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash); |
424 | 0 | NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); |
425 | |
|
426 | 0 | status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL, |
427 | 0 | trustObject, |
428 | 0 | CKO_NSS_TRUST, |
429 | 0 | trust_template, trust_size); |
430 | 0 | if (status != PR_SUCCESS) { |
431 | 0 | session = sessionOpt ? sessionOpt |
432 | 0 | : nssToken_GetDefaultSession(trustObject->token); |
433 | 0 | if (!session) { |
434 | 0 | nss_SetError(NSS_ERROR_INVALID_ARGUMENT); |
435 | 0 | return PR_FAILURE; |
436 | 0 | } |
437 | | |
438 | 0 | slot = nssToken_GetSlot(trustObject->token); |
439 | 0 | status = nssCKObject_GetAttributes(trustObject->handle, |
440 | 0 | trust_template, trust_size, |
441 | 0 | NULL, session, slot); |
442 | 0 | nssSlot_Destroy(slot); |
443 | 0 | if (status != PR_SUCCESS) { |
444 | 0 | return status; |
445 | 0 | } |
446 | 0 | } |
447 | | |
448 | 0 | if (sha1_hash_attr->ulValueLen == -1) { |
449 | | /* The trust object does not have the CKA_CERT_SHA1_HASH attribute. */ |
450 | 0 | sha1_hash_attr->ulValueLen = 0; |
451 | 0 | } |
452 | 0 | sha1_hash->size = sha1_hash_attr->ulValueLen; |
453 | 0 | *serverAuth = get_nss_trust(saTrust); |
454 | 0 | *clientAuth = get_nss_trust(caTrust); |
455 | 0 | *emailProtection = get_nss_trust(epTrust); |
456 | 0 | *codeSigning = get_nss_trust(csTrust); |
457 | 0 | *stepUpApproved = stepUp; |
458 | 0 | return PR_SUCCESS; |
459 | 0 | } |
460 | | |
461 | | NSS_IMPLEMENT PRStatus |
462 | | nssCryptokiCRL_GetAttributes( |
463 | | nssCryptokiObject *crlObject, |
464 | | nssSession *sessionOpt, |
465 | | NSSArena *arenaOpt, |
466 | | NSSItem *encodingOpt, |
467 | | NSSItem *subjectOpt, |
468 | | CK_ULONG *crl_class, |
469 | | NSSUTF8 **urlOpt, |
470 | | PRBool *isKRLOpt) |
471 | 0 | { |
472 | 0 | PRStatus status; |
473 | 0 | NSSSlot *slot; |
474 | 0 | nssSession *session; |
475 | 0 | CK_ATTRIBUTE_PTR attr; |
476 | 0 | CK_ATTRIBUTE crl_template[7]; |
477 | 0 | CK_ULONG crl_size; |
478 | 0 | PRUint32 i; |
479 | |
|
480 | 0 | NSS_CK_TEMPLATE_START(crl_template, attr, crl_size); |
481 | 0 | if (crl_class) { |
482 | 0 | NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS); |
483 | 0 | } |
484 | 0 | if (encodingOpt) { |
485 | 0 | NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); |
486 | 0 | } |
487 | 0 | if (urlOpt) { |
488 | 0 | NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL); |
489 | 0 | } |
490 | 0 | if (isKRLOpt) { |
491 | 0 | NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL); |
492 | 0 | } |
493 | 0 | if (subjectOpt) { |
494 | 0 | NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); |
495 | 0 | } |
496 | 0 | NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size); |
497 | |
|
498 | 0 | status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL, |
499 | 0 | crlObject, |
500 | 0 | CKO_NSS_CRL, |
501 | 0 | crl_template, crl_size); |
502 | 0 | if (status != PR_SUCCESS) { |
503 | 0 | session = sessionOpt ? sessionOpt |
504 | 0 | : nssToken_GetDefaultSession(crlObject->token); |
505 | 0 | if (session == NULL) { |
506 | 0 | nss_SetError(NSS_ERROR_INVALID_ARGUMENT); |
507 | 0 | return PR_FAILURE; |
508 | 0 | } |
509 | | |
510 | 0 | slot = nssToken_GetSlot(crlObject->token); |
511 | 0 | status = nssCKObject_GetAttributes(crlObject->handle, |
512 | 0 | crl_template, crl_size, |
513 | 0 | arenaOpt, session, slot); |
514 | 0 | nssSlot_Destroy(slot); |
515 | 0 | if (status != PR_SUCCESS) { |
516 | 0 | return status; |
517 | 0 | } |
518 | 0 | } |
519 | | |
520 | 0 | i = 0; |
521 | 0 | if (crl_class) { |
522 | 0 | NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); |
523 | 0 | i++; |
524 | 0 | } |
525 | 0 | if (encodingOpt) { |
526 | 0 | NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); |
527 | 0 | i++; |
528 | 0 | } |
529 | 0 | if (urlOpt) { |
530 | 0 | NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); |
531 | 0 | i++; |
532 | 0 | } |
533 | 0 | if (isKRLOpt) { |
534 | 0 | NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); |
535 | 0 | i++; |
536 | 0 | } |
537 | 0 | if (subjectOpt) { |
538 | 0 | NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); |
539 | 0 | i++; |
540 | 0 | } |
541 | 0 | return PR_SUCCESS; |
542 | 0 | } |
543 | | |
544 | | NSS_IMPLEMENT PRStatus |
545 | | nssCryptokiPrivateKey_SetCertificate( |
546 | | nssCryptokiObject *keyObject, |
547 | | nssSession *sessionOpt, |
548 | | const NSSUTF8 *nickname, |
549 | | NSSItem *id, |
550 | | NSSDER *subject) |
551 | 0 | { |
552 | 0 | CK_RV ckrv; |
553 | 0 | CK_ATTRIBUTE_PTR attr; |
554 | 0 | CK_ATTRIBUTE key_template[3]; |
555 | 0 | CK_ULONG key_size; |
556 | 0 | void *epv = nssToken_GetCryptokiEPV(keyObject->token); |
557 | 0 | nssSession *session; |
558 | 0 | NSSToken *token = keyObject->token; |
559 | 0 | nssSession *defaultSession = nssToken_GetDefaultSession(token); |
560 | 0 | PRBool createdSession = PR_FALSE; |
561 | |
|
562 | 0 | NSS_CK_TEMPLATE_START(key_template, attr, key_size); |
563 | 0 | NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); |
564 | 0 | NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); |
565 | 0 | NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); |
566 | 0 | NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size); |
567 | |
|
568 | 0 | if (sessionOpt) { |
569 | 0 | if (!nssSession_IsReadWrite(sessionOpt)) { |
570 | 0 | return PR_FAILURE; |
571 | 0 | } |
572 | 0 | session = sessionOpt; |
573 | 0 | } else if (defaultSession && nssSession_IsReadWrite(defaultSession)) { |
574 | 0 | session = defaultSession; |
575 | 0 | } else { |
576 | 0 | NSSSlot *slot = nssToken_GetSlot(token); |
577 | 0 | session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); |
578 | 0 | nssSlot_Destroy(slot); |
579 | 0 | if (!session) { |
580 | 0 | return PR_FAILURE; |
581 | 0 | } |
582 | 0 | createdSession = PR_TRUE; |
583 | 0 | } |
584 | | |
585 | 0 | ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, |
586 | 0 | keyObject->handle, |
587 | 0 | key_template, |
588 | 0 | key_size); |
589 | |
|
590 | 0 | if (createdSession) { |
591 | 0 | nssSession_Destroy(session); |
592 | 0 | } |
593 | |
|
594 | 0 | return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; |
595 | 0 | } |