OLD | NEW |
| (Empty) |
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 * pkix_pl_cert.c | |
6 * | |
7 * Certificate Object Functions | |
8 * | |
9 */ | |
10 | |
11 #include "pkix_pl_cert.h" | |
12 | |
13 extern PKIX_PL_HashTable *cachedCertSigTable; | |
14 | |
15 /* --Private-Cert-Functions------------------------------------- */ | |
16 | |
17 /* | |
18 * FUNCTION: pkix_pl_Cert_IsExtensionCritical | |
19 * DESCRIPTION: | |
20 * | |
21 * Checks the Cert specified by "cert" to determine whether the extension | |
22 * whose tag is the UInt32 value given by "tag" is marked as a critical | |
23 * extension, and stores the result in "pCritical". | |
24 * | |
25 * Tags are the index into the table "oids" of SECOidData defined in the | |
26 * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are | |
27 * are defined in secoidt.h for most of the table entries. | |
28 * | |
29 * If the specified tag is invalid (not in the list of tags) or if the | |
30 * extension is not found in the certificate, PKIX_FALSE is stored. | |
31 * | |
32 * PARAMETERS | |
33 * "cert" | |
34 * Address of Cert whose extensions are to be examined. Must be non-NULL. | |
35 * "tag" | |
36 * The UInt32 value of the tag for the extension whose criticality is | |
37 * to be determined | |
38 * "pCritical" | |
39 * Address where the Boolean value will be stored. Must be non-NULL. | |
40 * "plContext" | |
41 * Platform-specific context pointer. | |
42 * THREAD SAFETY: | |
43 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
44 * RETURNS: | |
45 * Returns NULL if the function succeeds. | |
46 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
47 */ | |
48 static PKIX_Error * | |
49 pkix_pl_Cert_IsExtensionCritical( | |
50 PKIX_PL_Cert *cert, | |
51 PKIX_UInt32 tag, | |
52 PKIX_Boolean *pCritical, | |
53 void *plContext) | |
54 { | |
55 PKIX_Boolean criticality = PKIX_FALSE; | |
56 CERTCertExtension **extensions = NULL; | |
57 SECStatus rv; | |
58 | |
59 PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical"); | |
60 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical); | |
61 | |
62 extensions = cert->nssCert->extensions; | |
63 PKIX_NULLCHECK_ONE(extensions); | |
64 | |
65 PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n"); | |
66 rv = CERT_GetExtenCriticality(extensions, tag, &criticality); | |
67 if (SECSuccess == rv) { | |
68 *pCritical = criticality; | |
69 } else { | |
70 *pCritical = PKIX_FALSE; | |
71 } | |
72 | |
73 PKIX_RETURN(CERT); | |
74 } | |
75 | |
76 /* | |
77 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo | |
78 * DESCRIPTION: | |
79 * | |
80 * Decodes the contents of the CertificatePolicy extension in the | |
81 * CERTCertificate pointed to by "nssCert", to create a List of | |
82 * CertPolicyInfos, which is stored at the address "pCertPolicyInfos". | |
83 * A CERTCertificate contains the DER representation of the Cert. | |
84 * If this certificate does not have a CertificatePolicy extension, | |
85 * NULL will be stored. If a List is returned, it will be immutable. | |
86 * | |
87 * PARAMETERS | |
88 * "nssCert" | |
89 * Address of the Cert data whose extension is to be examined. Must be | |
90 * non-NULL. | |
91 * "pCertPolicyInfos" | |
92 * Address where the List of CertPolicyInfos will be stored. Must be | |
93 * non-NULL. | |
94 * "plContext" | |
95 * Platform-specific context pointer. | |
96 * THREAD SAFETY: | |
97 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
98 * RETURNS: | |
99 * Returns NULL if the function succeeds. | |
100 * Returns a Cert Error if the function fails in a non-fatal way. | |
101 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
102 */ | |
103 static PKIX_Error * | |
104 pkix_pl_Cert_DecodePolicyInfo( | |
105 CERTCertificate *nssCert, | |
106 PKIX_List **pCertPolicyInfos, | |
107 void *plContext) | |
108 { | |
109 | |
110 SECStatus rv; | |
111 SECItem encodedCertPolicyInfo; | |
112 | |
113 /* Allocated in the arena; freed in CERT_Destroy... */ | |
114 CERTCertificatePolicies *certPol = NULL; | |
115 CERTPolicyInfo **policyInfos = NULL; | |
116 | |
117 /* Holder for the return value */ | |
118 PKIX_List *infos = NULL; | |
119 | |
120 PKIX_PL_OID *pkixOID = NULL; | |
121 PKIX_List *qualifiers = NULL; | |
122 PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; | |
123 PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL; | |
124 PKIX_PL_ByteArray *qualifierArray = NULL; | |
125 | |
126 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo"); | |
127 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos); | |
128 | |
129 /* get PolicyInfo as a SECItem */ | |
130 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); | |
131 rv = CERT_FindCertExtension | |
132 (nssCert, | |
133 SEC_OID_X509_CERTIFICATE_POLICIES, | |
134 &encodedCertPolicyInfo); | |
135 if (SECSuccess != rv) { | |
136 *pCertPolicyInfos = NULL; | |
137 goto cleanup; | |
138 } | |
139 | |
140 /* translate PolicyInfo to CERTCertificatePolicies */ | |
141 PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n"); | |
142 certPol = CERT_DecodeCertificatePoliciesExtension | |
143 (&encodedCertPolicyInfo); | |
144 | |
145 PORT_Free(encodedCertPolicyInfo.data); | |
146 | |
147 if (NULL == certPol) { | |
148 PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED); | |
149 } | |
150 | |
151 /* | |
152 * Check whether there are any policyInfos, so we can | |
153 * avoid creating an unnecessary List | |
154 */ | |
155 policyInfos = certPol->policyInfos; | |
156 if (!policyInfos) { | |
157 *pCertPolicyInfos = NULL; | |
158 goto cleanup; | |
159 } | |
160 | |
161 /* create a List of CertPolicyInfo Objects */ | |
162 PKIX_CHECK(PKIX_List_Create(&infos, plContext), | |
163 PKIX_LISTCREATEFAILED); | |
164 | |
165 /* | |
166 * Traverse the CERTCertificatePolicies structure, | |
167 * building each PKIX_PL_CertPolicyInfo object in turn | |
168 */ | |
169 while (*policyInfos != NULL) { | |
170 CERTPolicyInfo *policyInfo = *policyInfos; | |
171 CERTPolicyQualifier **policyQualifiers = | |
172 policyInfo->policyQualifiers; | |
173 if (policyQualifiers) { | |
174 /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */ | |
175 PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), | |
176 PKIX_LISTCREATEFAILED); | |
177 | |
178 while (*policyQualifiers != NULL) { | |
179 CERTPolicyQualifier *policyQualifier = | |
180 *policyQualifiers; | |
181 | |
182 /* create the qualifier's OID object */ | |
183 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
184 (&policyQualifier->qualifierID, | |
185 &pkixOID, plContext), | |
186 PKIX_OIDCREATEFAILED); | |
187 | |
188 /* create qualifier's ByteArray object */ | |
189 | |
190 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
191 (policyQualifier->qualifierValue.data, | |
192 policyQualifier->qualifierValue.len, | |
193 &qualifierArray, | |
194 plContext), | |
195 PKIX_BYTEARRAYCREATEFAILED); | |
196 | |
197 /* create a CertPolicyQualifier object */ | |
198 | |
199 PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create | |
200 (pkixOID, | |
201 qualifierArray, | |
202 &certPolicyQualifier, | |
203 plContext), | |
204 PKIX_CERTPOLICYQUALIFIERCREATEFAILED); | |
205 | |
206 PKIX_CHECK(PKIX_List_AppendItem | |
207 (qualifiers, | |
208 (PKIX_PL_Object *)certPolicyQualifier, | |
209 plContext), | |
210 PKIX_LISTAPPENDITEMFAILED); | |
211 | |
212 PKIX_DECREF(pkixOID); | |
213 PKIX_DECREF(qualifierArray); | |
214 PKIX_DECREF(certPolicyQualifier); | |
215 | |
216 policyQualifiers++; | |
217 } | |
218 | |
219 PKIX_CHECK(PKIX_List_SetImmutable | |
220 (qualifiers, plContext), | |
221 PKIX_LISTSETIMMUTABLEFAILED); | |
222 } | |
223 | |
224 | |
225 /* | |
226 * Create an OID object pkixOID from policyInfo->policyID. | |
227 * (The CERTPolicyInfo structure has an oid field, but it | |
228 * is of type SECOidTag. This function wants a SECItem.) | |
229 */ | |
230 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
231 (&policyInfo->policyID, &pkixOID, plContext), | |
232 PKIX_OIDCREATEFAILED); | |
233 | |
234 /* Create a CertPolicyInfo object */ | |
235 PKIX_CHECK(pkix_pl_CertPolicyInfo_Create | |
236 (pkixOID, qualifiers, &certPolicyInfo, plContext), | |
237 PKIX_CERTPOLICYINFOCREATEFAILED); | |
238 | |
239 /* Append the new CertPolicyInfo object to the list */ | |
240 PKIX_CHECK(PKIX_List_AppendItem | |
241 (infos, (PKIX_PL_Object *)certPolicyInfo, plContext), | |
242 PKIX_LISTAPPENDITEMFAILED); | |
243 | |
244 PKIX_DECREF(pkixOID); | |
245 PKIX_DECREF(qualifiers); | |
246 PKIX_DECREF(certPolicyInfo); | |
247 | |
248 policyInfos++; | |
249 } | |
250 | |
251 /* | |
252 * If there were no policies, we went straight to | |
253 * cleanup, so we don't have to NULLCHECK infos. | |
254 */ | |
255 PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext), | |
256 PKIX_LISTSETIMMUTABLEFAILED); | |
257 | |
258 *pCertPolicyInfos = infos; | |
259 infos = NULL; | |
260 | |
261 cleanup: | |
262 if (certPol) { | |
263 PKIX_CERT_DEBUG | |
264 ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n"); | |
265 CERT_DestroyCertificatePoliciesExtension(certPol); | |
266 } | |
267 | |
268 PKIX_DECREF(infos); | |
269 PKIX_DECREF(pkixOID); | |
270 PKIX_DECREF(qualifiers); | |
271 PKIX_DECREF(certPolicyInfo); | |
272 PKIX_DECREF(certPolicyQualifier); | |
273 PKIX_DECREF(qualifierArray); | |
274 | |
275 PKIX_RETURN(CERT); | |
276 } | |
277 | |
278 /* | |
279 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping | |
280 * DESCRIPTION: | |
281 * | |
282 * Decodes the contents of the PolicyMapping extension of the CERTCertificate | |
283 * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at | |
284 * the address pointed to by "pCertPolicyMaps". If this certificate does not | |
285 * have a PolicyMapping extension, NULL will be stored. If a List is returned, | |
286 * it will be immutable. | |
287 * | |
288 * PARAMETERS | |
289 * "nssCert" | |
290 * Address of the Cert data whose extension is to be examined. Must be | |
291 * non-NULL. | |
292 * "pCertPolicyMaps" | |
293 * Address where the List of CertPolicyMaps will be stored. Must be | |
294 * non-NULL. | |
295 * "plContext" | |
296 * Platform-specific context pointer. | |
297 * THREAD SAFETY: | |
298 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
299 * RETURNS: | |
300 * Returns NULL if the function succeeds. | |
301 * Returns a Cert Error if the function fails in a non-fatal way. | |
302 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
303 */ | |
304 static PKIX_Error * | |
305 pkix_pl_Cert_DecodePolicyMapping( | |
306 CERTCertificate *nssCert, | |
307 PKIX_List **pCertPolicyMaps, | |
308 void *plContext) | |
309 { | |
310 SECStatus rv; | |
311 SECItem encodedCertPolicyMaps; | |
312 | |
313 /* Allocated in the arena; freed in CERT_Destroy... */ | |
314 CERTCertificatePolicyMappings *certPolMaps = NULL; | |
315 CERTPolicyMap **policyMaps = NULL; | |
316 | |
317 /* Holder for the return value */ | |
318 PKIX_List *maps = NULL; | |
319 | |
320 PKIX_PL_OID *issuerDomainOID = NULL; | |
321 PKIX_PL_OID *subjectDomainOID = NULL; | |
322 PKIX_PL_CertPolicyMap *certPolicyMap = NULL; | |
323 | |
324 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping"); | |
325 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps); | |
326 | |
327 /* get PolicyMappings as a SECItem */ | |
328 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); | |
329 rv = CERT_FindCertExtension | |
330 (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps); | |
331 if (SECSuccess != rv) { | |
332 *pCertPolicyMaps = NULL; | |
333 goto cleanup; | |
334 } | |
335 | |
336 /* translate PolicyMaps to CERTCertificatePolicyMappings */ | |
337 certPolMaps = CERT_DecodePolicyMappingsExtension | |
338 (&encodedCertPolicyMaps); | |
339 | |
340 PORT_Free(encodedCertPolicyMaps.data); | |
341 | |
342 if (!certPolMaps) { | |
343 PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED); | |
344 } | |
345 | |
346 PKIX_NULLCHECK_ONE(certPolMaps->policyMaps); | |
347 | |
348 policyMaps = certPolMaps->policyMaps; | |
349 | |
350 /* create a List of CertPolicyMap Objects */ | |
351 PKIX_CHECK(PKIX_List_Create(&maps, plContext), | |
352 PKIX_LISTCREATEFAILED); | |
353 | |
354 /* | |
355 * Traverse the CERTCertificatePolicyMappings structure, | |
356 * building each CertPolicyMap object in turn | |
357 */ | |
358 do { | |
359 CERTPolicyMap *policyMap = *policyMaps; | |
360 | |
361 /* create the OID for the issuer Domain Policy */ | |
362 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
363 (&policyMap->issuerDomainPolicy, | |
364 &issuerDomainOID, plContext), | |
365 PKIX_OIDCREATEFAILED); | |
366 | |
367 /* create the OID for the subject Domain Policy */ | |
368 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
369 (&policyMap->subjectDomainPolicy, | |
370 &subjectDomainOID, plContext), | |
371 PKIX_OIDCREATEFAILED); | |
372 | |
373 /* create the CertPolicyMap */ | |
374 | |
375 PKIX_CHECK(pkix_pl_CertPolicyMap_Create | |
376 (issuerDomainOID, | |
377 subjectDomainOID, | |
378 &certPolicyMap, | |
379 plContext), | |
380 PKIX_CERTPOLICYMAPCREATEFAILED); | |
381 | |
382 PKIX_CHECK(PKIX_List_AppendItem | |
383 (maps, (PKIX_PL_Object *)certPolicyMap, plContext), | |
384 PKIX_LISTAPPENDITEMFAILED); | |
385 | |
386 PKIX_DECREF(issuerDomainOID); | |
387 PKIX_DECREF(subjectDomainOID); | |
388 PKIX_DECREF(certPolicyMap); | |
389 | |
390 policyMaps++; | |
391 } while (*policyMaps != NULL); | |
392 | |
393 PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext), | |
394 PKIX_LISTSETIMMUTABLEFAILED); | |
395 | |
396 *pCertPolicyMaps = maps; | |
397 maps = NULL; | |
398 | |
399 cleanup: | |
400 if (certPolMaps) { | |
401 PKIX_CERT_DEBUG | |
402 ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n"); | |
403 CERT_DestroyPolicyMappingsExtension(certPolMaps); | |
404 } | |
405 | |
406 PKIX_DECREF(maps); | |
407 PKIX_DECREF(issuerDomainOID); | |
408 PKIX_DECREF(subjectDomainOID); | |
409 PKIX_DECREF(certPolicyMap); | |
410 | |
411 PKIX_RETURN(CERT); | |
412 } | |
413 | |
414 /* | |
415 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints | |
416 * DESCRIPTION: | |
417 * | |
418 * Decodes the contents of the PolicyConstraints extension in the | |
419 * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values | |
420 * which are stored at the addresses "pExplicitPolicySkipCerts" and | |
421 * "pInhibitMappingSkipCerts", respectively. If this certificate does | |
422 * not have an PolicyConstraints extension, or if either of the optional | |
423 * components is not supplied, this function stores a value of -1 for any | |
424 * missing component. | |
425 * | |
426 * PARAMETERS | |
427 * "nssCert" | |
428 * Address of the Cert data whose extension is to be examined. Must be | |
429 * non-NULL. | |
430 * "pExplicitPolicySkipCerts" | |
431 * Address where the SkipCert value for the requireExplicitPolicy | |
432 * component will be stored. Must be non-NULL. | |
433 * "pInhibitMappingSkipCerts" | |
434 * Address where the SkipCert value for the inhibitPolicyMapping | |
435 * component will be stored. Must be non-NULL. | |
436 * "plContext" | |
437 * Platform-specific context pointer. | |
438 * THREAD SAFETY: | |
439 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
440 * RETURNS: | |
441 * Returns NULL if the function succeeds. | |
442 * Returns a Cert Error if the function fails in a non-fatal way. | |
443 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
444 */ | |
445 static PKIX_Error * | |
446 pkix_pl_Cert_DecodePolicyConstraints( | |
447 CERTCertificate *nssCert, | |
448 PKIX_Int32 *pExplicitPolicySkipCerts, | |
449 PKIX_Int32 *pInhibitMappingSkipCerts, | |
450 void *plContext) | |
451 { | |
452 CERTCertificatePolicyConstraints policyConstraints; | |
453 SECStatus rv; | |
454 SECItem encodedCertPolicyConstraints; | |
455 PKIX_Int32 explicitPolicySkipCerts = -1; | |
456 PKIX_Int32 inhibitMappingSkipCerts = -1; | |
457 | |
458 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints"); | |
459 PKIX_NULLCHECK_THREE | |
460 (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts); | |
461 | |
462 /* get the two skipCert values as SECItems */ | |
463 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); | |
464 rv = CERT_FindCertExtension | |
465 (nssCert, | |
466 SEC_OID_X509_POLICY_CONSTRAINTS, | |
467 &encodedCertPolicyConstraints); | |
468 | |
469 if (rv == SECSuccess) { | |
470 | |
471 policyConstraints.explicitPolicySkipCerts.data = | |
472 (unsigned char *)&explicitPolicySkipCerts; | |
473 policyConstraints.inhibitMappingSkipCerts.data = | |
474 (unsigned char *)&inhibitMappingSkipCerts; | |
475 | |
476 /* translate DER to CERTCertificatePolicyConstraints */ | |
477 rv = CERT_DecodePolicyConstraintsExtension | |
478 (&policyConstraints, &encodedCertPolicyConstraints); | |
479 | |
480 PORT_Free(encodedCertPolicyConstraints.data); | |
481 | |
482 if (rv != SECSuccess) { | |
483 PKIX_ERROR | |
484 (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED); | |
485 } | |
486 } | |
487 | |
488 *pExplicitPolicySkipCerts = explicitPolicySkipCerts; | |
489 *pInhibitMappingSkipCerts = inhibitMappingSkipCerts; | |
490 | |
491 cleanup: | |
492 PKIX_RETURN(CERT); | |
493 } | |
494 | |
495 /* | |
496 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy | |
497 * DESCRIPTION: | |
498 * | |
499 * Decodes the contents of the InhibitAnyPolicy extension in the | |
500 * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value, | |
501 * which is stored at the address "pSkipCerts". If this certificate does | |
502 * not have an InhibitAnyPolicy extension, -1 will be stored. | |
503 * | |
504 * PARAMETERS | |
505 * "nssCert" | |
506 * Address of the Cert data whose InhibitAnyPolicy extension is to be | |
507 * processed. Must be non-NULL. | |
508 * "pSkipCerts" | |
509 * Address where the SkipCert value from the InhibitAnyPolicy extension | |
510 * will be stored. Must be non-NULL. | |
511 * "plContext" | |
512 * Platform-specific context pointer. | |
513 * THREAD SAFETY: | |
514 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
515 * RETURNS: | |
516 * Returns NULL if the function succeeds. | |
517 * Returns a Cert Error if the function fails in a non-fatal way. | |
518 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
519 */ | |
520 PKIX_Error * | |
521 pkix_pl_Cert_DecodeInhibitAnyPolicy( | |
522 CERTCertificate *nssCert, | |
523 PKIX_Int32 *pSkipCerts, | |
524 void *plContext) | |
525 { | |
526 CERTCertificateInhibitAny inhibitAny; | |
527 SECStatus rv; | |
528 SECItem encodedCertInhibitAny; | |
529 PKIX_Int32 skipCerts = -1; | |
530 | |
531 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy"); | |
532 PKIX_NULLCHECK_TWO(nssCert, pSkipCerts); | |
533 | |
534 /* get InhibitAny as a SECItem */ | |
535 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); | |
536 rv = CERT_FindCertExtension | |
537 (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAn
y); | |
538 | |
539 if (rv == SECSuccess) { | |
540 inhibitAny.inhibitAnySkipCerts.data = | |
541 (unsigned char *)&skipCerts; | |
542 | |
543 /* translate DER to CERTCertificateInhibitAny */ | |
544 rv = CERT_DecodeInhibitAnyExtension | |
545 (&inhibitAny, &encodedCertInhibitAny); | |
546 | |
547 PORT_Free(encodedCertInhibitAny.data); | |
548 | |
549 if (rv != SECSuccess) { | |
550 PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED); | |
551 } | |
552 } | |
553 | |
554 *pSkipCerts = skipCerts; | |
555 | |
556 cleanup: | |
557 PKIX_RETURN(CERT); | |
558 } | |
559 | |
560 /* | |
561 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames | |
562 * DESCRIPTION: | |
563 * | |
564 * Retrieves the Subject Alternative Names of the certificate specified by | |
565 * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative | |
566 * Name extension is not present, NULL is returned at "pNssSubjAltNames". | |
567 * If the Subject Alternative Names has not been previously decoded, it is | |
568 * decoded here with lock on the "cert" unless the flag "hasLock" indicates | |
569 * the lock had been obtained at a higher call level. | |
570 * | |
571 * PARAMETERS | |
572 * "cert" | |
573 * Address of the certificate whose Subject Alternative Names extensions | |
574 * is retrieved. Must be non-NULL. | |
575 * "hasLock" | |
576 * Boolean indicates caller has acquired a lock. | |
577 * Must be non-NULL. | |
578 * "pNssSubjAltNames" | |
579 * Address where the returned Subject Alternative Names will be stored. | |
580 * Must be non-NULL. | |
581 * "plContext" | |
582 * Platform-specific context pointer. | |
583 * THREAD SAFETY: | |
584 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
585 * RETURNS: | |
586 * Returns NULL if the function succeeds. | |
587 * Returns a Cert Error if the function fails in a non-fatal way. | |
588 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
589 */ | |
590 static PKIX_Error * | |
591 pkix_pl_Cert_GetNssSubjectAltNames( | |
592 PKIX_PL_Cert *cert, | |
593 PKIX_Boolean hasLock, | |
594 CERTGeneralName **pNssSubjAltNames, | |
595 void *plContext) | |
596 { | |
597 CERTCertificate *nssCert = NULL; | |
598 CERTGeneralName *nssOriginalAltName = NULL; | |
599 PLArenaPool *arena = NULL; | |
600 SECItem altNameExtension = {siBuffer, NULL, 0}; | |
601 SECStatus rv = SECFailure; | |
602 | |
603 PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames"); | |
604 PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert); | |
605 | |
606 nssCert = cert->nssCert; | |
607 | |
608 if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ | |
609 | |
610 if (!hasLock) { | |
611 PKIX_OBJECT_LOCK(cert); | |
612 } | |
613 | |
614 if ((cert->nssSubjAltNames == NULL) && | |
615 (!cert->subjAltNamesAbsent)){ | |
616 | |
617 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, | |
618 (nssCert, | |
619 SEC_OID_X509_SUBJECT_ALT_NAME, | |
620 &altNameExtension)); | |
621 | |
622 if (rv != SECSuccess) { | |
623 *pNssSubjAltNames = NULL; | |
624 cert->subjAltNamesAbsent = PKIX_TRUE; | |
625 goto cleanup; | |
626 } | |
627 | |
628 if (cert->arenaNameConstraints == NULL) { | |
629 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, | |
630 (DER_DEFAULT_CHUNKSIZE)); | |
631 | |
632 if (arena == NULL) { | |
633 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
634 } | |
635 cert->arenaNameConstraints = arena; | |
636 } | |
637 | |
638 PKIX_PL_NSSCALLRV | |
639 (CERT, | |
640 nssOriginalAltName, | |
641 (CERTGeneralName *) CERT_DecodeAltNameExtension, | |
642 (cert->arenaNameConstraints, &altNameExtension)); | |
643 | |
644 PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data)); | |
645 | |
646 if (nssOriginalAltName == NULL) { | |
647 PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED); | |
648 } | |
649 cert->nssSubjAltNames = nssOriginalAltName; | |
650 | |
651 } | |
652 | |
653 if (!hasLock) { | |
654 PKIX_OBJECT_UNLOCK(cert); | |
655 } | |
656 } | |
657 | |
658 *pNssSubjAltNames = cert->nssSubjAltNames; | |
659 | |
660 cleanup: | |
661 PKIX_OBJECT_UNLOCK(lockedObject); | |
662 PKIX_RETURN(CERT); | |
663 } | |
664 | |
665 /* | |
666 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage | |
667 * DESCRIPTION: | |
668 * | |
669 * For each of the ON bit in "requiredExtendedKeyUsages" that represents its | |
670 * SECCertUsageEnum type, this function checks "cert"'s certType (extended | |
671 * key usage) and key usage with what is required for SECCertUsageEnum type. | |
672 * | |
673 * PARAMETERS | |
674 * "cert" | |
675 * Address of the certificate whose Extended Key Usage extensions | |
676 * is retrieved. Must be non-NULL. | |
677 * "requiredExtendedKeyUsages" | |
678 * An unsigned integer, its bit location is ON based on the required key | |
679 * usage value representing in SECCertUsageEnum. | |
680 * "pPass" | |
681 * Address where the return value, indicating key usage check passed, is | |
682 * stored. Must be non-NULL. | |
683 * "plContext" | |
684 * Platform-specific context pointer. | |
685 * THREAD SAFETY: | |
686 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
687 * RETURNS: | |
688 * Returns NULL if the function succeeds. | |
689 * Returns a Cert Error if the function fails in a non-fatal way. | |
690 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
691 */ | |
692 PKIX_Error * | |
693 pkix_pl_Cert_CheckExtendedKeyUsage( | |
694 PKIX_PL_Cert *cert, | |
695 PKIX_UInt32 requiredExtendedKeyUsages, | |
696 PKIX_Boolean *pPass, | |
697 void *plContext) | |
698 { | |
699 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; | |
700 PKIX_UInt32 certType = 0; | |
701 PKIX_UInt32 requiredKeyUsage = 0; | |
702 PKIX_UInt32 requiredCertType = 0; | |
703 PKIX_UInt32 requiredExtendedKeyUsage = 0; | |
704 PKIX_UInt32 i; | |
705 PKIX_Boolean isCA = PKIX_FALSE; | |
706 SECStatus rv = SECFailure; | |
707 | |
708 PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage"); | |
709 PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert); | |
710 | |
711 *pPass = PKIX_FALSE; | |
712 | |
713 PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n"); | |
714 cert_GetCertType(cert->nssCert); | |
715 certType = cert->nssCert->nsCertType; | |
716 | |
717 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints | |
718 (cert, | |
719 &basicConstraints, | |
720 plContext), | |
721 PKIX_CERTGETBASICCONSTRAINTFAILED); | |
722 | |
723 if (basicConstraints != NULL) { | |
724 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag | |
725 (basicConstraints, &isCA, plContext), | |
726 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); | |
727 } | |
728 | |
729 i = 0; | |
730 while (requiredExtendedKeyUsages != 0) { | |
731 | |
732 /* Find the bit location of the right-most non-zero bit */ | |
733 while (requiredExtendedKeyUsages != 0) { | |
734 if (((1 << i) & requiredExtendedKeyUsages) != 0) { | |
735 requiredExtendedKeyUsage = 1 << i; | |
736 break; | |
737 } | |
738 i++; | |
739 } | |
740 requiredExtendedKeyUsages ^= requiredExtendedKeyUsage; | |
741 | |
742 requiredExtendedKeyUsage = i; | |
743 | |
744 PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage, | |
745 (requiredExtendedKeyUsage, | |
746 isCA, | |
747 &requiredKeyUsage, | |
748 &requiredCertType)); | |
749 | |
750 if (!(certType & requiredCertType)) { | |
751 goto cleanup; | |
752 } | |
753 | |
754 PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage, | |
755 (cert->nssCert, requiredKeyUsage)); | |
756 if (rv != SECSuccess) { | |
757 goto cleanup; | |
758 } | |
759 i++; | |
760 | |
761 } | |
762 | |
763 *pPass = PKIX_TRUE; | |
764 | |
765 cleanup: | |
766 PKIX_DECREF(basicConstraints); | |
767 PKIX_RETURN(CERT); | |
768 } | |
769 | |
770 /* | |
771 * FUNCTION: pkix_pl_Cert_ToString_Helper | |
772 * DESCRIPTION: | |
773 * | |
774 * Helper function that creates a string representation of the Cert pointed | |
775 * to by "cert" and stores it at "pString", where the value of | |
776 * "partialString" determines whether a full or partial representation of | |
777 * the Cert is stored. | |
778 * | |
779 * PARAMETERS | |
780 * "cert" | |
781 * Address of Cert whose string representation is desired. | |
782 * Must be non-NULL. | |
783 * "partialString" | |
784 * Boolean indicating whether a partial Cert representation is desired. | |
785 * "pString" | |
786 * Address where object pointer will be stored. Must be non-NULL. | |
787 * "plContext" | |
788 * Platform-specific context pointer. | |
789 * THREAD SAFETY: | |
790 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
791 * RETURNS: | |
792 * Returns NULL if the function succeeds. | |
793 * Returns a Cert Error if the function fails in a non-fatal way. | |
794 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
795 */ | |
796 PKIX_Error * | |
797 pkix_pl_Cert_ToString_Helper( | |
798 PKIX_PL_Cert *cert, | |
799 PKIX_Boolean partialString, | |
800 PKIX_PL_String **pString, | |
801 void *plContext) | |
802 { | |
803 PKIX_PL_String *certString = NULL; | |
804 char *asciiFormat = NULL; | |
805 PKIX_PL_String *formatString = NULL; | |
806 PKIX_UInt32 certVersion; | |
807 PKIX_PL_BigInt *certSN = NULL; | |
808 PKIX_PL_String *certSNString = NULL; | |
809 PKIX_PL_X500Name *certIssuer = NULL; | |
810 PKIX_PL_String *certIssuerString = NULL; | |
811 PKIX_PL_X500Name *certSubject = NULL; | |
812 PKIX_PL_String *certSubjectString = NULL; | |
813 PKIX_PL_String *notBeforeString = NULL; | |
814 PKIX_PL_String *notAfterString = NULL; | |
815 PKIX_List *subjAltNames = NULL; | |
816 PKIX_PL_String *subjAltNamesString = NULL; | |
817 PKIX_PL_ByteArray *authKeyId = NULL; | |
818 PKIX_PL_String *authKeyIdString = NULL; | |
819 PKIX_PL_ByteArray *subjKeyId = NULL; | |
820 PKIX_PL_String *subjKeyIdString = NULL; | |
821 PKIX_PL_PublicKey *nssPubKey = NULL; | |
822 PKIX_PL_String *nssPubKeyString = NULL; | |
823 PKIX_List *critExtOIDs = NULL; | |
824 PKIX_PL_String *critExtOIDsString = NULL; | |
825 PKIX_List *extKeyUsages = NULL; | |
826 PKIX_PL_String *extKeyUsagesString = NULL; | |
827 PKIX_PL_CertBasicConstraints *basicConstraint = NULL; | |
828 PKIX_PL_String *certBasicConstraintsString = NULL; | |
829 PKIX_List *policyInfo = NULL; | |
830 PKIX_PL_String *certPolicyInfoString = NULL; | |
831 PKIX_List *certPolicyMappings = NULL; | |
832 PKIX_PL_String *certPolicyMappingsString = NULL; | |
833 PKIX_Int32 certExplicitPolicy = 0; | |
834 PKIX_Int32 certInhibitMapping = 0; | |
835 PKIX_Int32 certInhibitAnyPolicy = 0; | |
836 PKIX_PL_CertNameConstraints *nameConstraints = NULL; | |
837 PKIX_PL_String *nameConstraintsString = NULL; | |
838 PKIX_List *authorityInfoAccess = NULL; | |
839 PKIX_PL_String *authorityInfoAccessString = NULL; | |
840 PKIX_List *subjectInfoAccess = NULL; | |
841 PKIX_PL_String *subjectInfoAccessString = NULL; | |
842 | |
843 PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper"); | |
844 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString); | |
845 | |
846 /* | |
847 * XXX Add to this format as certificate components are developed. | |
848 */ | |
849 | |
850 if (partialString){ | |
851 asciiFormat = | |
852 "\t[Issuer: %s\n" | |
853 "\t Subject: %s]"; | |
854 } else { | |
855 asciiFormat = | |
856 "[\n" | |
857 "\tVersion: v%d\n" | |
858 "\tSerialNumber: %s\n" | |
859 "\tIssuer: %s\n" | |
860 "\tSubject: %s\n" | |
861 "\tValidity: [From: %s\n" | |
862 "\t To: %s]\n" | |
863 "\tSubjectAltNames: %s\n" | |
864 "\tAuthorityKeyId: %s\n" | |
865 "\tSubjectKeyId: %s\n" | |
866 "\tSubjPubKeyAlgId: %s\n" | |
867 "\tCritExtOIDs: %s\n" | |
868 "\tExtKeyUsages: %s\n" | |
869 "\tBasicConstraint: %s\n" | |
870 "\tCertPolicyInfo: %s\n" | |
871 "\tPolicyMappings: %s\n" | |
872 "\tExplicitPolicy: %d\n" | |
873 "\tInhibitMapping: %d\n" | |
874 "\tInhibitAnyPolicy:%d\n" | |
875 "\tNameConstraints: %s\n" | |
876 "\tAuthorityInfoAccess: %s\n" | |
877 "\tSubjectInfoAccess: %s\n" | |
878 "\tCacheFlag: %d\n" | |
879 "]\n"; | |
880 } | |
881 | |
882 | |
883 | |
884 PKIX_CHECK(PKIX_PL_String_Create | |
885 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), | |
886 PKIX_STRINGCREATEFAILED); | |
887 | |
888 /* Issuer */ | |
889 PKIX_CHECK(PKIX_PL_Cert_GetIssuer | |
890 (cert, &certIssuer, plContext), | |
891 PKIX_CERTGETISSUERFAILED); | |
892 | |
893 PKIX_CHECK(PKIX_PL_Object_ToString | |
894 ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext), | |
895 PKIX_X500NAMETOSTRINGFAILED); | |
896 | |
897 /* Subject */ | |
898 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext), | |
899 PKIX_CERTGETSUBJECTFAILED); | |
900 | |
901 PKIX_TOSTRING(certSubject, &certSubjectString, plContext, | |
902 PKIX_X500NAMETOSTRINGFAILED); | |
903 | |
904 if (partialString){ | |
905 PKIX_CHECK(PKIX_PL_Sprintf | |
906 (&certString, | |
907 plContext, | |
908 formatString, | |
909 certIssuerString, | |
910 certSubjectString), | |
911 PKIX_SPRINTFFAILED); | |
912 | |
913 *pString = certString; | |
914 goto cleanup; | |
915 } | |
916 | |
917 /* Version */ | |
918 PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext), | |
919 PKIX_CERTGETVERSIONFAILED); | |
920 | |
921 /* SerialNumber */ | |
922 PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext), | |
923 PKIX_CERTGETSERIALNUMBERFAILED); | |
924 | |
925 PKIX_CHECK(PKIX_PL_Object_ToString | |
926 ((PKIX_PL_Object *)certSN, &certSNString, plContext), | |
927 PKIX_BIGINTTOSTRINGFAILED); | |
928 | |
929 /* Validity: NotBefore */ | |
930 PKIX_CHECK(pkix_pl_Date_ToString_Helper | |
931 (&(cert->nssCert->validity.notBefore), | |
932 ¬BeforeString, | |
933 plContext), | |
934 PKIX_DATETOSTRINGHELPERFAILED); | |
935 | |
936 /* Validity: NotAfter */ | |
937 PKIX_CHECK(pkix_pl_Date_ToString_Helper | |
938 (&(cert->nssCert->validity.notAfter), | |
939 ¬AfterString, | |
940 plContext), | |
941 PKIX_DATETOSTRINGHELPERFAILED); | |
942 | |
943 /* SubjectAltNames */ | |
944 PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames | |
945 (cert, &subjAltNames, plContext), | |
946 PKIX_CERTGETSUBJECTALTNAMESFAILED); | |
947 | |
948 PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext, | |
949 PKIX_LISTTOSTRINGFAILED); | |
950 | |
951 /* AuthorityKeyIdentifier */ | |
952 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
953 (cert, &authKeyId, plContext), | |
954 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); | |
955 | |
956 PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext, | |
957 PKIX_BYTEARRAYTOSTRINGFAILED); | |
958 | |
959 /* SubjectKeyIdentifier */ | |
960 PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier | |
961 (cert, &subjKeyId, plContext), | |
962 PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); | |
963 | |
964 PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext, | |
965 PKIX_BYTEARRAYTOSTRINGFAILED); | |
966 | |
967 /* SubjectPublicKey */ | |
968 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
969 (cert, &nssPubKey, plContext), | |
970 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
971 | |
972 PKIX_CHECK(PKIX_PL_Object_ToString | |
973 ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext), | |
974 PKIX_PUBLICKEYTOSTRINGFAILED); | |
975 | |
976 /* CriticalExtensionOIDs */ | |
977 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs | |
978 (cert, &critExtOIDs, plContext), | |
979 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); | |
980 | |
981 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, | |
982 PKIX_LISTTOSTRINGFAILED); | |
983 | |
984 /* ExtendedKeyUsages */ | |
985 PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage | |
986 (cert, &extKeyUsages, plContext), | |
987 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); | |
988 | |
989 PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext, | |
990 PKIX_LISTTOSTRINGFAILED); | |
991 | |
992 /* CertBasicConstraints */ | |
993 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints | |
994 (cert, &basicConstraint, plContext), | |
995 PKIX_CERTGETBASICCONSTRAINTSFAILED); | |
996 | |
997 PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext, | |
998 PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED); | |
999 | |
1000 /* CertPolicyInfo */ | |
1001 PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation | |
1002 (cert, &policyInfo, plContext), | |
1003 PKIX_CERTGETPOLICYINFORMATIONFAILED); | |
1004 | |
1005 PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext, | |
1006 PKIX_LISTTOSTRINGFAILED); | |
1007 | |
1008 /* Advanced Policies */ | |
1009 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings | |
1010 (cert, &certPolicyMappings, plContext), | |
1011 PKIX_CERTGETPOLICYMAPPINGSFAILED); | |
1012 | |
1013 PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext, | |
1014 PKIX_LISTTOSTRINGFAILED); | |
1015 | |
1016 PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy | |
1017 (cert, &certExplicitPolicy, plContext), | |
1018 PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); | |
1019 | |
1020 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited | |
1021 (cert, &certInhibitMapping, plContext), | |
1022 PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); | |
1023 | |
1024 PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy | |
1025 (cert, &certInhibitAnyPolicy, plContext), | |
1026 PKIX_CERTGETINHIBITANYPOLICYFAILED); | |
1027 | |
1028 /* Name Constraints */ | |
1029 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints | |
1030 (cert, &nameConstraints, plContext), | |
1031 PKIX_CERTGETNAMECONSTRAINTSFAILED); | |
1032 | |
1033 PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext, | |
1034 PKIX_LISTTOSTRINGFAILED); | |
1035 | |
1036 /* Authority Information Access */ | |
1037 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess | |
1038 (cert, &authorityInfoAccess, plContext), | |
1039 PKIX_CERTGETAUTHORITYINFOACCESSFAILED); | |
1040 | |
1041 PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext
, | |
1042 PKIX_LISTTOSTRINGFAILED); | |
1043 | |
1044 /* Subject Information Access */ | |
1045 PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess | |
1046 (cert, &subjectInfoAccess, plContext), | |
1047 PKIX_CERTGETSUBJECTINFOACCESSFAILED); | |
1048 | |
1049 PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext, | |
1050 PKIX_LISTTOSTRINGFAILED); | |
1051 | |
1052 PKIX_CHECK(PKIX_PL_Sprintf | |
1053 (&certString, | |
1054 plContext, | |
1055 formatString, | |
1056 certVersion + 1, | |
1057 certSNString, | |
1058 certIssuerString, | |
1059 certSubjectString, | |
1060 notBeforeString, | |
1061 notAfterString, | |
1062 subjAltNamesString, | |
1063 authKeyIdString, | |
1064 subjKeyIdString, | |
1065 nssPubKeyString, | |
1066 critExtOIDsString, | |
1067 extKeyUsagesString, | |
1068 certBasicConstraintsString, | |
1069 certPolicyInfoString, | |
1070 certPolicyMappingsString, | |
1071 certExplicitPolicy, /* an Int32, not a String */ | |
1072 certInhibitMapping, /* an Int32, not a String */ | |
1073 certInhibitAnyPolicy, /* an Int32, not a String */ | |
1074 nameConstraintsString, | |
1075 authorityInfoAccessString, | |
1076 subjectInfoAccessString, | |
1077 cert->cacheFlag), /* a boolean */ | |
1078 PKIX_SPRINTFFAILED); | |
1079 | |
1080 *pString = certString; | |
1081 | |
1082 cleanup: | |
1083 PKIX_DECREF(certSN); | |
1084 PKIX_DECREF(certSNString); | |
1085 PKIX_DECREF(certIssuer); | |
1086 PKIX_DECREF(certIssuerString); | |
1087 PKIX_DECREF(certSubject); | |
1088 PKIX_DECREF(certSubjectString); | |
1089 PKIX_DECREF(notBeforeString); | |
1090 PKIX_DECREF(notAfterString); | |
1091 PKIX_DECREF(subjAltNames); | |
1092 PKIX_DECREF(subjAltNamesString); | |
1093 PKIX_DECREF(authKeyId); | |
1094 PKIX_DECREF(authKeyIdString); | |
1095 PKIX_DECREF(subjKeyId); | |
1096 PKIX_DECREF(subjKeyIdString); | |
1097 PKIX_DECREF(nssPubKey); | |
1098 PKIX_DECREF(nssPubKeyString); | |
1099 PKIX_DECREF(critExtOIDs); | |
1100 PKIX_DECREF(critExtOIDsString); | |
1101 PKIX_DECREF(extKeyUsages); | |
1102 PKIX_DECREF(extKeyUsagesString); | |
1103 PKIX_DECREF(basicConstraint); | |
1104 PKIX_DECREF(certBasicConstraintsString); | |
1105 PKIX_DECREF(policyInfo); | |
1106 PKIX_DECREF(certPolicyInfoString); | |
1107 PKIX_DECREF(certPolicyMappings); | |
1108 PKIX_DECREF(certPolicyMappingsString); | |
1109 PKIX_DECREF(nameConstraints); | |
1110 PKIX_DECREF(nameConstraintsString); | |
1111 PKIX_DECREF(authorityInfoAccess); | |
1112 PKIX_DECREF(authorityInfoAccessString); | |
1113 PKIX_DECREF(subjectInfoAccess); | |
1114 PKIX_DECREF(subjectInfoAccessString); | |
1115 PKIX_DECREF(formatString); | |
1116 | |
1117 PKIX_RETURN(CERT); | |
1118 } | |
1119 | |
1120 /* | |
1121 * FUNCTION: pkix_pl_Cert_Destroy | |
1122 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
1123 */ | |
1124 static PKIX_Error * | |
1125 pkix_pl_Cert_Destroy( | |
1126 PKIX_PL_Object *object, | |
1127 void *plContext) | |
1128 { | |
1129 PKIX_PL_Cert *cert = NULL; | |
1130 | |
1131 PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy"); | |
1132 PKIX_NULLCHECK_ONE(object); | |
1133 | |
1134 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
1135 PKIX_OBJECTNOTCERT); | |
1136 | |
1137 cert = (PKIX_PL_Cert*)object; | |
1138 | |
1139 PKIX_DECREF(cert->subject); | |
1140 PKIX_DECREF(cert->issuer); | |
1141 PKIX_DECREF(cert->subjAltNames); | |
1142 PKIX_DECREF(cert->publicKeyAlgId); | |
1143 PKIX_DECREF(cert->publicKey); | |
1144 PKIX_DECREF(cert->serialNumber); | |
1145 PKIX_DECREF(cert->critExtOids); | |
1146 PKIX_DECREF(cert->authKeyId); | |
1147 PKIX_DECREF(cert->subjKeyId); | |
1148 PKIX_DECREF(cert->extKeyUsages); | |
1149 PKIX_DECREF(cert->certBasicConstraints); | |
1150 PKIX_DECREF(cert->certPolicyInfos); | |
1151 PKIX_DECREF(cert->certPolicyMappings); | |
1152 PKIX_DECREF(cert->nameConstraints); | |
1153 PKIX_DECREF(cert->store); | |
1154 PKIX_DECREF(cert->authorityInfoAccess); | |
1155 PKIX_DECREF(cert->subjectInfoAccess); | |
1156 PKIX_DECREF(cert->crldpList); | |
1157 | |
1158 if (cert->arenaNameConstraints){ | |
1159 /* This arena was allocated for SubjectAltNames */ | |
1160 PKIX_PL_NSSCALL(CERT, PORT_FreeArena, | |
1161 (cert->arenaNameConstraints, PR_FALSE)); | |
1162 | |
1163 cert->arenaNameConstraints = NULL; | |
1164 cert->nssSubjAltNames = NULL; | |
1165 } | |
1166 | |
1167 CERT_DestroyCertificate(cert->nssCert); | |
1168 cert->nssCert = NULL; | |
1169 | |
1170 cleanup: | |
1171 PKIX_RETURN(CERT); | |
1172 } | |
1173 | |
1174 /* | |
1175 * FUNCTION: pkix_pl_Cert_ToString | |
1176 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
1177 */ | |
1178 static PKIX_Error * | |
1179 pkix_pl_Cert_ToString( | |
1180 PKIX_PL_Object *object, | |
1181 PKIX_PL_String **pString, | |
1182 void *plContext) | |
1183 { | |
1184 PKIX_PL_String *certString = NULL; | |
1185 PKIX_PL_Cert *pkixCert = NULL; | |
1186 | |
1187 PKIX_ENTER(CERT, "pkix_pl_Cert_toString"); | |
1188 PKIX_NULLCHECK_TWO(object, pString); | |
1189 | |
1190 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
1191 PKIX_OBJECTNOTCERT); | |
1192 | |
1193 pkixCert = (PKIX_PL_Cert *)object; | |
1194 | |
1195 PKIX_CHECK(pkix_pl_Cert_ToString_Helper | |
1196 (pkixCert, PKIX_FALSE, &certString, plContext), | |
1197 PKIX_CERTTOSTRINGHELPERFAILED); | |
1198 | |
1199 *pString = certString; | |
1200 | |
1201 cleanup: | |
1202 PKIX_RETURN(CERT); | |
1203 } | |
1204 | |
1205 /* | |
1206 * FUNCTION: pkix_pl_Cert_Hashcode | |
1207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
1208 */ | |
1209 static PKIX_Error * | |
1210 pkix_pl_Cert_Hashcode( | |
1211 PKIX_PL_Object *object, | |
1212 PKIX_UInt32 *pHashcode, | |
1213 void *plContext) | |
1214 { | |
1215 PKIX_PL_Cert *pkixCert = NULL; | |
1216 CERTCertificate *nssCert = NULL; | |
1217 unsigned char *derBytes = NULL; | |
1218 PKIX_UInt32 derLength; | |
1219 PKIX_UInt32 certHash; | |
1220 | |
1221 PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode"); | |
1222 PKIX_NULLCHECK_TWO(object, pHashcode); | |
1223 | |
1224 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
1225 PKIX_OBJECTNOTCERT); | |
1226 | |
1227 pkixCert = (PKIX_PL_Cert *)object; | |
1228 | |
1229 nssCert = pkixCert->nssCert; | |
1230 derBytes = (nssCert->derCert).data; | |
1231 derLength = (nssCert->derCert).len; | |
1232 | |
1233 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext), | |
1234 PKIX_HASHFAILED); | |
1235 | |
1236 *pHashcode = certHash; | |
1237 | |
1238 cleanup: | |
1239 PKIX_RETURN(CERT); | |
1240 } | |
1241 | |
1242 | |
1243 /* | |
1244 * FUNCTION: pkix_pl_Cert_Equals | |
1245 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
1246 */ | |
1247 static PKIX_Error * | |
1248 pkix_pl_Cert_Equals( | |
1249 PKIX_PL_Object *firstObject, | |
1250 PKIX_PL_Object *secondObject, | |
1251 PKIX_Boolean *pResult, | |
1252 void *plContext) | |
1253 { | |
1254 CERTCertificate *firstCert = NULL; | |
1255 CERTCertificate *secondCert = NULL; | |
1256 PKIX_UInt32 secondType; | |
1257 PKIX_Boolean cmpResult; | |
1258 | |
1259 PKIX_ENTER(CERT, "pkix_pl_Cert_Equals"); | |
1260 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
1261 | |
1262 /* test that firstObject is a Cert */ | |
1263 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext), | |
1264 PKIX_FIRSTOBJECTNOTCERT); | |
1265 | |
1266 /* | |
1267 * Since we know firstObject is a Cert, if both references are | |
1268 * identical, they must be equal | |
1269 */ | |
1270 if (firstObject == secondObject){ | |
1271 *pResult = PKIX_TRUE; | |
1272 goto cleanup; | |
1273 } | |
1274 | |
1275 /* | |
1276 * If secondObject isn't a Cert, we don't throw an error. | |
1277 * We simply return a Boolean result of FALSE | |
1278 */ | |
1279 *pResult = PKIX_FALSE; | |
1280 PKIX_CHECK(PKIX_PL_Object_GetType | |
1281 (secondObject, &secondType, plContext), | |
1282 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
1283 if (secondType != PKIX_CERT_TYPE) goto cleanup; | |
1284 | |
1285 firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert; | |
1286 secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert; | |
1287 | |
1288 PKIX_NULLCHECK_TWO(firstCert, secondCert); | |
1289 | |
1290 /* CERT_CompareCerts does byte comparison on DER encodings of certs */ | |
1291 PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n"); | |
1292 cmpResult = CERT_CompareCerts(firstCert, secondCert); | |
1293 | |
1294 *pResult = cmpResult; | |
1295 | |
1296 cleanup: | |
1297 PKIX_RETURN(CERT); | |
1298 } | |
1299 | |
1300 /* | |
1301 * FUNCTION: pkix_pl_Cert_RegisterSelf | |
1302 * DESCRIPTION: | |
1303 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] | |
1304 * THREAD SAFETY: | |
1305 * Not Thread Safe - for performance and complexity reasons | |
1306 * | |
1307 * Since this function is only called by PKIX_PL_Initialize, which should | |
1308 * only be called once, it is acceptable that this function is not | |
1309 * thread-safe. | |
1310 */ | |
1311 PKIX_Error * | |
1312 pkix_pl_Cert_RegisterSelf(void *plContext) | |
1313 { | |
1314 | |
1315 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
1316 pkix_ClassTable_Entry entry; | |
1317 | |
1318 PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf"); | |
1319 | |
1320 entry.description = "Cert"; | |
1321 entry.objCounter = 0; | |
1322 entry.typeObjectSize = sizeof(PKIX_PL_Cert); | |
1323 entry.destructor = pkix_pl_Cert_Destroy; | |
1324 entry.equalsFunction = pkix_pl_Cert_Equals; | |
1325 entry.hashcodeFunction = pkix_pl_Cert_Hashcode; | |
1326 entry.toStringFunction = pkix_pl_Cert_ToString; | |
1327 entry.comparator = NULL; | |
1328 entry.duplicateFunction = pkix_duplicateImmutable; | |
1329 | |
1330 systemClasses[PKIX_CERT_TYPE] = entry; | |
1331 | |
1332 PKIX_RETURN(CERT); | |
1333 } | |
1334 | |
1335 /* | |
1336 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert | |
1337 * DESCRIPTION: | |
1338 * | |
1339 * Creates a new certificate using the CERTCertificate pointed to by "nssCert" | |
1340 * and stores it at "pCert". Once created, a Cert is immutable. | |
1341 * | |
1342 * This function is primarily used as a convenience function for the | |
1343 * performance tests that have easy access to a CERTCertificate. | |
1344 * | |
1345 * PARAMETERS: | |
1346 * "nssCert" | |
1347 * Address of CERTCertificate representing the NSS certificate. | |
1348 * Must be non-NULL. | |
1349 * "pCert" | |
1350 * Address where object pointer will be stored. Must be non-NULL. | |
1351 * "plContext" | |
1352 * Platform-specific context pointer. | |
1353 * THREAD SAFETY: | |
1354 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1355 * RETURNS: | |
1356 * Returns NULL if the function succeeds. | |
1357 * Returns a Cert Error if the function fails in a non-fatal way. | |
1358 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1359 */ | |
1360 PKIX_Error * | |
1361 pkix_pl_Cert_CreateWithNSSCert( | |
1362 CERTCertificate *nssCert, | |
1363 PKIX_PL_Cert **pCert, | |
1364 void *plContext) | |
1365 { | |
1366 PKIX_PL_Cert *cert = NULL; | |
1367 | |
1368 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert"); | |
1369 PKIX_NULLCHECK_TWO(pCert, nssCert); | |
1370 | |
1371 /* create a PKIX_PL_Cert object */ | |
1372 PKIX_CHECK(PKIX_PL_Object_Alloc | |
1373 (PKIX_CERT_TYPE, | |
1374 sizeof (PKIX_PL_Cert), | |
1375 (PKIX_PL_Object **)&cert, | |
1376 plContext), | |
1377 PKIX_COULDNOTCREATEOBJECT); | |
1378 | |
1379 /* populate the nssCert field */ | |
1380 cert->nssCert = nssCert; | |
1381 | |
1382 /* initialize remaining fields */ | |
1383 /* | |
1384 * Fields ending with Absent are initialized to PKIX_FALSE so that the | |
1385 * first time we need the value we will look for it. If we find it is | |
1386 * actually absent, the flag will at that time be set to PKIX_TRUE to | |
1387 * prevent searching for it later. | |
1388 * Fields ending with Processed are those where a value is defined | |
1389 * for the Absent case, and a value of zero is possible. When the | |
1390 * flag is still true we have to look for the field, set the default | |
1391 * value if necessary, and set the Processed flag to PKIX_TRUE. | |
1392 */ | |
1393 cert->subject = NULL; | |
1394 cert->issuer = NULL; | |
1395 cert->subjAltNames = NULL; | |
1396 cert->subjAltNamesAbsent = PKIX_FALSE; | |
1397 cert->publicKeyAlgId = NULL; | |
1398 cert->publicKey = NULL; | |
1399 cert->serialNumber = NULL; | |
1400 cert->critExtOids = NULL; | |
1401 cert->subjKeyId = NULL; | |
1402 cert->subjKeyIdAbsent = PKIX_FALSE; | |
1403 cert->authKeyId = NULL; | |
1404 cert->authKeyIdAbsent = PKIX_FALSE; | |
1405 cert->extKeyUsages = NULL; | |
1406 cert->extKeyUsagesAbsent = PKIX_FALSE; | |
1407 cert->certBasicConstraints = NULL; | |
1408 cert->basicConstraintsAbsent = PKIX_FALSE; | |
1409 cert->certPolicyInfos = NULL; | |
1410 cert->policyInfoAbsent = PKIX_FALSE; | |
1411 cert->policyMappingsAbsent = PKIX_FALSE; | |
1412 cert->certPolicyMappings = NULL; | |
1413 cert->policyConstraintsProcessed = PKIX_FALSE; | |
1414 cert->policyConstraintsExplicitPolicySkipCerts = 0; | |
1415 cert->policyConstraintsInhibitMappingSkipCerts = 0; | |
1416 cert->inhibitAnyPolicyProcessed = PKIX_FALSE; | |
1417 cert->inhibitAnySkipCerts = 0; | |
1418 cert->nameConstraints = NULL; | |
1419 cert->nameConstraintsAbsent = PKIX_FALSE; | |
1420 cert->arenaNameConstraints = NULL; | |
1421 cert->nssSubjAltNames = NULL; | |
1422 cert->cacheFlag = PKIX_FALSE; | |
1423 cert->store = NULL; | |
1424 cert->authorityInfoAccess = NULL; | |
1425 cert->subjectInfoAccess = NULL; | |
1426 cert->isUserTrustAnchor = PKIX_FALSE; | |
1427 cert->crldpList = NULL; | |
1428 | |
1429 *pCert = cert; | |
1430 | |
1431 cleanup: | |
1432 PKIX_RETURN(CERT); | |
1433 } | |
1434 | |
1435 /* | |
1436 * FUNCTION: pkix_pl_Cert_CreateToList | |
1437 * DESCRIPTION: | |
1438 * | |
1439 * Creates a new certificate using the DER-encoding pointed to by "derCertItem" | |
1440 * and appends it to the list pointed to by "certList". If Cert creation fails, | |
1441 * the function returns with certList unchanged, but any decoding Error is | |
1442 * discarded. | |
1443 * | |
1444 * PARAMETERS: | |
1445 * "derCertItem" | |
1446 * Address of SECItem containing the DER representation of a certificate. | |
1447 * Must be non-NULL. | |
1448 * "certList" | |
1449 * Address of List to which the Cert will be appended, if successfully | |
1450 * created. May be empty, but must be non-NULL. | |
1451 * "plContext" | |
1452 * Platform-specific context pointer. | |
1453 * THREAD SAFETY: | |
1454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1455 * RETURNS: | |
1456 * Returns NULL if the function succeeds. | |
1457 * Returns a Cert Error if the function fails in a non-fatal way. | |
1458 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1459 */ | |
1460 PKIX_Error * | |
1461 pkix_pl_Cert_CreateToList( | |
1462 SECItem *derCertItem, | |
1463 PKIX_List *certList, | |
1464 void *plContext) | |
1465 { | |
1466 CERTCertificate *nssCert = NULL; | |
1467 PKIX_PL_Cert *cert = NULL; | |
1468 CERTCertDBHandle *handle; | |
1469 | |
1470 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList"); | |
1471 PKIX_NULLCHECK_TWO(derCertItem, certList); | |
1472 | |
1473 handle = CERT_GetDefaultCertDB(); | |
1474 nssCert = CERT_NewTempCertificate(handle, derCertItem, | |
1475 /* nickname */ NULL, | |
1476 /* isPerm */ PR_FALSE, | |
1477 /* copyDer */ PR_TRUE); | |
1478 if (!nssCert) { | |
1479 goto cleanup; | |
1480 } | |
1481 | |
1482 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
1483 (nssCert, &cert, plContext), | |
1484 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1485 | |
1486 nssCert = NULL; | |
1487 | |
1488 PKIX_CHECK(PKIX_List_AppendItem | |
1489 (certList, (PKIX_PL_Object *) cert, plContext), | |
1490 PKIX_LISTAPPENDITEMFAILED); | |
1491 | |
1492 cleanup: | |
1493 if (nssCert) { | |
1494 CERT_DestroyCertificate(nssCert); | |
1495 } | |
1496 | |
1497 PKIX_DECREF(cert); | |
1498 PKIX_RETURN(CERT); | |
1499 } | |
1500 | |
1501 /* --Public-Functions------------------------------------------------------- */ | |
1502 | |
1503 /* | |
1504 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h) | |
1505 * XXX We may want to cache the cert after parsing it, so it can be reused | |
1506 * XXX Are the NSS/NSPR functions thread safe | |
1507 */ | |
1508 PKIX_Error * | |
1509 PKIX_PL_Cert_Create( | |
1510 PKIX_PL_ByteArray *byteArray, | |
1511 PKIX_PL_Cert **pCert, | |
1512 void *plContext) | |
1513 { | |
1514 CERTCertificate *nssCert = NULL; | |
1515 SECItem *derCertItem = NULL; | |
1516 void *derBytes = NULL; | |
1517 PKIX_UInt32 derLength; | |
1518 PKIX_PL_Cert *cert = NULL; | |
1519 CERTCertDBHandle *handle; | |
1520 | |
1521 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); | |
1522 PKIX_NULLCHECK_TWO(pCert, byteArray); | |
1523 | |
1524 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer | |
1525 (byteArray, &derBytes, plContext), | |
1526 PKIX_BYTEARRAYGETPOINTERFAILED); | |
1527 | |
1528 PKIX_CHECK(PKIX_PL_ByteArray_GetLength | |
1529 (byteArray, &derLength, plContext), | |
1530 PKIX_BYTEARRAYGETLENGTHFAILED); | |
1531 | |
1532 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); | |
1533 if (derCertItem == NULL){ | |
1534 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
1535 } | |
1536 | |
1537 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); | |
1538 | |
1539 /* | |
1540 * setting copyDER to true forces NSS to make its own copy of the DER, | |
1541 * allowing us to free our copy without worrying about whether NSS | |
1542 * is still using it | |
1543 */ | |
1544 handle = CERT_GetDefaultCertDB(); | |
1545 nssCert = CERT_NewTempCertificate(handle, derCertItem, | |
1546 /* nickname */ NULL, | |
1547 /* isPerm */ PR_FALSE, | |
1548 /* copyDer */ PR_TRUE); | |
1549 if (!nssCert){ | |
1550 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); | |
1551 } | |
1552 | |
1553 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
1554 (nssCert, &cert, plContext), | |
1555 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1556 | |
1557 *pCert = cert; | |
1558 | |
1559 cleanup: | |
1560 if (derCertItem){ | |
1561 SECITEM_FreeItem(derCertItem, PKIX_TRUE); | |
1562 } | |
1563 | |
1564 if (nssCert && PKIX_ERROR_RECEIVED){ | |
1565 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
1566 CERT_DestroyCertificate(nssCert); | |
1567 nssCert = NULL; | |
1568 } | |
1569 | |
1570 PKIX_FREE(derBytes); | |
1571 PKIX_RETURN(CERT); | |
1572 } | |
1573 | |
1574 | |
1575 /* | |
1576 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate | |
1577 * (see comments in pkix_pl_pki.h) | |
1578 */ | |
1579 PKIX_Error * | |
1580 PKIX_PL_Cert_CreateFromCERTCertificate( | |
1581 const CERTCertificate *nssCert, | |
1582 PKIX_PL_Cert **pCert, | |
1583 void *plContext) | |
1584 { | |
1585 void *buf = NULL; | |
1586 PKIX_UInt32 len; | |
1587 PKIX_PL_ByteArray *byteArray = NULL; | |
1588 | |
1589 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); | |
1590 PKIX_NULLCHECK_TWO(pCert, nssCert); | |
1591 | |
1592 buf = (void*)nssCert->derCert.data; | |
1593 len = nssCert->derCert.len; | |
1594 | |
1595 PKIX_CHECK( | |
1596 PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), | |
1597 PKIX_BYTEARRAYCREATEFAILED); | |
1598 | |
1599 PKIX_CHECK( | |
1600 PKIX_PL_Cert_Create(byteArray, pCert, plContext), | |
1601 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1602 | |
1603 #ifdef PKIX_UNDEF | |
1604 /* will be tested and used as a patch for bug 391612 */ | |
1605 nssCert = CERT_DupCertificate(nssInCert); | |
1606 | |
1607 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
1608 (nssCert, &cert, plContext), | |
1609 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1610 #endif /* PKIX_UNDEF */ | |
1611 | |
1612 cleanup: | |
1613 | |
1614 #ifdef PKIX_UNDEF | |
1615 if (nssCert && PKIX_ERROR_RECEIVED){ | |
1616 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
1617 CERT_DestroyCertificate(nssCert); | |
1618 nssCert = NULL; | |
1619 } | |
1620 #endif /* PKIX_UNDEF */ | |
1621 | |
1622 PKIX_DECREF(byteArray); | |
1623 PKIX_RETURN(CERT); | |
1624 } | |
1625 | |
1626 | |
1627 /* | |
1628 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) | |
1629 */ | |
1630 PKIX_Error * | |
1631 PKIX_PL_Cert_GetVersion( | |
1632 PKIX_PL_Cert *cert, | |
1633 PKIX_UInt32 *pVersion, | |
1634 void *plContext) | |
1635 { | |
1636 CERTCertificate *nssCert = NULL; | |
1637 PKIX_UInt32 myVersion = 0; /* v1 */ | |
1638 | |
1639 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); | |
1640 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); | |
1641 | |
1642 nssCert = cert->nssCert; | |
1643 if (nssCert->version.len != 0) { | |
1644 myVersion = *(nssCert->version.data); | |
1645 } | |
1646 | |
1647 if (myVersion > 2){ | |
1648 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); | |
1649 } | |
1650 | |
1651 *pVersion = myVersion; | |
1652 | |
1653 cleanup: | |
1654 PKIX_RETURN(CERT); | |
1655 } | |
1656 | |
1657 /* | |
1658 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) | |
1659 */ | |
1660 PKIX_Error * | |
1661 PKIX_PL_Cert_GetSerialNumber( | |
1662 PKIX_PL_Cert *cert, | |
1663 PKIX_PL_BigInt **pSerialNumber, | |
1664 void *plContext) | |
1665 { | |
1666 CERTCertificate *nssCert = NULL; | |
1667 SECItem serialNumItem; | |
1668 PKIX_PL_BigInt *serialNumber = NULL; | |
1669 char *bytes = NULL; | |
1670 PKIX_UInt32 length; | |
1671 | |
1672 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); | |
1673 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); | |
1674 | |
1675 if (cert->serialNumber == NULL){ | |
1676 | |
1677 PKIX_OBJECT_LOCK(cert); | |
1678 | |
1679 if (cert->serialNumber == NULL){ | |
1680 | |
1681 nssCert = cert->nssCert; | |
1682 serialNumItem = nssCert->serialNumber; | |
1683 | |
1684 length = serialNumItem.len; | |
1685 bytes = (char *)serialNumItem.data; | |
1686 | |
1687 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes | |
1688 (bytes, length, &serialNumber, plContext), | |
1689 PKIX_BIGINTCREATEWITHBYTESFAILED); | |
1690 | |
1691 /* save a cached copy in case it is asked for again */ | |
1692 cert->serialNumber = serialNumber; | |
1693 } | |
1694 | |
1695 PKIX_OBJECT_UNLOCK(cert); | |
1696 } | |
1697 | |
1698 PKIX_INCREF(cert->serialNumber); | |
1699 *pSerialNumber = cert->serialNumber; | |
1700 | |
1701 cleanup: | |
1702 PKIX_OBJECT_UNLOCK(lockedObject); | |
1703 PKIX_RETURN(CERT); | |
1704 } | |
1705 | |
1706 /* | |
1707 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) | |
1708 */ | |
1709 PKIX_Error * | |
1710 PKIX_PL_Cert_GetSubject( | |
1711 PKIX_PL_Cert *cert, | |
1712 PKIX_PL_X500Name **pCertSubject, | |
1713 void *plContext) | |
1714 { | |
1715 PKIX_PL_X500Name *pkixSubject = NULL; | |
1716 CERTName *subjName = NULL; | |
1717 SECItem *derSubjName = NULL; | |
1718 | |
1719 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); | |
1720 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); | |
1721 | |
1722 /* if we don't have a cached copy from before, we create one */ | |
1723 if (cert->subject == NULL){ | |
1724 | |
1725 PKIX_OBJECT_LOCK(cert); | |
1726 | |
1727 if (cert->subject == NULL){ | |
1728 | |
1729 subjName = &cert->nssCert->subject; | |
1730 derSubjName = &cert->nssCert->derSubject; | |
1731 | |
1732 /* if there is no subject name */ | |
1733 if (derSubjName->data == NULL) { | |
1734 | |
1735 pkixSubject = NULL; | |
1736 | |
1737 } else { | |
1738 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
1739 (derSubjName, subjName, &pkixSubject, | |
1740 plContext), | |
1741 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
1742 | |
1743 } | |
1744 /* save a cached copy in case it is asked for again */ | |
1745 cert->subject = pkixSubject; | |
1746 } | |
1747 | |
1748 PKIX_OBJECT_UNLOCK(cert); | |
1749 } | |
1750 | |
1751 PKIX_INCREF(cert->subject); | |
1752 *pCertSubject = cert->subject; | |
1753 | |
1754 cleanup: | |
1755 PKIX_OBJECT_UNLOCK(lockedObject); | |
1756 PKIX_RETURN(CERT); | |
1757 } | |
1758 | |
1759 /* | |
1760 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) | |
1761 */ | |
1762 PKIX_Error * | |
1763 PKIX_PL_Cert_GetIssuer( | |
1764 PKIX_PL_Cert *cert, | |
1765 PKIX_PL_X500Name **pCertIssuer, | |
1766 void *plContext) | |
1767 { | |
1768 PKIX_PL_X500Name *pkixIssuer = NULL; | |
1769 SECItem *derIssuerName = NULL; | |
1770 CERTName *issuerName = NULL; | |
1771 | |
1772 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); | |
1773 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); | |
1774 | |
1775 /* if we don't have a cached copy from before, we create one */ | |
1776 if (cert->issuer == NULL){ | |
1777 | |
1778 PKIX_OBJECT_LOCK(cert); | |
1779 | |
1780 if (cert->issuer == NULL){ | |
1781 | |
1782 issuerName = &cert->nssCert->issuer; | |
1783 derIssuerName = &cert->nssCert->derIssuer; | |
1784 | |
1785 /* if there is no subject name */ | |
1786 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
1787 (derIssuerName, issuerName, | |
1788 &pkixIssuer, plContext), | |
1789 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
1790 | |
1791 /* save a cached copy in case it is asked for again */ | |
1792 cert->issuer = pkixIssuer; | |
1793 } | |
1794 | |
1795 PKIX_OBJECT_UNLOCK(cert); | |
1796 } | |
1797 | |
1798 PKIX_INCREF(cert->issuer); | |
1799 *pCertIssuer = cert->issuer; | |
1800 | |
1801 cleanup: | |
1802 PKIX_RETURN(CERT); | |
1803 } | |
1804 | |
1805 /* | |
1806 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) | |
1807 */ | |
1808 PKIX_Error * | |
1809 PKIX_PL_Cert_GetSubjectAltNames( | |
1810 PKIX_PL_Cert *cert, | |
1811 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ | |
1812 void *plContext) | |
1813 { | |
1814 PKIX_PL_GeneralName *pkixAltName = NULL; | |
1815 PKIX_List *altNamesList = NULL; | |
1816 | |
1817 CERTGeneralName *nssOriginalAltName = NULL; | |
1818 CERTGeneralName *nssTempAltName = NULL; | |
1819 | |
1820 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); | |
1821 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); | |
1822 | |
1823 /* if we don't have a cached copy from before, we create one */ | |
1824 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ | |
1825 | |
1826 PKIX_OBJECT_LOCK(cert); | |
1827 | |
1828 if ((cert->subjAltNames == NULL) && | |
1829 (!cert->subjAltNamesAbsent)){ | |
1830 | |
1831 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
1832 (cert, | |
1833 PKIX_TRUE, | |
1834 &nssOriginalAltName, | |
1835 plContext), | |
1836 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
1837 | |
1838 if (nssOriginalAltName == NULL) { | |
1839 cert->subjAltNamesAbsent = PKIX_TRUE; | |
1840 pSubjectAltNames = NULL; | |
1841 goto cleanup; | |
1842 } | |
1843 | |
1844 nssTempAltName = nssOriginalAltName; | |
1845 | |
1846 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), | |
1847 PKIX_LISTCREATEFAILED); | |
1848 | |
1849 do { | |
1850 PKIX_CHECK(pkix_pl_GeneralName_Create | |
1851 (nssTempAltName, &pkixAltName, plContext), | |
1852 PKIX_GENERALNAMECREATEFAILED); | |
1853 | |
1854 PKIX_CHECK(PKIX_List_AppendItem | |
1855 (altNamesList, | |
1856 (PKIX_PL_Object *)pkixAltName, | |
1857 plContext), | |
1858 PKIX_LISTAPPENDITEMFAILED); | |
1859 | |
1860 PKIX_DECREF(pkixAltName); | |
1861 | |
1862 PKIX_CERT_DEBUG | |
1863 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
1864 nssTempAltName = CERT_GetNextGeneralName | |
1865 (nssTempAltName); | |
1866 | |
1867 } while (nssTempAltName != nssOriginalAltName); | |
1868 | |
1869 /* save a cached copy in case it is asked for again */ | |
1870 cert->subjAltNames = altNamesList; | |
1871 PKIX_CHECK(PKIX_List_SetImmutable | |
1872 (cert->subjAltNames, plContext), | |
1873 PKIX_LISTSETIMMUTABLEFAILED); | |
1874 | |
1875 } | |
1876 | |
1877 PKIX_OBJECT_UNLOCK(cert); | |
1878 } | |
1879 | |
1880 PKIX_INCREF(cert->subjAltNames); | |
1881 | |
1882 *pSubjectAltNames = cert->subjAltNames; | |
1883 | |
1884 cleanup: | |
1885 PKIX_DECREF(pkixAltName); | |
1886 if (PKIX_ERROR_RECEIVED){ | |
1887 PKIX_DECREF(altNamesList); | |
1888 } | |
1889 PKIX_RETURN(CERT); | |
1890 } | |
1891 | |
1892 /* | |
1893 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) | |
1894 */ | |
1895 PKIX_Error * | |
1896 PKIX_PL_Cert_GetAllSubjectNames( | |
1897 PKIX_PL_Cert *cert, | |
1898 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ | |
1899 void *plContext) | |
1900 { | |
1901 CERTGeneralName *nssOriginalSubjectName = NULL; | |
1902 CERTGeneralName *nssTempSubjectName = NULL; | |
1903 PKIX_List *allSubjectNames = NULL; | |
1904 PKIX_PL_GeneralName *pkixSubjectName = NULL; | |
1905 PLArenaPool *arena = NULL; | |
1906 | |
1907 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); | |
1908 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); | |
1909 | |
1910 | |
1911 if (cert->nssCert->subjectName == NULL){ | |
1912 /* if there is no subject DN, just get altnames */ | |
1913 | |
1914 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
1915 (cert, | |
1916 PKIX_FALSE, /* hasLock */ | |
1917 &nssOriginalSubjectName, | |
1918 plContext), | |
1919 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
1920 | |
1921 } else { /* get subject DN and altnames */ | |
1922 | |
1923 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1924 if (arena == NULL) { | |
1925 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
1926 } | |
1927 | |
1928 /* This NSS call returns both Subject and Subject Alt Names */ | |
1929 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); | |
1930 nssOriginalSubjectName = | |
1931 CERT_GetCertificateNames(cert->nssCert, arena); | |
1932 } | |
1933 | |
1934 if (nssOriginalSubjectName == NULL) { | |
1935 pAllSubjectNames = NULL; | |
1936 goto cleanup; | |
1937 } | |
1938 | |
1939 nssTempSubjectName = nssOriginalSubjectName; | |
1940 | |
1941 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), | |
1942 PKIX_LISTCREATEFAILED); | |
1943 | |
1944 do { | |
1945 PKIX_CHECK(pkix_pl_GeneralName_Create | |
1946 (nssTempSubjectName, &pkixSubjectName, plContext), | |
1947 PKIX_GENERALNAMECREATEFAILED); | |
1948 | |
1949 PKIX_CHECK(PKIX_List_AppendItem | |
1950 (allSubjectNames, | |
1951 (PKIX_PL_Object *)pkixSubjectName, | |
1952 plContext), | |
1953 PKIX_LISTAPPENDITEMFAILED); | |
1954 | |
1955 PKIX_DECREF(pkixSubjectName); | |
1956 | |
1957 PKIX_CERT_DEBUG | |
1958 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
1959 nssTempSubjectName = CERT_GetNextGeneralName | |
1960 (nssTempSubjectName); | |
1961 } while (nssTempSubjectName != nssOriginalSubjectName); | |
1962 | |
1963 *pAllSubjectNames = allSubjectNames; | |
1964 | |
1965 cleanup: | |
1966 if (PKIX_ERROR_RECEIVED){ | |
1967 PKIX_DECREF(allSubjectNames); | |
1968 } | |
1969 | |
1970 if (arena){ | |
1971 PORT_FreeArena(arena, PR_FALSE); | |
1972 } | |
1973 PKIX_DECREF(pkixSubjectName); | |
1974 PKIX_RETURN(CERT); | |
1975 } | |
1976 | |
1977 /* | |
1978 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId | |
1979 * (see comments in pkix_pl_pki.h) | |
1980 */ | |
1981 PKIX_Error * | |
1982 PKIX_PL_Cert_GetSubjectPublicKeyAlgId( | |
1983 PKIX_PL_Cert *cert, | |
1984 PKIX_PL_OID **pSubjKeyAlgId, | |
1985 void *plContext) | |
1986 { | |
1987 PKIX_PL_OID *pubKeyAlgId = NULL; | |
1988 | |
1989 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); | |
1990 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); | |
1991 | |
1992 /* if we don't have a cached copy from before, we create one */ | |
1993 if (cert->publicKeyAlgId == NULL){ | |
1994 PKIX_OBJECT_LOCK(cert); | |
1995 if (cert->publicKeyAlgId == NULL){ | |
1996 CERTCertificate *nssCert = cert->nssCert; | |
1997 SECAlgorithmID *algorithm; | |
1998 SECItem *algBytes; | |
1999 | |
2000 algorithm = &nssCert->subjectPublicKeyInfo.algorithm; | |
2001 algBytes = &algorithm->algorithm; | |
2002 if (!algBytes->data || !algBytes->len) { | |
2003 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); | |
2004 } | |
2005 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
2006 (algBytes, &pubKeyAlgId, plContext), | |
2007 PKIX_OIDCREATEFAILED); | |
2008 | |
2009 /* save a cached copy in case it is asked for again */ | |
2010 cert->publicKeyAlgId = pubKeyAlgId; | |
2011 pubKeyAlgId = NULL; | |
2012 } | |
2013 PKIX_OBJECT_UNLOCK(cert); | |
2014 } | |
2015 | |
2016 PKIX_INCREF(cert->publicKeyAlgId); | |
2017 *pSubjKeyAlgId = cert->publicKeyAlgId; | |
2018 | |
2019 cleanup: | |
2020 PKIX_DECREF(pubKeyAlgId); | |
2021 PKIX_RETURN(CERT); | |
2022 } | |
2023 | |
2024 /* | |
2025 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) | |
2026 */ | |
2027 PKIX_Error * | |
2028 PKIX_PL_Cert_GetSubjectPublicKey( | |
2029 PKIX_PL_Cert *cert, | |
2030 PKIX_PL_PublicKey **pPublicKey, | |
2031 void *plContext) | |
2032 { | |
2033 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
2034 SECStatus rv; | |
2035 | |
2036 CERTSubjectPublicKeyInfo *from = NULL; | |
2037 CERTSubjectPublicKeyInfo *to = NULL; | |
2038 SECItem *fromItem = NULL; | |
2039 SECItem *toItem = NULL; | |
2040 | |
2041 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); | |
2042 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); | |
2043 | |
2044 /* if we don't have a cached copy from before, we create one */ | |
2045 if (cert->publicKey == NULL){ | |
2046 | |
2047 PKIX_OBJECT_LOCK(cert); | |
2048 | |
2049 if (cert->publicKey == NULL){ | |
2050 | |
2051 /* create a PKIX_PL_PublicKey object */ | |
2052 PKIX_CHECK(PKIX_PL_Object_Alloc | |
2053 (PKIX_PUBLICKEY_TYPE, | |
2054 sizeof (PKIX_PL_PublicKey), | |
2055 (PKIX_PL_Object **)&pkixPubKey, | |
2056 plContext), | |
2057 PKIX_COULDNOTCREATEOBJECT); | |
2058 | |
2059 /* initialize fields */ | |
2060 pkixPubKey->nssSPKI = NULL; | |
2061 | |
2062 /* populate the SPKI field */ | |
2063 PKIX_CHECK(PKIX_PL_Malloc | |
2064 (sizeof (CERTSubjectPublicKeyInfo), | |
2065 (void **)&pkixPubKey->nssSPKI, | |
2066 plContext), | |
2067 PKIX_MALLOCFAILED); | |
2068 | |
2069 to = pkixPubKey->nssSPKI; | |
2070 from = &cert->nssCert->subjectPublicKeyInfo; | |
2071 | |
2072 PKIX_NULLCHECK_TWO(to, from); | |
2073 | |
2074 PKIX_CERT_DEBUG | |
2075 ("\t\tCalling SECOID_CopyAlgorithmID).\n"); | |
2076 rv = SECOID_CopyAlgorithmID | |
2077 (NULL, &to->algorithm, &from->algorithm); | |
2078 if (rv != SECSuccess) { | |
2079 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); | |
2080 } | |
2081 | |
2082 /* | |
2083 * NSS stores the length of subjectPublicKey in bits. | |
2084 * Therefore, we use that length converted to bytes | |
2085 * using ((length+7)>>3) before calling PORT_Memcpy | |
2086 * in order to avoid "read from uninitialized memory" | |
2087 * errors. | |
2088 */ | |
2089 | |
2090 toItem = &to->subjectPublicKey; | |
2091 fromItem = &from->subjectPublicKey; | |
2092 | |
2093 PKIX_NULLCHECK_TWO(toItem, fromItem); | |
2094 | |
2095 toItem->type = fromItem->type; | |
2096 | |
2097 toItem->data = | |
2098 (unsigned char*) PORT_ZAlloc(fromItem->len); | |
2099 if (!toItem->data){ | |
2100 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2101 } | |
2102 | |
2103 (void) PORT_Memcpy(toItem->data, | |
2104 fromItem->data, | |
2105 (fromItem->len + 7)>>3); | |
2106 toItem->len = fromItem->len; | |
2107 | |
2108 /* save a cached copy in case it is asked for again */ | |
2109 cert->publicKey = pkixPubKey; | |
2110 } | |
2111 | |
2112 PKIX_OBJECT_UNLOCK(cert); | |
2113 } | |
2114 | |
2115 PKIX_INCREF(cert->publicKey); | |
2116 *pPublicKey = cert->publicKey; | |
2117 | |
2118 cleanup: | |
2119 | |
2120 if (PKIX_ERROR_RECEIVED && pkixPubKey){ | |
2121 PKIX_DECREF(pkixPubKey); | |
2122 cert->publicKey = NULL; | |
2123 } | |
2124 PKIX_RETURN(CERT); | |
2125 } | |
2126 | |
2127 /* | |
2128 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs | |
2129 * (see comments in pkix_pl_pki.h) | |
2130 */ | |
2131 PKIX_Error * | |
2132 PKIX_PL_Cert_GetCriticalExtensionOIDs( | |
2133 PKIX_PL_Cert *cert, | |
2134 PKIX_List **pList, /* list of PKIX_PL_OID */ | |
2135 void *plContext) | |
2136 { | |
2137 PKIX_List *oidsList = NULL; | |
2138 CERTCertExtension **extensions = NULL; | |
2139 CERTCertificate *nssCert = NULL; | |
2140 | |
2141 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); | |
2142 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); | |
2143 | |
2144 /* if we don't have a cached copy from before, we create one */ | |
2145 if (cert->critExtOids == NULL) { | |
2146 | |
2147 PKIX_OBJECT_LOCK(cert); | |
2148 | |
2149 if (cert->critExtOids == NULL) { | |
2150 | |
2151 nssCert = cert->nssCert; | |
2152 | |
2153 /* | |
2154 * ASN.1 for Extension | |
2155 * | |
2156 * Extension ::= SEQUENCE { | |
2157 * extnID OBJECT IDENTIFIER, | |
2158 * critical BOOLEAN DEFAULT FALSE, | |
2159 * extnValue OCTET STRING } | |
2160 * | |
2161 */ | |
2162 | |
2163 extensions = nssCert->extensions; | |
2164 | |
2165 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs | |
2166 (extensions, &oidsList, plContext), | |
2167 PKIX_GETCRITICALEXTENSIONOIDSFAILED); | |
2168 | |
2169 /* save a cached copy in case it is asked for again */ | |
2170 cert->critExtOids = oidsList; | |
2171 } | |
2172 | |
2173 PKIX_OBJECT_UNLOCK(cert); | |
2174 } | |
2175 | |
2176 /* We should return a copy of the List since this list changes */ | |
2177 PKIX_DUPLICATE(cert->critExtOids, pList, plContext, | |
2178 PKIX_OBJECTDUPLICATELISTFAILED); | |
2179 | |
2180 cleanup: | |
2181 PKIX_OBJECT_UNLOCK(lockedObject); | |
2182 PKIX_RETURN(CERT); | |
2183 } | |
2184 | |
2185 /* | |
2186 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
2187 * (see comments in pkix_pl_pki.h) | |
2188 */ | |
2189 PKIX_Error * | |
2190 PKIX_PL_Cert_GetAuthorityKeyIdentifier( | |
2191 PKIX_PL_Cert *cert, | |
2192 PKIX_PL_ByteArray **pAuthKeyId, | |
2193 void *plContext) | |
2194 { | |
2195 PKIX_PL_ByteArray *authKeyId = NULL; | |
2196 CERTCertificate *nssCert = NULL; | |
2197 CERTAuthKeyID *authKeyIdExtension = NULL; | |
2198 PLArenaPool *arena = NULL; | |
2199 SECItem retItem; | |
2200 | |
2201 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); | |
2202 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); | |
2203 | |
2204 /* if we don't have a cached copy from before, we create one */ | |
2205 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
2206 | |
2207 PKIX_OBJECT_LOCK(cert); | |
2208 | |
2209 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
2210 | |
2211 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
2212 if (arena == NULL) { | |
2213 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2214 } | |
2215 | |
2216 nssCert = cert->nssCert; | |
2217 | |
2218 authKeyIdExtension = | |
2219 CERT_FindAuthKeyIDExten(arena, nssCert); | |
2220 if (authKeyIdExtension == NULL){ | |
2221 cert->authKeyIdAbsent = PKIX_TRUE; | |
2222 *pAuthKeyId = NULL; | |
2223 goto cleanup; | |
2224 } | |
2225 | |
2226 retItem = authKeyIdExtension->keyID; | |
2227 | |
2228 if (retItem.len == 0){ | |
2229 cert->authKeyIdAbsent = PKIX_TRUE; | |
2230 *pAuthKeyId = NULL; | |
2231 goto cleanup; | |
2232 } | |
2233 | |
2234 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
2235 (retItem.data, | |
2236 retItem.len, | |
2237 &authKeyId, | |
2238 plContext), | |
2239 PKIX_BYTEARRAYCREATEFAILED); | |
2240 | |
2241 /* save a cached copy in case it is asked for again */ | |
2242 cert->authKeyId = authKeyId; | |
2243 } | |
2244 | |
2245 PKIX_OBJECT_UNLOCK(cert); | |
2246 } | |
2247 | |
2248 PKIX_INCREF(cert->authKeyId); | |
2249 *pAuthKeyId = cert->authKeyId; | |
2250 | |
2251 cleanup: | |
2252 PKIX_OBJECT_UNLOCK(lockedObject); | |
2253 if (arena){ | |
2254 PORT_FreeArena(arena, PR_FALSE); | |
2255 } | |
2256 PKIX_RETURN(CERT); | |
2257 } | |
2258 | |
2259 /* | |
2260 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier | |
2261 * (see comments in pkix_pl_pki.h) | |
2262 */ | |
2263 PKIX_Error * | |
2264 PKIX_PL_Cert_GetSubjectKeyIdentifier( | |
2265 PKIX_PL_Cert *cert, | |
2266 PKIX_PL_ByteArray **pSubjKeyId, | |
2267 void *plContext) | |
2268 { | |
2269 PKIX_PL_ByteArray *subjKeyId = NULL; | |
2270 CERTCertificate *nssCert = NULL; | |
2271 SECItem *retItem = NULL; | |
2272 SECStatus status; | |
2273 | |
2274 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); | |
2275 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); | |
2276 | |
2277 /* if we don't have a cached copy from before, we create one */ | |
2278 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
2279 | |
2280 PKIX_OBJECT_LOCK(cert); | |
2281 | |
2282 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
2283 | |
2284 retItem = SECITEM_AllocItem(NULL, NULL, 0); | |
2285 if (retItem == NULL){ | |
2286 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2287 } | |
2288 | |
2289 nssCert = cert->nssCert; | |
2290 | |
2291 status = CERT_FindSubjectKeyIDExtension | |
2292 (nssCert, retItem); | |
2293 if (status != SECSuccess) { | |
2294 cert->subjKeyIdAbsent = PKIX_TRUE; | |
2295 *pSubjKeyId = NULL; | |
2296 goto cleanup; | |
2297 } | |
2298 | |
2299 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
2300 (retItem->data, | |
2301 retItem->len, | |
2302 &subjKeyId, | |
2303 plContext), | |
2304 PKIX_BYTEARRAYCREATEFAILED); | |
2305 | |
2306 /* save a cached copy in case it is asked for again */ | |
2307 cert->subjKeyId = subjKeyId; | |
2308 } | |
2309 | |
2310 PKIX_OBJECT_UNLOCK(cert); | |
2311 } | |
2312 | |
2313 PKIX_INCREF(cert->subjKeyId); | |
2314 *pSubjKeyId = cert->subjKeyId; | |
2315 | |
2316 cleanup: | |
2317 PKIX_OBJECT_UNLOCK(lockedObject); | |
2318 if (retItem){ | |
2319 SECITEM_FreeItem(retItem, PKIX_TRUE); | |
2320 } | |
2321 PKIX_RETURN(CERT); | |
2322 } | |
2323 | |
2324 /* | |
2325 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) | |
2326 */ | |
2327 PKIX_Error * | |
2328 PKIX_PL_Cert_GetExtendedKeyUsage( | |
2329 PKIX_PL_Cert *cert, | |
2330 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ | |
2331 void *plContext) | |
2332 { | |
2333 CERTOidSequence *extKeyUsage = NULL; | |
2334 CERTCertificate *nssCert = NULL; | |
2335 PKIX_PL_OID *pkixOID = NULL; | |
2336 PKIX_List *oidsList = NULL; | |
2337 SECItem **oids = NULL; | |
2338 SECItem encodedExtKeyUsage; | |
2339 SECStatus rv; | |
2340 | |
2341 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); | |
2342 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); | |
2343 | |
2344 /* if we don't have a cached copy from before, we create one */ | |
2345 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ | |
2346 | |
2347 PKIX_OBJECT_LOCK(cert); | |
2348 | |
2349 if ((cert->extKeyUsages == NULL) && | |
2350 (!cert->extKeyUsagesAbsent)){ | |
2351 | |
2352 nssCert = cert->nssCert; | |
2353 | |
2354 rv = CERT_FindCertExtension | |
2355 (nssCert, SEC_OID_X509_EXT_KEY_USAGE, | |
2356 &encodedExtKeyUsage); | |
2357 if (rv != SECSuccess){ | |
2358 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
2359 *pKeyUsage = NULL; | |
2360 goto cleanup; | |
2361 } | |
2362 | |
2363 extKeyUsage = | |
2364 CERT_DecodeOidSequence(&encodedExtKeyUsage); | |
2365 if (extKeyUsage == NULL){ | |
2366 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); | |
2367 } | |
2368 | |
2369 PORT_Free(encodedExtKeyUsage.data); | |
2370 | |
2371 oids = extKeyUsage->oids; | |
2372 | |
2373 if (!oids){ | |
2374 /* no extended key usage extensions found */ | |
2375 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
2376 *pKeyUsage = NULL; | |
2377 goto cleanup; | |
2378 } | |
2379 | |
2380 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), | |
2381 PKIX_LISTCREATEFAILED); | |
2382 | |
2383 while (*oids){ | |
2384 SECItem *oid = *oids++; | |
2385 | |
2386 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
2387 (oid, &pkixOID, plContext), | |
2388 PKIX_OIDCREATEFAILED); | |
2389 | |
2390 PKIX_CHECK(PKIX_List_AppendItem | |
2391 (oidsList, | |
2392 (PKIX_PL_Object *)pkixOID, | |
2393 plContext), | |
2394 PKIX_LISTAPPENDITEMFAILED); | |
2395 PKIX_DECREF(pkixOID); | |
2396 } | |
2397 | |
2398 PKIX_CHECK(PKIX_List_SetImmutable | |
2399 (oidsList, plContext), | |
2400 PKIX_LISTSETIMMUTABLEFAILED); | |
2401 | |
2402 /* save a cached copy in case it is asked for again */ | |
2403 cert->extKeyUsages = oidsList; | |
2404 oidsList = NULL; | |
2405 } | |
2406 | |
2407 PKIX_OBJECT_UNLOCK(cert); | |
2408 } | |
2409 | |
2410 PKIX_INCREF(cert->extKeyUsages); | |
2411 *pKeyUsage = cert->extKeyUsages; | |
2412 | |
2413 cleanup: | |
2414 PKIX_OBJECT_UNLOCK(lockedObject); | |
2415 | |
2416 PKIX_DECREF(pkixOID); | |
2417 PKIX_DECREF(oidsList); | |
2418 CERT_DestroyOidSequence(extKeyUsage); | |
2419 | |
2420 PKIX_RETURN(CERT); | |
2421 } | |
2422 | |
2423 /* | |
2424 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints | |
2425 * (see comments in pkix_pl_pki.h) | |
2426 */ | |
2427 PKIX_Error * | |
2428 PKIX_PL_Cert_GetBasicConstraints( | |
2429 PKIX_PL_Cert *cert, | |
2430 PKIX_PL_CertBasicConstraints **pBasicConstraints, | |
2431 void *plContext) | |
2432 { | |
2433 CERTCertificate *nssCert = NULL; | |
2434 CERTBasicConstraints nssBasicConstraint; | |
2435 SECStatus rv; | |
2436 PKIX_PL_CertBasicConstraints *basic; | |
2437 PKIX_Int32 pathLen = 0; | |
2438 PKIX_Boolean isCA = PKIX_FALSE; | |
2439 enum { | |
2440 realBC, synthBC, absentBC | |
2441 } constraintSource = absentBC; | |
2442 | |
2443 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); | |
2444 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); | |
2445 | |
2446 /* if we don't have a cached copy from before, we create one */ | |
2447 if ((cert->certBasicConstraints == NULL) && | |
2448 (!cert->basicConstraintsAbsent)) { | |
2449 | |
2450 PKIX_OBJECT_LOCK(cert); | |
2451 | |
2452 if ((cert->certBasicConstraints == NULL) && | |
2453 (!cert->basicConstraintsAbsent)) { | |
2454 | |
2455 nssCert = cert->nssCert; | |
2456 | |
2457 PKIX_CERT_DEBUG( | |
2458 "\t\tCalling Cert_FindBasicConstraintExten\n"); | |
2459 rv = CERT_FindBasicConstraintExten | |
2460 (nssCert, &nssBasicConstraint); | |
2461 if (rv == SECSuccess) { | |
2462 constraintSource = realBC; | |
2463 } | |
2464 | |
2465 if (constraintSource == absentBC) { | |
2466 /* can we deduce it's a CA and create a | |
2467 synthetic constraint? | |
2468 */ | |
2469 CERTCertTrust trust; | |
2470 rv = CERT_GetCertTrust(nssCert, &trust); | |
2471 if (rv == SECSuccess) { | |
2472 int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_V
ALID_CA; | |
2473 if ((trust.sslFlags & anyWantedFlag) | |
2474 || (trust.emailFlags & anyWantedFlag) | |
2475 || (trust.objectSigningFlags & anyWantedFlag
)) { | |
2476 | |
2477 constraintSource = synthBC; | |
2478 } | |
2479 } | |
2480 } | |
2481 | |
2482 if (constraintSource == absentBC) { | |
2483 cert->basicConstraintsAbsent = PKIX_TRUE; | |
2484 *pBasicConstraints = NULL; | |
2485 goto cleanup; | |
2486 } | |
2487 } | |
2488 | |
2489 if (constraintSource == synthBC) { | |
2490 isCA = PKIX_TRUE; | |
2491 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
2492 } else { | |
2493 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; | |
2494 | |
2495 /* The pathLen has meaning only for CAs */ | |
2496 if (isCA) { | |
2497 if (CERT_UNLIMITED_PATH_CONSTRAINT == | |
2498 nssBasicConstraint.pathLenConstraint) { | |
2499 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
2500 } else { | |
2501 pathLen = nssBasicConstraint.pathLenConstraint; | |
2502 } | |
2503 } | |
2504 } | |
2505 | |
2506 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create | |
2507 (isCA, pathLen, &basic, plContext), | |
2508 PKIX_CERTBASICCONSTRAINTSCREATEFAILED); | |
2509 | |
2510 /* save a cached copy in case it is asked for again */ | |
2511 cert->certBasicConstraints = basic; | |
2512 } | |
2513 | |
2514 PKIX_INCREF(cert->certBasicConstraints); | |
2515 *pBasicConstraints = cert->certBasicConstraints; | |
2516 | |
2517 cleanup: | |
2518 PKIX_OBJECT_UNLOCK(lockedObject); | |
2519 PKIX_RETURN(CERT); | |
2520 } | |
2521 | |
2522 /* | |
2523 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation | |
2524 * (see comments in pkix_pl_pki.h) | |
2525 */ | |
2526 PKIX_Error * | |
2527 PKIX_PL_Cert_GetPolicyInformation( | |
2528 PKIX_PL_Cert *cert, | |
2529 PKIX_List **pPolicyInfo, | |
2530 void *plContext) | |
2531 { | |
2532 PKIX_List *policyList = NULL; | |
2533 | |
2534 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); | |
2535 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); | |
2536 | |
2537 /* if we don't have a cached copy from before, we create one */ | |
2538 if ((cert->certPolicyInfos == NULL) && | |
2539 (!cert->policyInfoAbsent)) { | |
2540 | |
2541 PKIX_OBJECT_LOCK(cert); | |
2542 | |
2543 if ((cert->certPolicyInfos == NULL) && | |
2544 (!cert->policyInfoAbsent)) { | |
2545 | |
2546 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo | |
2547 (cert->nssCert, &policyList, plContext), | |
2548 PKIX_CERTDECODEPOLICYINFOFAILED); | |
2549 | |
2550 if (!policyList) { | |
2551 cert->policyInfoAbsent = PKIX_TRUE; | |
2552 *pPolicyInfo = NULL; | |
2553 goto cleanup; | |
2554 } | |
2555 } | |
2556 | |
2557 PKIX_OBJECT_UNLOCK(cert); | |
2558 | |
2559 /* save a cached copy in case it is asked for again */ | |
2560 cert->certPolicyInfos = policyList; | |
2561 policyList = NULL; | |
2562 } | |
2563 | |
2564 PKIX_INCREF(cert->certPolicyInfos); | |
2565 *pPolicyInfo = cert->certPolicyInfos; | |
2566 | |
2567 cleanup: | |
2568 PKIX_OBJECT_UNLOCK(lockedObject); | |
2569 | |
2570 PKIX_DECREF(policyList); | |
2571 PKIX_RETURN(CERT); | |
2572 } | |
2573 | |
2574 /* | |
2575 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) | |
2576 */ | |
2577 PKIX_Error * | |
2578 PKIX_PL_Cert_GetPolicyMappings( | |
2579 PKIX_PL_Cert *cert, | |
2580 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ | |
2581 void *plContext) | |
2582 { | |
2583 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ | |
2584 | |
2585 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); | |
2586 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); | |
2587 | |
2588 /* if we don't have a cached copy from before, we create one */ | |
2589 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { | |
2590 | |
2591 PKIX_OBJECT_LOCK(cert); | |
2592 | |
2593 if (!(cert->certPolicyMappings) && | |
2594 !(cert->policyMappingsAbsent)) { | |
2595 | |
2596 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping | |
2597 (cert->nssCert, &policyMappings, plContext), | |
2598 PKIX_CERTDECODEPOLICYMAPPINGFAILED); | |
2599 | |
2600 if (!policyMappings) { | |
2601 cert->policyMappingsAbsent = PKIX_TRUE; | |
2602 *pPolicyMappings = NULL; | |
2603 goto cleanup; | |
2604 } | |
2605 } | |
2606 | |
2607 PKIX_OBJECT_UNLOCK(cert); | |
2608 | |
2609 /* save a cached copy in case it is asked for again */ | |
2610 cert->certPolicyMappings = policyMappings; | |
2611 policyMappings = NULL; | |
2612 } | |
2613 | |
2614 PKIX_INCREF(cert->certPolicyMappings); | |
2615 *pPolicyMappings = cert->certPolicyMappings; | |
2616 | |
2617 cleanup: | |
2618 PKIX_OBJECT_UNLOCK(lockedObject); | |
2619 | |
2620 PKIX_DECREF(policyMappings); | |
2621 PKIX_RETURN(CERT); | |
2622 } | |
2623 | |
2624 /* | |
2625 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy | |
2626 * (see comments in pkix_pl_pki.h) | |
2627 */ | |
2628 PKIX_Error * | |
2629 PKIX_PL_Cert_GetRequireExplicitPolicy( | |
2630 PKIX_PL_Cert *cert, | |
2631 PKIX_Int32 *pSkipCerts, | |
2632 void *plContext) | |
2633 { | |
2634 PKIX_Int32 explicitPolicySkipCerts = 0; | |
2635 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
2636 | |
2637 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); | |
2638 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2639 | |
2640 if (!(cert->policyConstraintsProcessed)) { | |
2641 PKIX_OBJECT_LOCK(cert); | |
2642 | |
2643 if (!(cert->policyConstraintsProcessed)) { | |
2644 | |
2645 /* | |
2646 * If we can't process it now, we probably will be | |
2647 * unable to process it later. Set the default value. | |
2648 */ | |
2649 cert->policyConstraintsProcessed = PKIX_TRUE; | |
2650 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
2651 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
2652 | |
2653 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
2654 (cert->nssCert, | |
2655 &explicitPolicySkipCerts, | |
2656 &inhibitMappingSkipCerts, | |
2657 plContext), | |
2658 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
2659 | |
2660 cert->policyConstraintsExplicitPolicySkipCerts = | |
2661 explicitPolicySkipCerts; | |
2662 cert->policyConstraintsInhibitMappingSkipCerts = | |
2663 inhibitMappingSkipCerts; | |
2664 } | |
2665 | |
2666 PKIX_OBJECT_UNLOCK(cert); | |
2667 } | |
2668 | |
2669 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; | |
2670 | |
2671 cleanup: | |
2672 PKIX_OBJECT_UNLOCK(lockedObject); | |
2673 PKIX_RETURN(CERT); | |
2674 } | |
2675 | |
2676 /* | |
2677 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited | |
2678 * (see comments in pkix_pl_pki.h) | |
2679 */ | |
2680 PKIX_Error * | |
2681 PKIX_PL_Cert_GetPolicyMappingInhibited( | |
2682 PKIX_PL_Cert *cert, | |
2683 PKIX_Int32 *pSkipCerts, | |
2684 void *plContext) | |
2685 { | |
2686 PKIX_Int32 explicitPolicySkipCerts = 0; | |
2687 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
2688 | |
2689 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); | |
2690 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2691 | |
2692 if (!(cert->policyConstraintsProcessed)) { | |
2693 PKIX_OBJECT_LOCK(cert); | |
2694 | |
2695 if (!(cert->policyConstraintsProcessed)) { | |
2696 | |
2697 /* | |
2698 * If we can't process it now, we probably will be | |
2699 * unable to process it later. Set the default value. | |
2700 */ | |
2701 cert->policyConstraintsProcessed = PKIX_TRUE; | |
2702 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
2703 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
2704 | |
2705 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
2706 (cert->nssCert, | |
2707 &explicitPolicySkipCerts, | |
2708 &inhibitMappingSkipCerts, | |
2709 plContext), | |
2710 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
2711 | |
2712 cert->policyConstraintsExplicitPolicySkipCerts = | |
2713 explicitPolicySkipCerts; | |
2714 cert->policyConstraintsInhibitMappingSkipCerts = | |
2715 inhibitMappingSkipCerts; | |
2716 } | |
2717 | |
2718 PKIX_OBJECT_UNLOCK(cert); | |
2719 } | |
2720 | |
2721 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; | |
2722 | |
2723 cleanup: | |
2724 PKIX_OBJECT_UNLOCK(lockedObject); | |
2725 PKIX_RETURN(CERT); | |
2726 } | |
2727 | |
2728 /* | |
2729 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) | |
2730 */ | |
2731 PKIX_Error * | |
2732 PKIX_PL_Cert_GetInhibitAnyPolicy( | |
2733 PKIX_PL_Cert *cert, | |
2734 PKIX_Int32 *pSkipCerts, | |
2735 void *plContext) | |
2736 { | |
2737 PKIX_Int32 skipCerts = 0; | |
2738 | |
2739 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); | |
2740 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2741 | |
2742 if (!(cert->inhibitAnyPolicyProcessed)) { | |
2743 | |
2744 PKIX_OBJECT_LOCK(cert); | |
2745 | |
2746 if (!(cert->inhibitAnyPolicyProcessed)) { | |
2747 | |
2748 /* | |
2749 * If we can't process it now, we probably will be | |
2750 * unable to process it later. Set the default value. | |
2751 */ | |
2752 cert->inhibitAnyPolicyProcessed = PKIX_TRUE; | |
2753 cert->inhibitAnySkipCerts = -1; | |
2754 | |
2755 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy | |
2756 (cert->nssCert, &skipCerts, plContext), | |
2757 PKIX_CERTDECODEINHIBITANYPOLICYFAILED); | |
2758 | |
2759 cert->inhibitAnySkipCerts = skipCerts; | |
2760 } | |
2761 | |
2762 PKIX_OBJECT_UNLOCK(cert); | |
2763 } | |
2764 | |
2765 cleanup: | |
2766 PKIX_OBJECT_UNLOCK(lockedObject); | |
2767 *pSkipCerts = cert->inhibitAnySkipCerts; | |
2768 PKIX_RETURN(CERT); | |
2769 } | |
2770 | |
2771 /* | |
2772 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical | |
2773 * (see comments in pkix_pl_pki.h) | |
2774 */ | |
2775 PKIX_Error * | |
2776 PKIX_PL_Cert_AreCertPoliciesCritical( | |
2777 PKIX_PL_Cert *cert, | |
2778 PKIX_Boolean *pCritical, | |
2779 void *plContext) | |
2780 { | |
2781 PKIX_Boolean criticality = PKIX_FALSE; | |
2782 | |
2783 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); | |
2784 PKIX_NULLCHECK_TWO(cert, pCritical); | |
2785 | |
2786 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( | |
2787 cert, | |
2788 SEC_OID_X509_CERTIFICATE_POLICIES, | |
2789 &criticality, | |
2790 plContext), | |
2791 PKIX_CERTISEXTENSIONCRITICALFAILED); | |
2792 | |
2793 *pCritical = criticality; | |
2794 | |
2795 cleanup: | |
2796 PKIX_RETURN(CERT); | |
2797 } | |
2798 | |
2799 /* | |
2800 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) | |
2801 */ | |
2802 PKIX_Error * | |
2803 PKIX_PL_Cert_VerifySignature( | |
2804 PKIX_PL_Cert *cert, | |
2805 PKIX_PL_PublicKey *pubKey, | |
2806 void *plContext) | |
2807 { | |
2808 CERTCertificate *nssCert = NULL; | |
2809 SECKEYPublicKey *nssPubKey = NULL; | |
2810 CERTSignedData *tbsCert = NULL; | |
2811 PKIX_PL_Cert *cachedCert = NULL; | |
2812 PKIX_Error *verifySig = NULL; | |
2813 PKIX_Error *cachedSig = NULL; | |
2814 SECStatus status; | |
2815 PKIX_Boolean certEqual = PKIX_FALSE; | |
2816 PKIX_Boolean certInHash = PKIX_FALSE; | |
2817 void* wincx = NULL; | |
2818 | |
2819 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); | |
2820 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); | |
2821 | |
2822 verifySig = PKIX_PL_HashTable_Lookup | |
2823 (cachedCertSigTable, | |
2824 (PKIX_PL_Object *) pubKey, | |
2825 (PKIX_PL_Object **) &cachedCert, | |
2826 plContext); | |
2827 | |
2828 if (cachedCert != NULL && verifySig == NULL) { | |
2829 /* Cached Signature Table lookup succeed */ | |
2830 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, | |
2831 PKIX_OBJECTEQUALSFAILED); | |
2832 if (certEqual == PKIX_TRUE) { | |
2833 goto cleanup; | |
2834 } | |
2835 /* Different PubKey may hash to same value, skip add */ | |
2836 certInHash = PKIX_TRUE; | |
2837 } | |
2838 | |
2839 nssCert = cert->nssCert; | |
2840 tbsCert = &nssCert->signatureWrap; | |
2841 | |
2842 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); | |
2843 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); | |
2844 if (!nssPubKey){ | |
2845 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); | |
2846 } | |
2847 | |
2848 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); | |
2849 | |
2850 PKIX_CHECK(pkix_pl_NssContext_GetWincx | |
2851 ((PKIX_PL_NssContext *)plContext, &wincx), | |
2852 PKIX_NSSCONTEXTGETWINCXFAILED); | |
2853 | |
2854 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); | |
2855 | |
2856 if (status != SECSuccess) { | |
2857 if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABL
ED) { | |
2858 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
2859 } | |
2860 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); | |
2861 } | |
2862 | |
2863 if (certInHash == PKIX_FALSE) { | |
2864 cachedSig = PKIX_PL_HashTable_Add | |
2865 (cachedCertSigTable, | |
2866 (PKIX_PL_Object *) pubKey, | |
2867 (PKIX_PL_Object *) cert, | |
2868 plContext); | |
2869 | |
2870 if (cachedSig != NULL) { | |
2871 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed
\n"); | |
2872 } | |
2873 } | |
2874 | |
2875 cleanup: | |
2876 if (nssPubKey){ | |
2877 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); | |
2878 SECKEY_DestroyPublicKey(nssPubKey); | |
2879 } | |
2880 | |
2881 PKIX_DECREF(cachedCert); | |
2882 PKIX_DECREF(verifySig); | |
2883 PKIX_DECREF(cachedSig); | |
2884 | |
2885 PKIX_RETURN(CERT); | |
2886 } | |
2887 | |
2888 /* | |
2889 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) | |
2890 */ | |
2891 PKIX_Error * | |
2892 PKIX_PL_Cert_CheckValidity( | |
2893 PKIX_PL_Cert *cert, | |
2894 PKIX_PL_Date *date, | |
2895 void *plContext) | |
2896 { | |
2897 SECCertTimeValidity val; | |
2898 PRTime timeToCheck; | |
2899 PKIX_Boolean allowOverride; | |
2900 SECCertificateUsage requiredUsages; | |
2901 | |
2902 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); | |
2903 PKIX_NULLCHECK_ONE(cert); | |
2904 | |
2905 /* if the caller supplies a date, we use it; else, use current time */ | |
2906 if (date != NULL){ | |
2907 PKIX_CHECK(pkix_pl_Date_GetPRTime | |
2908 (date, &timeToCheck, plContext), | |
2909 PKIX_DATEGETPRTIMEFAILED); | |
2910 } else { | |
2911 timeToCheck = PR_Now(); | |
2912 } | |
2913 | |
2914 requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
2915 allowOverride = | |
2916 (PRBool)((requiredUsages & certificateUsageSSLServer) || | |
2917 (requiredUsages & certificateUsageSSLServerWithStepUp)); | |
2918 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride
); | |
2919 if (val != secCertTimeValid){ | |
2920 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); | |
2921 } | |
2922 | |
2923 cleanup: | |
2924 PKIX_RETURN(CERT); | |
2925 } | |
2926 | |
2927 /* | |
2928 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) | |
2929 */ | |
2930 PKIX_Error * | |
2931 PKIX_PL_Cert_GetValidityNotAfter( | |
2932 PKIX_PL_Cert *cert, | |
2933 PKIX_PL_Date **pDate, | |
2934 void *plContext) | |
2935 { | |
2936 PRTime prtime; | |
2937 SECStatus rv = SECFailure; | |
2938 | |
2939 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); | |
2940 PKIX_NULLCHECK_TWO(cert, pDate); | |
2941 | |
2942 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); | |
2943 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); | |
2944 if (rv != SECSuccess){ | |
2945 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); | |
2946 } | |
2947 | |
2948 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime | |
2949 (prtime, pDate, plContext), | |
2950 PKIX_DATECREATEFROMPRTIMEFAILED); | |
2951 | |
2952 cleanup: | |
2953 PKIX_RETURN(CERT); | |
2954 } | |
2955 | |
2956 /* | |
2957 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) | |
2958 */ | |
2959 PKIX_Error * | |
2960 PKIX_PL_Cert_VerifyCertAndKeyType( | |
2961 PKIX_PL_Cert *cert, | |
2962 PKIX_Boolean isChainCert, | |
2963 void *plContext) | |
2964 { | |
2965 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; | |
2966 SECCertificateUsage certificateUsage; | |
2967 SECCertUsage certUsage = 0; | |
2968 unsigned int requiredKeyUsage; | |
2969 unsigned int requiredCertType; | |
2970 unsigned int certType; | |
2971 SECStatus rv = SECSuccess; | |
2972 | |
2973 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); | |
2974 PKIX_NULLCHECK_TWO(cert, plContext); | |
2975 | |
2976 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
2977 | |
2978 /* ensure we obtained a single usage bit only */ | |
2979 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
2980 | |
2981 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
2982 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
2983 | |
2984 /* check key usage and netscape cert type */ | |
2985 cert_GetCertType(cert->nssCert); | |
2986 certType = cert->nssCert->nsCertType; | |
2987 if (isChainCert || | |
2988 (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { | |
2989 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, | |
2990 &requiredKeyUsage, | |
2991 &requiredCertType); | |
2992 if (rv == SECFailure) { | |
2993 PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); | |
2994 } | |
2995 } else { | |
2996 /* use this key usage and cert type for certUsageAnyCA and | |
2997 * certUsageVerifyCA. */ | |
2998 requiredKeyUsage = KU_KEY_CERT_SIGN; | |
2999 requiredCertType = NS_CERT_TYPE_CA; | |
3000 } | |
3001 if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { | |
3002 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
3003 } | |
3004 if (!(certType & requiredCertType)) { | |
3005 PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); | |
3006 } | |
3007 cleanup: | |
3008 PKIX_DECREF(basicConstraints); | |
3009 PKIX_RETURN(CERT); | |
3010 } | |
3011 | |
3012 /* | |
3013 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) | |
3014 */ | |
3015 PKIX_Error * | |
3016 PKIX_PL_Cert_VerifyKeyUsage( | |
3017 PKIX_PL_Cert *cert, | |
3018 PKIX_UInt32 keyUsage, | |
3019 void *plContext) | |
3020 { | |
3021 CERTCertificate *nssCert = NULL; | |
3022 PKIX_UInt32 nssKeyUsage = 0; | |
3023 SECStatus status; | |
3024 | |
3025 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); | |
3026 PKIX_NULLCHECK_TWO(cert, cert->nssCert); | |
3027 | |
3028 nssCert = cert->nssCert; | |
3029 | |
3030 /* if cert doesn't have keyUsage extension, all keyUsages are valid */ | |
3031 if (!nssCert->keyUsagePresent){ | |
3032 goto cleanup; | |
3033 } | |
3034 | |
3035 if (keyUsage & PKIX_DIGITAL_SIGNATURE){ | |
3036 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; | |
3037 } | |
3038 | |
3039 if (keyUsage & PKIX_NON_REPUDIATION){ | |
3040 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; | |
3041 } | |
3042 | |
3043 if (keyUsage & PKIX_KEY_ENCIPHERMENT){ | |
3044 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; | |
3045 } | |
3046 | |
3047 if (keyUsage & PKIX_DATA_ENCIPHERMENT){ | |
3048 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; | |
3049 } | |
3050 | |
3051 if (keyUsage & PKIX_KEY_AGREEMENT){ | |
3052 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; | |
3053 } | |
3054 | |
3055 if (keyUsage & PKIX_KEY_CERT_SIGN){ | |
3056 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; | |
3057 } | |
3058 | |
3059 if (keyUsage & PKIX_CRL_SIGN){ | |
3060 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; | |
3061 } | |
3062 | |
3063 if (keyUsage & PKIX_ENCIPHER_ONLY){ | |
3064 nssKeyUsage = nssKeyUsage | 0x01; | |
3065 } | |
3066 | |
3067 if (keyUsage & PKIX_DECIPHER_ONLY){ | |
3068 /* XXX we should support this once it is fixed in NSS */ | |
3069 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); | |
3070 } | |
3071 | |
3072 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); | |
3073 if (status != SECSuccess) { | |
3074 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
3075 } | |
3076 | |
3077 cleanup: | |
3078 PKIX_RETURN(CERT); | |
3079 } | |
3080 | |
3081 /* | |
3082 * FUNCTION: PKIX_PL_Cert_GetNameConstraints | |
3083 * (see comments in pkix_pl_pki.h) | |
3084 */ | |
3085 PKIX_Error * | |
3086 PKIX_PL_Cert_GetNameConstraints( | |
3087 PKIX_PL_Cert *cert, | |
3088 PKIX_PL_CertNameConstraints **pNameConstraints, | |
3089 void *plContext) | |
3090 { | |
3091 PKIX_PL_CertNameConstraints *nameConstraints = NULL; | |
3092 | |
3093 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); | |
3094 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); | |
3095 | |
3096 /* if we don't have a cached copy from before, we create one */ | |
3097 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { | |
3098 | |
3099 PKIX_OBJECT_LOCK(cert); | |
3100 | |
3101 if (cert->nameConstraints == NULL && | |
3102 !cert->nameConstraintsAbsent) { | |
3103 | |
3104 PKIX_CHECK(pkix_pl_CertNameConstraints_Create | |
3105 (cert->nssCert, &nameConstraints, plContext), | |
3106 PKIX_CERTNAMECONSTRAINTSCREATEFAILED); | |
3107 | |
3108 if (nameConstraints == NULL) { | |
3109 cert->nameConstraintsAbsent = PKIX_TRUE; | |
3110 } | |
3111 | |
3112 cert->nameConstraints = nameConstraints; | |
3113 } | |
3114 | |
3115 PKIX_OBJECT_UNLOCK(cert); | |
3116 | |
3117 } | |
3118 | |
3119 PKIX_INCREF(cert->nameConstraints); | |
3120 | |
3121 *pNameConstraints = cert->nameConstraints; | |
3122 | |
3123 cleanup: | |
3124 PKIX_OBJECT_UNLOCK(lockedObject); | |
3125 PKIX_RETURN(CERT); | |
3126 } | |
3127 | |
3128 /* | |
3129 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints | |
3130 * (see comments in pkix_pl_pki.h) | |
3131 */ | |
3132 PKIX_Error * | |
3133 PKIX_PL_Cert_CheckNameConstraints( | |
3134 PKIX_PL_Cert *cert, | |
3135 PKIX_PL_CertNameConstraints *nameConstraints, | |
3136 PKIX_Boolean treatCommonNameAsDNSName, | |
3137 void *plContext) | |
3138 { | |
3139 PKIX_Boolean checkPass = PKIX_TRUE; | |
3140 CERTGeneralName *nssSubjectNames = NULL; | |
3141 PLArenaPool *arena = NULL; | |
3142 | |
3143 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); | |
3144 PKIX_NULLCHECK_ONE(cert); | |
3145 | |
3146 if (nameConstraints != NULL) { | |
3147 | |
3148 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
3149 if (arena == NULL) { | |
3150 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3151 } | |
3152 | |
3153 /* This NSS call returns Subject Alt Names. If | |
3154 * treatCommonNameAsDNSName is true, it also returns the | |
3155 * Subject Common Name | |
3156 */ | |
3157 PKIX_CERT_DEBUG | |
3158 ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); | |
3159 nssSubjectNames = CERT_GetConstrainedCertificateNames | |
3160 (cert->nssCert, arena, treatCommonNameAsDNSName); | |
3161 | |
3162 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames | |
3163 (nssSubjectNames, | |
3164 nameConstraints, | |
3165 &checkPass, | |
3166 plContext), | |
3167 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); | |
3168 | |
3169 if (checkPass != PKIX_TRUE) { | |
3170 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); | |
3171 } | |
3172 } | |
3173 | |
3174 cleanup: | |
3175 if (arena){ | |
3176 PORT_FreeArena(arena, PR_FALSE); | |
3177 } | |
3178 | |
3179 PKIX_RETURN(CERT); | |
3180 } | |
3181 | |
3182 /* | |
3183 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints | |
3184 * (see comments in pkix_pl_pki.h) | |
3185 */ | |
3186 PKIX_Error * | |
3187 PKIX_PL_Cert_MergeNameConstraints( | |
3188 PKIX_PL_CertNameConstraints *firstNC, | |
3189 PKIX_PL_CertNameConstraints *secondNC, | |
3190 PKIX_PL_CertNameConstraints **pResultNC, | |
3191 void *plContext) | |
3192 { | |
3193 PKIX_PL_CertNameConstraints *mergedNC = NULL; | |
3194 | |
3195 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); | |
3196 PKIX_NULLCHECK_TWO(firstNC, pResultNC); | |
3197 | |
3198 if (secondNC == NULL) { | |
3199 | |
3200 PKIX_INCREF(firstNC); | |
3201 *pResultNC = firstNC; | |
3202 | |
3203 goto cleanup; | |
3204 } | |
3205 | |
3206 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge | |
3207 (firstNC, secondNC, &mergedNC, plContext), | |
3208 PKIX_CERTNAMECONSTRAINTSMERGEFAILED); | |
3209 | |
3210 *pResultNC = mergedNC; | |
3211 | |
3212 cleanup: | |
3213 PKIX_RETURN(CERT); | |
3214 } | |
3215 | |
3216 /* | |
3217 * Find out the state of the NSS trust bits for the requested usage. | |
3218 * Returns SECFailure if the cert is explicitly distrusted. | |
3219 * Returns SECSuccess if the cert can be used to form a chain (normal case), | |
3220 * or it is explicitly trusted. The trusted bool is set to true if it is | |
3221 * explicitly trusted. | |
3222 */ | |
3223 static SECStatus | |
3224 pkix_pl_Cert_GetTrusted(void *plContext, | |
3225 PKIX_PL_Cert *cert, | |
3226 PKIX_Boolean *trusted, | |
3227 PKIX_Boolean isCA) | |
3228 { | |
3229 SECStatus rv; | |
3230 CERTCertificate *nssCert = NULL; | |
3231 SECCertUsage certUsage = 0; | |
3232 SECCertificateUsage certificateUsage; | |
3233 SECTrustType trustType; | |
3234 unsigned int trustFlags; | |
3235 unsigned int requiredFlags; | |
3236 CERTCertTrust trust; | |
3237 | |
3238 *trusted = PKIX_FALSE; | |
3239 | |
3240 /* no key usage information */ | |
3241 if (plContext == NULL) { | |
3242 return SECSuccess; | |
3243 } | |
3244 | |
3245 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
3246 | |
3247 /* ensure we obtained a single usage bit only */ | |
3248 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
3249 | |
3250 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
3251 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
3252 | |
3253 nssCert = cert->nssCert; | |
3254 | |
3255 if (!isCA) { | |
3256 PRBool prTrusted; | |
3257 unsigned int failedFlags; | |
3258 rv = cert_CheckLeafTrust(nssCert, certUsage, | |
3259 &failedFlags, &prTrusted); | |
3260 *trusted = (PKIX_Boolean) prTrusted; | |
3261 return rv; | |
3262 } | |
3263 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, | |
3264 &trustType); | |
3265 if (rv != SECSuccess) { | |
3266 return SECSuccess; | |
3267 } | |
3268 | |
3269 rv = CERT_GetCertTrust(nssCert, &trust); | |
3270 if (rv != SECSuccess) { | |
3271 return SECSuccess; | |
3272 } | |
3273 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); | |
3274 /* normally trustTypeNone usages accept any of the given trust bits | |
3275 * being on as acceptable. If any are distrusted (and none are trusted), | |
3276 * then we will also distrust the cert */ | |
3277 if ((trustFlags == 0) && (trustType == trustTypeNone)) { | |
3278 trustFlags = trust.sslFlags | trust.emailFlags | | |
3279 trust.objectSigningFlags; | |
3280 } | |
3281 if ((trustFlags & requiredFlags) == requiredFlags) { | |
3282 *trusted = PKIX_TRUE; | |
3283 return SECSuccess; | |
3284 } | |
3285 if ((trustFlags & CERTDB_TERMINAL_RECORD) && | |
3286 ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { | |
3287 return SECFailure; | |
3288 } | |
3289 return SECSuccess; | |
3290 } | |
3291 | |
3292 /* | |
3293 * FUNCTION: PKIX_PL_Cert_IsCertTrusted | |
3294 * (see comments in pkix_pl_pki.h) | |
3295 */ | |
3296 PKIX_Error * | |
3297 PKIX_PL_Cert_IsCertTrusted( | |
3298 PKIX_PL_Cert *cert, | |
3299 PKIX_PL_TrustAnchorMode trustAnchorMode, | |
3300 PKIX_Boolean *pTrusted, | |
3301 void *plContext) | |
3302 { | |
3303 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; | |
3304 PKIX_Boolean trusted = PKIX_FALSE; | |
3305 SECStatus rv = SECFailure; | |
3306 | |
3307 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); | |
3308 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
3309 | |
3310 /* Call GetTrusted first to see if we are going to distrust the | |
3311 * certificate */ | |
3312 rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); | |
3313 if (rv != SECSuccess) { | |
3314 /* Failure means the cert is explicitly distrusted, | |
3315 * let the next level know not to use it. */ | |
3316 *pTrusted = PKIX_FALSE; | |
3317 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
3318 } | |
3319 | |
3320 if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || | |
3321 (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && | |
3322 cert->isUserTrustAnchor)) { | |
3323 /* Use the trust anchor's |trusted| value */ | |
3324 *pTrusted = cert->isUserTrustAnchor; | |
3325 goto cleanup; | |
3326 } | |
3327 | |
3328 /* no key usage information or store is not trusted */ | |
3329 if (plContext == NULL || cert->store == NULL) { | |
3330 *pTrusted = PKIX_FALSE; | |
3331 goto cleanup; | |
3332 } | |
3333 | |
3334 PKIX_CHECK(PKIX_CertStore_GetTrustCallback | |
3335 (cert->store, &trustCallback, plContext), | |
3336 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); | |
3337 | |
3338 PKIX_CHECK_ONLY_FATAL(trustCallback | |
3339 (cert->store, cert, &trusted, plContext), | |
3340 PKIX_CHECKTRUSTCALLBACKFAILED); | |
3341 | |
3342 /* allow trust store to override if we can trust the trust | |
3343 * bits */ | |
3344 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { | |
3345 *pTrusted = PKIX_FALSE; | |
3346 goto cleanup; | |
3347 } | |
3348 | |
3349 *pTrusted = trusted; | |
3350 | |
3351 cleanup: | |
3352 PKIX_RETURN(CERT); | |
3353 } | |
3354 | |
3355 /* | |
3356 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted | |
3357 * (see comments in pkix_pl_pki.h) | |
3358 */ | |
3359 PKIX_Error * | |
3360 PKIX_PL_Cert_IsLeafCertTrusted( | |
3361 PKIX_PL_Cert *cert, | |
3362 PKIX_Boolean *pTrusted, | |
3363 void *plContext) | |
3364 { | |
3365 SECStatus rv; | |
3366 | |
3367 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); | |
3368 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
3369 | |
3370 *pTrusted = PKIX_FALSE; | |
3371 | |
3372 rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); | |
3373 if (rv != SECSuccess) { | |
3374 /* Failure means the cert is explicitly distrusted, | |
3375 * let the next level know not to use it. */ | |
3376 *pTrusted = PKIX_FALSE; | |
3377 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
3378 } | |
3379 | |
3380 cleanup: | |
3381 PKIX_RETURN(CERT); | |
3382 } | |
3383 | |
3384 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ | |
3385 PKIX_Error* | |
3386 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, | |
3387 void *plContext) | |
3388 { | |
3389 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); | |
3390 PKIX_NULLCHECK_ONE(cert); | |
3391 | |
3392 cert->isUserTrustAnchor = PKIX_TRUE; | |
3393 | |
3394 PKIX_RETURN(CERT); | |
3395 } | |
3396 | |
3397 /* | |
3398 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) | |
3399 */ | |
3400 PKIX_Error * | |
3401 PKIX_PL_Cert_GetCacheFlag( | |
3402 PKIX_PL_Cert *cert, | |
3403 PKIX_Boolean *pCacheFlag, | |
3404 void *plContext) | |
3405 { | |
3406 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); | |
3407 PKIX_NULLCHECK_TWO(cert, pCacheFlag); | |
3408 | |
3409 *pCacheFlag = cert->cacheFlag; | |
3410 | |
3411 PKIX_RETURN(CERT); | |
3412 } | |
3413 | |
3414 /* | |
3415 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) | |
3416 */ | |
3417 PKIX_Error * | |
3418 PKIX_PL_Cert_SetCacheFlag( | |
3419 PKIX_PL_Cert *cert, | |
3420 PKIX_Boolean cacheFlag, | |
3421 void *plContext) | |
3422 { | |
3423 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); | |
3424 PKIX_NULLCHECK_ONE(cert); | |
3425 | |
3426 cert->cacheFlag = cacheFlag; | |
3427 | |
3428 PKIX_RETURN(CERT); | |
3429 } | |
3430 | |
3431 /* | |
3432 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) | |
3433 */ | |
3434 PKIX_Error * | |
3435 PKIX_PL_Cert_GetTrustCertStore( | |
3436 PKIX_PL_Cert *cert, | |
3437 PKIX_CertStore **pTrustCertStore, | |
3438 void *plContext) | |
3439 { | |
3440 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); | |
3441 PKIX_NULLCHECK_TWO(cert, pTrustCertStore); | |
3442 | |
3443 PKIX_INCREF(cert->store); | |
3444 *pTrustCertStore = cert->store; | |
3445 | |
3446 cleanup: | |
3447 PKIX_RETURN(CERT); | |
3448 } | |
3449 | |
3450 /* | |
3451 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) | |
3452 */ | |
3453 PKIX_Error * | |
3454 PKIX_PL_Cert_SetTrustCertStore( | |
3455 PKIX_PL_Cert *cert, | |
3456 PKIX_CertStore *trustCertStore, | |
3457 void *plContext) | |
3458 { | |
3459 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); | |
3460 PKIX_NULLCHECK_TWO(cert, trustCertStore); | |
3461 | |
3462 PKIX_INCREF(trustCertStore); | |
3463 cert->store = trustCertStore; | |
3464 | |
3465 cleanup: | |
3466 PKIX_RETURN(CERT); | |
3467 } | |
3468 | |
3469 /* | |
3470 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess | |
3471 * (see comments in pkix_pl_pki.h) | |
3472 */ | |
3473 PKIX_Error * | |
3474 PKIX_PL_Cert_GetAuthorityInfoAccess( | |
3475 PKIX_PL_Cert *cert, | |
3476 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ | |
3477 void *plContext) | |
3478 { | |
3479 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ | |
3480 SECItem *encodedAIA = NULL; | |
3481 CERTAuthInfoAccess **aia = NULL; | |
3482 PLArenaPool *arena = NULL; | |
3483 SECStatus rv; | |
3484 | |
3485 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); | |
3486 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); | |
3487 | |
3488 /* if we don't have a cached copy from before, we create one */ | |
3489 if (cert->authorityInfoAccess == NULL) { | |
3490 | |
3491 PKIX_OBJECT_LOCK(cert); | |
3492 | |
3493 if (cert->authorityInfoAccess == NULL) { | |
3494 | |
3495 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, | |
3496 (NULL, NULL, 0)); | |
3497 | |
3498 if (encodedAIA == NULL) { | |
3499 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3500 } | |
3501 | |
3502 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, | |
3503 (cert->nssCert, | |
3504 SEC_OID_X509_AUTH_INFO_ACCESS, | |
3505 encodedAIA)); | |
3506 | |
3507 if (rv == SECFailure) { | |
3508 goto cleanup; | |
3509 } | |
3510 | |
3511 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, | |
3512 (DER_DEFAULT_CHUNKSIZE)); | |
3513 | |
3514 if (arena == NULL) { | |
3515 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3516 } | |
3517 | |
3518 PKIX_PL_NSSCALLRV | |
3519 (CERT, aia, CERT_DecodeAuthInfoAccessExtension, | |
3520 (arena, encodedAIA)); | |
3521 | |
3522 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
3523 (aia, &aiaList, plContext), | |
3524 PKIX_INFOACCESSCREATELISTFAILED); | |
3525 | |
3526 cert->authorityInfoAccess = aiaList; | |
3527 } | |
3528 | |
3529 PKIX_OBJECT_UNLOCK(cert); | |
3530 } | |
3531 | |
3532 PKIX_INCREF(cert->authorityInfoAccess); | |
3533 | |
3534 *pAiaList = cert->authorityInfoAccess; | |
3535 | |
3536 cleanup: | |
3537 PKIX_OBJECT_UNLOCK(lockedObject); | |
3538 if (arena != NULL) { | |
3539 PORT_FreeArena(arena, PR_FALSE); | |
3540 } | |
3541 | |
3542 if (encodedAIA != NULL) { | |
3543 SECITEM_FreeItem(encodedAIA, PR_TRUE); | |
3544 } | |
3545 | |
3546 PKIX_RETURN(CERT); | |
3547 } | |
3548 | |
3549 /* XXX Following defines belongs to NSS */ | |
3550 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, | |
3551 0x07, 0x01, 0x0b}; | |
3552 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } | |
3553 | |
3554 /* | |
3555 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess | |
3556 * (see comments in pkix_pl_pki.h) | |
3557 */ | |
3558 PKIX_Error * | |
3559 PKIX_PL_Cert_GetSubjectInfoAccess( | |
3560 PKIX_PL_Cert *cert, | |
3561 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ | |
3562 void *plContext) | |
3563 { | |
3564 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ | |
3565 SECItem siaOID = OI(siaOIDString); | |
3566 SECItem *encodedSubjInfoAccess = NULL; | |
3567 CERTAuthInfoAccess **subjInfoAccess = NULL; | |
3568 PLArenaPool *arena = NULL; | |
3569 SECStatus rv; | |
3570 | |
3571 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); | |
3572 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); | |
3573 | |
3574 /* XXX | |
3575 * Codes to deal with SubjectInfoAccess OID should be moved to | |
3576 * NSS soon. I implemented them here so we don't touch NSS | |
3577 * source tree, from JP's suggestion. | |
3578 */ | |
3579 | |
3580 /* if we don't have a cached copy from before, we create one */ | |
3581 if (cert->subjectInfoAccess == NULL) { | |
3582 | |
3583 PKIX_OBJECT_LOCK(cert); | |
3584 | |
3585 if (cert->subjectInfoAccess == NULL) { | |
3586 | |
3587 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); | |
3588 if (encodedSubjInfoAccess == NULL) { | |
3589 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3590 } | |
3591 | |
3592 PKIX_CERT_DEBUG | |
3593 ("\t\tCalling CERT_FindCertExtensionByOID).\n"); | |
3594 rv = CERT_FindCertExtensionByOID | |
3595 (cert->nssCert, &siaOID, encodedSubjInfoAccess); | |
3596 | |
3597 if (rv == SECFailure) { | |
3598 goto cleanup; | |
3599 } | |
3600 | |
3601 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
3602 if (arena == NULL) { | |
3603 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3604 } | |
3605 | |
3606 /* XXX | |
3607 * Decode Subject Information Access - | |
3608 * since its type is the same as Authority Information | |
3609 * Access, reuse the call. NSS- change name to avoid | |
3610 * confusion. | |
3611 */ | |
3612 PKIX_CERT_DEBUG | |
3613 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); | |
3614 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension | |
3615 (arena, encodedSubjInfoAccess); | |
3616 | |
3617 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
3618 (subjInfoAccess, &siaList, plContext), | |
3619 PKIX_INFOACCESSCREATELISTFAILED); | |
3620 | |
3621 cert->subjectInfoAccess = siaList; | |
3622 | |
3623 } | |
3624 | |
3625 PKIX_OBJECT_UNLOCK(cert); | |
3626 } | |
3627 | |
3628 PKIX_INCREF(cert->subjectInfoAccess); | |
3629 *pSiaList = cert->subjectInfoAccess; | |
3630 | |
3631 cleanup: | |
3632 PKIX_OBJECT_UNLOCK(lockedObject); | |
3633 if (arena != NULL) { | |
3634 PORT_FreeArena(arena, PR_FALSE); | |
3635 } | |
3636 | |
3637 if (encodedSubjInfoAccess != NULL) { | |
3638 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); | |
3639 } | |
3640 PKIX_RETURN(CERT); | |
3641 } | |
3642 | |
3643 /* | |
3644 * FUNCTION: PKIX_PL_Cert_GetCrlDp | |
3645 * (see comments in pkix_pl_pki.h) | |
3646 */ | |
3647 PKIX_Error * | |
3648 PKIX_PL_Cert_GetCrlDp( | |
3649 PKIX_PL_Cert *cert, | |
3650 PKIX_List **pDpList, | |
3651 void *plContext) | |
3652 { | |
3653 PKIX_UInt32 dpIndex = 0; | |
3654 pkix_pl_CrlDp *dp = NULL; | |
3655 CERTCrlDistributionPoints *dpoints = NULL; | |
3656 | |
3657 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); | |
3658 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); | |
3659 | |
3660 /* if we don't have a cached copy from before, we create one */ | |
3661 if (cert->crldpList == NULL) { | |
3662 PKIX_OBJECT_LOCK(cert); | |
3663 if (cert->crldpList != NULL) { | |
3664 goto cleanup; | |
3665 } | |
3666 PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), | |
3667 PKIX_LISTCREATEFAILED); | |
3668 dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); | |
3669 if (!dpoints || !dpoints->distPoints) { | |
3670 goto cleanup; | |
3671 } | |
3672 for (;dpoints->distPoints[dpIndex];dpIndex++) { | |
3673 PKIX_CHECK( | |
3674 pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], | |
3675 &cert->nssCert->issuer, | |
3676 &dp, plContext), | |
3677 PKIX_CRLDPCREATEFAILED); | |
3678 /* Create crldp list in reverse order in attempt to get | |
3679 * to the whole crl first. */ | |
3680 PKIX_CHECK( | |
3681 PKIX_List_InsertItem(cert->crldpList, 0, | |
3682 (PKIX_PL_Object*)dp, | |
3683 plContext), | |
3684 PKIX_LISTAPPENDITEMFAILED); | |
3685 PKIX_DECREF(dp); | |
3686 } | |
3687 } | |
3688 cleanup: | |
3689 PKIX_INCREF(cert->crldpList); | |
3690 *pDpList = cert->crldpList; | |
3691 | |
3692 PKIX_OBJECT_UNLOCK(lockedObject); | |
3693 PKIX_DECREF(dp); | |
3694 | |
3695 PKIX_RETURN(CERT); | |
3696 } | |
3697 | |
3698 /* | |
3699 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate | |
3700 * (see comments in pkix_pl_pki.h) | |
3701 */ | |
3702 PKIX_Error * | |
3703 PKIX_PL_Cert_GetCERTCertificate( | |
3704 PKIX_PL_Cert *cert, | |
3705 CERTCertificate **pnssCert, | |
3706 void *plContext) | |
3707 { | |
3708 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); | |
3709 PKIX_NULLCHECK_TWO(cert, pnssCert); | |
3710 | |
3711 *pnssCert = CERT_DupCertificate(cert->nssCert); | |
3712 | |
3713 PKIX_RETURN(CERT); | |
3714 } | |
OLD | NEW |