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