Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 /* | |
5 * 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, &encodedCertInhibitAny); | |
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_Boolean copyDER; | |
1519 PKIX_PL_Cert *cert = NULL; | |
1520 CERTCertDBHandle *handle; | |
1521 | |
1522 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); | |
1523 PKIX_NULLCHECK_TWO(pCert, byteArray); | |
1524 | |
1525 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer | |
1526 (byteArray, &derBytes, plContext), | |
1527 PKIX_BYTEARRAYGETPOINTERFAILED); | |
1528 | |
1529 PKIX_CHECK(PKIX_PL_ByteArray_GetLength | |
1530 (byteArray, &derLength, plContext), | |
1531 PKIX_BYTEARRAYGETLENGTHFAILED); | |
1532 | |
1533 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); | |
1534 if (derCertItem == NULL){ | |
1535 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
1536 } | |
1537 | |
1538 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); | |
1539 | |
1540 /* | |
1541 * setting copyDER to true forces NSS to make its own copy of the DER, | |
1542 * allowing us to free our copy without worrying about whether NSS | |
1543 * is still using it | |
1544 */ | |
1545 copyDER = PKIX_TRUE; | |
1546 handle = CERT_GetDefaultCertDB(); | |
1547 nssCert = CERT_NewTempCertificate(handle, derCertItem, | |
1548 /* nickname */ NULL, | |
1549 /* isPerm */ PR_FALSE, | |
1550 /* copyDer */ PR_TRUE); | |
1551 if (!nssCert){ | |
1552 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); | |
1553 } | |
1554 | |
1555 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
1556 (nssCert, &cert, plContext), | |
1557 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1558 | |
1559 *pCert = cert; | |
1560 | |
1561 cleanup: | |
1562 if (derCertItem){ | |
1563 SECITEM_FreeItem(derCertItem, PKIX_TRUE); | |
1564 } | |
1565 | |
1566 if (nssCert && PKIX_ERROR_RECEIVED){ | |
1567 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
1568 CERT_DestroyCertificate(nssCert); | |
1569 nssCert = NULL; | |
1570 } | |
1571 | |
1572 PKIX_FREE(derBytes); | |
1573 PKIX_RETURN(CERT); | |
1574 } | |
1575 | |
1576 | |
1577 /* | |
1578 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate | |
1579 * (see comments in pkix_pl_pki.h) | |
1580 */ | |
1581 PKIX_Error * | |
1582 PKIX_PL_Cert_CreateFromCERTCertificate( | |
1583 const CERTCertificate *nssCert, | |
1584 PKIX_PL_Cert **pCert, | |
1585 void *plContext) | |
1586 { | |
1587 void *buf = NULL; | |
1588 PKIX_UInt32 len; | |
1589 PKIX_PL_ByteArray *byteArray = NULL; | |
1590 | |
1591 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); | |
1592 PKIX_NULLCHECK_TWO(pCert, nssCert); | |
1593 | |
1594 buf = (void*)nssCert->derCert.data; | |
1595 len = nssCert->derCert.len; | |
1596 | |
1597 PKIX_CHECK( | |
1598 PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), | |
1599 PKIX_BYTEARRAYCREATEFAILED); | |
1600 | |
1601 PKIX_CHECK( | |
1602 PKIX_PL_Cert_Create(byteArray, pCert, plContext), | |
1603 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1604 | |
1605 #ifdef PKIX_UNDEF | |
1606 /* will be tested and used as a patch for bug 391612 */ | |
1607 nssCert = CERT_DupCertificate(nssInCert); | |
1608 | |
1609 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
1610 (nssCert, &cert, plContext), | |
1611 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
1612 #endif /* PKIX_UNDEF */ | |
1613 | |
1614 cleanup: | |
1615 | |
1616 #ifdef PKIX_UNDEF | |
1617 if (nssCert && PKIX_ERROR_RECEIVED){ | |
1618 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
1619 CERT_DestroyCertificate(nssCert); | |
1620 nssCert = NULL; | |
1621 } | |
1622 #endif /* PKIX_UNDEF */ | |
1623 | |
1624 PKIX_DECREF(byteArray); | |
1625 PKIX_RETURN(CERT); | |
1626 } | |
1627 | |
1628 | |
1629 /* | |
1630 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) | |
1631 */ | |
1632 PKIX_Error * | |
1633 PKIX_PL_Cert_GetVersion( | |
1634 PKIX_PL_Cert *cert, | |
1635 PKIX_UInt32 *pVersion, | |
1636 void *plContext) | |
1637 { | |
1638 CERTCertificate *nssCert = NULL; | |
1639 PKIX_UInt32 myVersion = 0; /* v1 */ | |
1640 | |
1641 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); | |
1642 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); | |
1643 | |
1644 nssCert = cert->nssCert; | |
1645 if (nssCert->version.len != 0) { | |
1646 myVersion = *(nssCert->version.data); | |
1647 } | |
1648 | |
1649 if (myVersion > 2){ | |
1650 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); | |
1651 } | |
1652 | |
1653 *pVersion = myVersion; | |
1654 | |
1655 cleanup: | |
1656 PKIX_RETURN(CERT); | |
1657 } | |
1658 | |
1659 /* | |
1660 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) | |
1661 */ | |
1662 PKIX_Error * | |
1663 PKIX_PL_Cert_GetSerialNumber( | |
1664 PKIX_PL_Cert *cert, | |
1665 PKIX_PL_BigInt **pSerialNumber, | |
1666 void *plContext) | |
1667 { | |
1668 CERTCertificate *nssCert = NULL; | |
1669 SECItem serialNumItem; | |
1670 PKIX_PL_BigInt *serialNumber = NULL; | |
1671 char *bytes = NULL; | |
1672 PKIX_UInt32 length; | |
1673 | |
1674 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); | |
1675 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); | |
1676 | |
1677 if (cert->serialNumber == NULL){ | |
1678 | |
1679 PKIX_OBJECT_LOCK(cert); | |
1680 | |
1681 if (cert->serialNumber == NULL){ | |
1682 | |
1683 nssCert = cert->nssCert; | |
1684 serialNumItem = nssCert->serialNumber; | |
1685 | |
1686 length = serialNumItem.len; | |
1687 bytes = (char *)serialNumItem.data; | |
1688 | |
1689 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes | |
1690 (bytes, length, &serialNumber, plContext), | |
1691 PKIX_BIGINTCREATEWITHBYTESFAILED); | |
1692 | |
1693 /* save a cached copy in case it is asked for again */ | |
1694 cert->serialNumber = serialNumber; | |
1695 } | |
1696 | |
1697 PKIX_OBJECT_UNLOCK(cert); | |
1698 } | |
1699 | |
1700 PKIX_INCREF(cert->serialNumber); | |
1701 *pSerialNumber = cert->serialNumber; | |
1702 | |
1703 cleanup: | |
1704 PKIX_OBJECT_UNLOCK(lockedObject); | |
1705 PKIX_RETURN(CERT); | |
1706 } | |
1707 | |
1708 /* | |
1709 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) | |
1710 */ | |
1711 PKIX_Error * | |
1712 PKIX_PL_Cert_GetSubject( | |
1713 PKIX_PL_Cert *cert, | |
1714 PKIX_PL_X500Name **pCertSubject, | |
1715 void *plContext) | |
1716 { | |
1717 PKIX_PL_X500Name *pkixSubject = NULL; | |
1718 CERTName *subjName = NULL; | |
1719 SECItem *derSubjName = NULL; | |
1720 | |
1721 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); | |
1722 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); | |
1723 | |
1724 /* if we don't have a cached copy from before, we create one */ | |
1725 if (cert->subject == NULL){ | |
1726 | |
1727 PKIX_OBJECT_LOCK(cert); | |
1728 | |
1729 if (cert->subject == NULL){ | |
1730 | |
1731 subjName = &cert->nssCert->subject; | |
1732 derSubjName = &cert->nssCert->derSubject; | |
1733 | |
1734 /* if there is no subject name */ | |
1735 if (derSubjName->data == NULL) { | |
1736 | |
1737 pkixSubject = NULL; | |
1738 | |
1739 } else { | |
1740 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
1741 (derSubjName, subjName, &pkixSubject, | |
1742 plContext), | |
1743 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
1744 | |
1745 } | |
1746 /* save a cached copy in case it is asked for again */ | |
1747 cert->subject = pkixSubject; | |
1748 } | |
1749 | |
1750 PKIX_OBJECT_UNLOCK(cert); | |
1751 } | |
1752 | |
1753 PKIX_INCREF(cert->subject); | |
1754 *pCertSubject = cert->subject; | |
1755 | |
1756 cleanup: | |
1757 PKIX_OBJECT_UNLOCK(lockedObject); | |
1758 PKIX_RETURN(CERT); | |
1759 } | |
1760 | |
1761 /* | |
1762 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) | |
1763 */ | |
1764 PKIX_Error * | |
1765 PKIX_PL_Cert_GetIssuer( | |
1766 PKIX_PL_Cert *cert, | |
1767 PKIX_PL_X500Name **pCertIssuer, | |
1768 void *plContext) | |
1769 { | |
1770 PKIX_PL_X500Name *pkixIssuer = NULL; | |
1771 SECItem *derIssuerName = NULL; | |
1772 CERTName *issuerName = NULL; | |
1773 | |
1774 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); | |
1775 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); | |
1776 | |
1777 /* if we don't have a cached copy from before, we create one */ | |
1778 if (cert->issuer == NULL){ | |
1779 | |
1780 PKIX_OBJECT_LOCK(cert); | |
1781 | |
1782 if (cert->issuer == NULL){ | |
1783 | |
1784 issuerName = &cert->nssCert->issuer; | |
1785 derIssuerName = &cert->nssCert->derIssuer; | |
1786 | |
1787 /* if there is no subject name */ | |
1788 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
1789 (derIssuerName, issuerName, | |
1790 &pkixIssuer, plContext), | |
1791 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
1792 | |
1793 /* save a cached copy in case it is asked for again */ | |
1794 cert->issuer = pkixIssuer; | |
1795 } | |
1796 | |
1797 PKIX_OBJECT_UNLOCK(cert); | |
1798 } | |
1799 | |
1800 PKIX_INCREF(cert->issuer); | |
1801 *pCertIssuer = cert->issuer; | |
1802 | |
1803 cleanup: | |
1804 PKIX_RETURN(CERT); | |
1805 } | |
1806 | |
1807 /* | |
1808 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) | |
1809 */ | |
1810 PKIX_Error * | |
1811 PKIX_PL_Cert_GetSubjectAltNames( | |
1812 PKIX_PL_Cert *cert, | |
1813 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ | |
1814 void *plContext) | |
1815 { | |
1816 PKIX_PL_GeneralName *pkixAltName = NULL; | |
1817 PKIX_List *altNamesList = NULL; | |
1818 | |
1819 CERTGeneralName *nssOriginalAltName = NULL; | |
1820 CERTGeneralName *nssTempAltName = NULL; | |
1821 | |
1822 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); | |
1823 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); | |
1824 | |
1825 /* if we don't have a cached copy from before, we create one */ | |
1826 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ | |
1827 | |
1828 PKIX_OBJECT_LOCK(cert); | |
1829 | |
1830 if ((cert->subjAltNames == NULL) && | |
1831 (!cert->subjAltNamesAbsent)){ | |
1832 | |
1833 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
1834 (cert, | |
1835 PKIX_TRUE, | |
1836 &nssOriginalAltName, | |
1837 plContext), | |
1838 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
1839 | |
1840 if (nssOriginalAltName == NULL) { | |
1841 cert->subjAltNamesAbsent = PKIX_TRUE; | |
1842 pSubjectAltNames = NULL; | |
1843 goto cleanup; | |
1844 } | |
1845 | |
1846 nssTempAltName = nssOriginalAltName; | |
1847 | |
1848 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), | |
1849 PKIX_LISTCREATEFAILED); | |
1850 | |
1851 do { | |
1852 PKIX_CHECK(pkix_pl_GeneralName_Create | |
1853 (nssTempAltName, &pkixAltName, plContext), | |
1854 PKIX_GENERALNAMECREATEFAILED); | |
1855 | |
1856 PKIX_CHECK(PKIX_List_AppendItem | |
1857 (altNamesList, | |
1858 (PKIX_PL_Object *)pkixAltName, | |
1859 plContext), | |
1860 PKIX_LISTAPPENDITEMFAILED); | |
1861 | |
1862 PKIX_DECREF(pkixAltName); | |
1863 | |
1864 PKIX_CERT_DEBUG | |
1865 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
1866 nssTempAltName = CERT_GetNextGeneralName | |
1867 (nssTempAltName); | |
1868 | |
1869 } while (nssTempAltName != nssOriginalAltName); | |
1870 | |
1871 /* save a cached copy in case it is asked for again */ | |
1872 cert->subjAltNames = altNamesList; | |
1873 PKIX_CHECK(PKIX_List_SetImmutable | |
1874 (cert->subjAltNames, plContext), | |
1875 PKIX_LISTSETIMMUTABLEFAILED); | |
1876 | |
1877 } | |
1878 | |
1879 PKIX_OBJECT_UNLOCK(cert); | |
1880 } | |
1881 | |
1882 PKIX_INCREF(cert->subjAltNames); | |
1883 | |
1884 *pSubjectAltNames = cert->subjAltNames; | |
1885 | |
1886 cleanup: | |
1887 PKIX_DECREF(pkixAltName); | |
1888 if (PKIX_ERROR_RECEIVED){ | |
1889 PKIX_DECREF(altNamesList); | |
1890 } | |
1891 PKIX_RETURN(CERT); | |
1892 } | |
1893 | |
1894 /* | |
1895 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) | |
1896 */ | |
1897 PKIX_Error * | |
1898 PKIX_PL_Cert_GetAllSubjectNames( | |
1899 PKIX_PL_Cert *cert, | |
1900 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ | |
1901 void *plContext) | |
1902 { | |
1903 CERTGeneralName *nssOriginalSubjectName = NULL; | |
1904 CERTGeneralName *nssTempSubjectName = NULL; | |
1905 PKIX_List *allSubjectNames = NULL; | |
1906 PKIX_PL_GeneralName *pkixSubjectName = NULL; | |
1907 PLArenaPool *arena = NULL; | |
1908 | |
1909 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); | |
1910 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); | |
1911 | |
1912 | |
1913 if (cert->nssCert->subjectName == NULL){ | |
1914 /* if there is no subject DN, just get altnames */ | |
1915 | |
1916 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
1917 (cert, | |
1918 PKIX_FALSE, /* hasLock */ | |
1919 &nssOriginalSubjectName, | |
1920 plContext), | |
1921 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
1922 | |
1923 } else { /* get subject DN and altnames */ | |
1924 | |
1925 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1926 if (arena == NULL) { | |
1927 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
1928 } | |
1929 | |
1930 /* This NSS call returns both Subject and Subject Alt Names */ | |
1931 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); | |
1932 nssOriginalSubjectName = | |
1933 CERT_GetCertificateNames(cert->nssCert, arena); | |
1934 } | |
1935 | |
1936 if (nssOriginalSubjectName == NULL) { | |
1937 pAllSubjectNames = NULL; | |
1938 goto cleanup; | |
1939 } | |
1940 | |
1941 nssTempSubjectName = nssOriginalSubjectName; | |
1942 | |
1943 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), | |
1944 PKIX_LISTCREATEFAILED); | |
1945 | |
1946 do { | |
1947 PKIX_CHECK(pkix_pl_GeneralName_Create | |
1948 (nssTempSubjectName, &pkixSubjectName, plContext), | |
1949 PKIX_GENERALNAMECREATEFAILED); | |
1950 | |
1951 PKIX_CHECK(PKIX_List_AppendItem | |
1952 (allSubjectNames, | |
1953 (PKIX_PL_Object *)pkixSubjectName, | |
1954 plContext), | |
1955 PKIX_LISTAPPENDITEMFAILED); | |
1956 | |
1957 PKIX_DECREF(pkixSubjectName); | |
1958 | |
1959 PKIX_CERT_DEBUG | |
1960 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
1961 nssTempSubjectName = CERT_GetNextGeneralName | |
1962 (nssTempSubjectName); | |
1963 } while (nssTempSubjectName != nssOriginalSubjectName); | |
1964 | |
1965 *pAllSubjectNames = allSubjectNames; | |
1966 | |
1967 cleanup: | |
1968 if (PKIX_ERROR_RECEIVED){ | |
1969 PKIX_DECREF(allSubjectNames); | |
1970 } | |
1971 | |
1972 if (arena){ | |
1973 PORT_FreeArena(arena, PR_FALSE); | |
1974 } | |
1975 PKIX_DECREF(pkixSubjectName); | |
1976 PKIX_RETURN(CERT); | |
1977 } | |
1978 | |
1979 /* | |
1980 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId | |
1981 * (see comments in pkix_pl_pki.h) | |
1982 */ | |
1983 PKIX_Error * | |
1984 PKIX_PL_Cert_GetSubjectPublicKeyAlgId( | |
1985 PKIX_PL_Cert *cert, | |
1986 PKIX_PL_OID **pSubjKeyAlgId, | |
1987 void *plContext) | |
1988 { | |
1989 PKIX_PL_OID *pubKeyAlgId = NULL; | |
1990 | |
1991 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); | |
1992 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); | |
1993 | |
1994 /* if we don't have a cached copy from before, we create one */ | |
1995 if (cert->publicKeyAlgId == NULL){ | |
1996 PKIX_OBJECT_LOCK(cert); | |
1997 if (cert->publicKeyAlgId == NULL){ | |
1998 CERTCertificate *nssCert = cert->nssCert; | |
1999 SECAlgorithmID *algorithm; | |
2000 SECItem *algBytes; | |
2001 | |
2002 algorithm = &nssCert->subjectPublicKeyInfo.algorithm; | |
2003 algBytes = &algorithm->algorithm; | |
2004 if (!algBytes->data || !algBytes->len) { | |
2005 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); | |
2006 } | |
2007 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
2008 (algBytes, &pubKeyAlgId, plContext), | |
2009 PKIX_OIDCREATEFAILED); | |
2010 | |
2011 /* save a cached copy in case it is asked for again */ | |
2012 cert->publicKeyAlgId = pubKeyAlgId; | |
2013 pubKeyAlgId = NULL; | |
2014 } | |
2015 PKIX_OBJECT_UNLOCK(cert); | |
2016 } | |
2017 | |
2018 PKIX_INCREF(cert->publicKeyAlgId); | |
2019 *pSubjKeyAlgId = cert->publicKeyAlgId; | |
2020 | |
2021 cleanup: | |
2022 PKIX_DECREF(pubKeyAlgId); | |
2023 PKIX_RETURN(CERT); | |
2024 } | |
2025 | |
2026 /* | |
2027 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) | |
2028 */ | |
2029 PKIX_Error * | |
2030 PKIX_PL_Cert_GetSubjectPublicKey( | |
2031 PKIX_PL_Cert *cert, | |
2032 PKIX_PL_PublicKey **pPublicKey, | |
2033 void *plContext) | |
2034 { | |
2035 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
2036 SECStatus rv; | |
2037 | |
2038 CERTSubjectPublicKeyInfo *from = NULL; | |
2039 CERTSubjectPublicKeyInfo *to = NULL; | |
2040 SECItem *fromItem = NULL; | |
2041 SECItem *toItem = NULL; | |
2042 | |
2043 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); | |
2044 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); | |
2045 | |
2046 /* if we don't have a cached copy from before, we create one */ | |
2047 if (cert->publicKey == NULL){ | |
2048 | |
2049 PKIX_OBJECT_LOCK(cert); | |
2050 | |
2051 if (cert->publicKey == NULL){ | |
2052 | |
2053 /* create a PKIX_PL_PublicKey object */ | |
2054 PKIX_CHECK(PKIX_PL_Object_Alloc | |
2055 (PKIX_PUBLICKEY_TYPE, | |
2056 sizeof (PKIX_PL_PublicKey), | |
2057 (PKIX_PL_Object **)&pkixPubKey, | |
2058 plContext), | |
2059 PKIX_COULDNOTCREATEOBJECT); | |
2060 | |
2061 /* initialize fields */ | |
2062 pkixPubKey->nssSPKI = NULL; | |
2063 | |
2064 /* populate the SPKI field */ | |
2065 PKIX_CHECK(PKIX_PL_Malloc | |
2066 (sizeof (CERTSubjectPublicKeyInfo), | |
2067 (void **)&pkixPubKey->nssSPKI, | |
2068 plContext), | |
2069 PKIX_MALLOCFAILED); | |
2070 | |
2071 to = pkixPubKey->nssSPKI; | |
2072 from = &cert->nssCert->subjectPublicKeyInfo; | |
2073 | |
2074 PKIX_NULLCHECK_TWO(to, from); | |
2075 | |
2076 PKIX_CERT_DEBUG | |
2077 ("\t\tCalling SECOID_CopyAlgorithmID).\n"); | |
2078 rv = SECOID_CopyAlgorithmID | |
2079 (NULL, &to->algorithm, &from->algorithm); | |
2080 if (rv != SECSuccess) { | |
2081 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); | |
2082 } | |
2083 | |
2084 /* | |
2085 * NSS stores the length of subjectPublicKey in bits. | |
2086 * Therefore, we use that length converted to bytes | |
2087 * using ((length+7)>>3) before calling PORT_Memcpy | |
2088 * in order to avoid "read from uninitialized memory" | |
2089 * errors. | |
2090 */ | |
2091 | |
2092 toItem = &to->subjectPublicKey; | |
2093 fromItem = &from->subjectPublicKey; | |
2094 | |
2095 PKIX_NULLCHECK_TWO(toItem, fromItem); | |
2096 | |
2097 toItem->type = fromItem->type; | |
2098 | |
2099 toItem->data = | |
2100 (unsigned char*) PORT_ZAlloc(fromItem->len); | |
2101 if (!toItem->data){ | |
2102 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2103 } | |
2104 | |
2105 (void) PORT_Memcpy(toItem->data, | |
2106 fromItem->data, | |
2107 (fromItem->len + 7)>>3); | |
2108 toItem->len = fromItem->len; | |
2109 | |
2110 /* save a cached copy in case it is asked for again */ | |
2111 cert->publicKey = pkixPubKey; | |
2112 } | |
2113 | |
2114 PKIX_OBJECT_UNLOCK(cert); | |
2115 } | |
2116 | |
2117 PKIX_INCREF(cert->publicKey); | |
2118 *pPublicKey = cert->publicKey; | |
2119 | |
2120 cleanup: | |
2121 | |
2122 if (PKIX_ERROR_RECEIVED && pkixPubKey){ | |
2123 PKIX_DECREF(pkixPubKey); | |
2124 cert->publicKey = NULL; | |
2125 } | |
2126 PKIX_RETURN(CERT); | |
2127 } | |
2128 | |
2129 /* | |
2130 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs | |
2131 * (see comments in pkix_pl_pki.h) | |
2132 */ | |
2133 PKIX_Error * | |
2134 PKIX_PL_Cert_GetCriticalExtensionOIDs( | |
2135 PKIX_PL_Cert *cert, | |
2136 PKIX_List **pList, /* list of PKIX_PL_OID */ | |
2137 void *plContext) | |
2138 { | |
2139 PKIX_List *oidsList = NULL; | |
2140 CERTCertExtension **extensions = NULL; | |
2141 CERTCertificate *nssCert = NULL; | |
2142 | |
2143 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); | |
2144 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); | |
2145 | |
2146 /* if we don't have a cached copy from before, we create one */ | |
2147 if (cert->critExtOids == NULL) { | |
2148 | |
2149 PKIX_OBJECT_LOCK(cert); | |
2150 | |
2151 if (cert->critExtOids == NULL) { | |
2152 | |
2153 nssCert = cert->nssCert; | |
2154 | |
2155 /* | |
2156 * ASN.1 for Extension | |
2157 * | |
2158 * Extension ::= SEQUENCE { | |
2159 * extnID OBJECT IDENTIFIER, | |
2160 * critical BOOLEAN DEFAULT FALSE, | |
2161 * extnValue OCTET STRING } | |
2162 * | |
2163 */ | |
2164 | |
2165 extensions = nssCert->extensions; | |
2166 | |
2167 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs | |
2168 (extensions, &oidsList, plContext), | |
2169 PKIX_GETCRITICALEXTENSIONOIDSFAILED); | |
2170 | |
2171 /* save a cached copy in case it is asked for again */ | |
2172 cert->critExtOids = oidsList; | |
2173 } | |
2174 | |
2175 PKIX_OBJECT_UNLOCK(cert); | |
2176 } | |
2177 | |
2178 /* We should return a copy of the List since this list changes */ | |
2179 PKIX_DUPLICATE(cert->critExtOids, pList, plContext, | |
2180 PKIX_OBJECTDUPLICATELISTFAILED); | |
2181 | |
2182 cleanup: | |
2183 PKIX_OBJECT_UNLOCK(lockedObject); | |
2184 PKIX_RETURN(CERT); | |
2185 } | |
2186 | |
2187 /* | |
2188 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
2189 * (see comments in pkix_pl_pki.h) | |
2190 */ | |
2191 PKIX_Error * | |
2192 PKIX_PL_Cert_GetAuthorityKeyIdentifier( | |
2193 PKIX_PL_Cert *cert, | |
2194 PKIX_PL_ByteArray **pAuthKeyId, | |
2195 void *plContext) | |
2196 { | |
2197 PKIX_PL_ByteArray *authKeyId = NULL; | |
2198 CERTCertificate *nssCert = NULL; | |
2199 CERTAuthKeyID *authKeyIdExtension = NULL; | |
2200 PLArenaPool *arena = NULL; | |
2201 SECItem retItem; | |
2202 | |
2203 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); | |
2204 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); | |
2205 | |
2206 /* if we don't have a cached copy from before, we create one */ | |
2207 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
2208 | |
2209 PKIX_OBJECT_LOCK(cert); | |
2210 | |
2211 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
2212 | |
2213 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
2214 if (arena == NULL) { | |
2215 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2216 } | |
2217 | |
2218 nssCert = cert->nssCert; | |
2219 | |
2220 authKeyIdExtension = | |
2221 CERT_FindAuthKeyIDExten(arena, nssCert); | |
2222 if (authKeyIdExtension == NULL){ | |
2223 cert->authKeyIdAbsent = PKIX_TRUE; | |
2224 *pAuthKeyId = NULL; | |
2225 goto cleanup; | |
2226 } | |
2227 | |
2228 retItem = authKeyIdExtension->keyID; | |
2229 | |
2230 if (retItem.len == 0){ | |
2231 cert->authKeyIdAbsent = PKIX_TRUE; | |
2232 *pAuthKeyId = NULL; | |
2233 goto cleanup; | |
2234 } | |
2235 | |
2236 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
2237 (retItem.data, | |
2238 retItem.len, | |
2239 &authKeyId, | |
2240 plContext), | |
2241 PKIX_BYTEARRAYCREATEFAILED); | |
2242 | |
2243 /* save a cached copy in case it is asked for again */ | |
2244 cert->authKeyId = authKeyId; | |
2245 } | |
2246 | |
2247 PKIX_OBJECT_UNLOCK(cert); | |
2248 } | |
2249 | |
2250 PKIX_INCREF(cert->authKeyId); | |
2251 *pAuthKeyId = cert->authKeyId; | |
2252 | |
2253 cleanup: | |
2254 PKIX_OBJECT_UNLOCK(lockedObject); | |
2255 if (arena){ | |
2256 PORT_FreeArena(arena, PR_FALSE); | |
2257 } | |
2258 PKIX_RETURN(CERT); | |
2259 } | |
2260 | |
2261 /* | |
2262 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier | |
2263 * (see comments in pkix_pl_pki.h) | |
2264 */ | |
2265 PKIX_Error * | |
2266 PKIX_PL_Cert_GetSubjectKeyIdentifier( | |
2267 PKIX_PL_Cert *cert, | |
2268 PKIX_PL_ByteArray **pSubjKeyId, | |
2269 void *plContext) | |
2270 { | |
2271 PKIX_PL_ByteArray *subjKeyId = NULL; | |
2272 CERTCertificate *nssCert = NULL; | |
2273 SECItem *retItem = NULL; | |
2274 SECStatus status; | |
2275 | |
2276 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); | |
2277 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); | |
2278 | |
2279 /* if we don't have a cached copy from before, we create one */ | |
2280 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
2281 | |
2282 PKIX_OBJECT_LOCK(cert); | |
2283 | |
2284 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
2285 | |
2286 retItem = SECITEM_AllocItem(NULL, NULL, 0); | |
2287 if (retItem == NULL){ | |
2288 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
2289 } | |
2290 | |
2291 nssCert = cert->nssCert; | |
2292 | |
2293 status = CERT_FindSubjectKeyIDExtension | |
2294 (nssCert, retItem); | |
2295 if (status != SECSuccess) { | |
2296 cert->subjKeyIdAbsent = PKIX_TRUE; | |
2297 *pSubjKeyId = NULL; | |
2298 goto cleanup; | |
2299 } | |
2300 | |
2301 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
2302 (retItem->data, | |
2303 retItem->len, | |
2304 &subjKeyId, | |
2305 plContext), | |
2306 PKIX_BYTEARRAYCREATEFAILED); | |
2307 | |
2308 /* save a cached copy in case it is asked for again */ | |
2309 cert->subjKeyId = subjKeyId; | |
2310 } | |
2311 | |
2312 PKIX_OBJECT_UNLOCK(cert); | |
2313 } | |
2314 | |
2315 PKIX_INCREF(cert->subjKeyId); | |
2316 *pSubjKeyId = cert->subjKeyId; | |
2317 | |
2318 cleanup: | |
2319 PKIX_OBJECT_UNLOCK(lockedObject); | |
2320 if (retItem){ | |
2321 SECITEM_FreeItem(retItem, PKIX_TRUE); | |
2322 } | |
2323 PKIX_RETURN(CERT); | |
2324 } | |
2325 | |
2326 /* | |
2327 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) | |
2328 */ | |
2329 PKIX_Error * | |
2330 PKIX_PL_Cert_GetExtendedKeyUsage( | |
2331 PKIX_PL_Cert *cert, | |
2332 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ | |
2333 void *plContext) | |
2334 { | |
2335 CERTOidSequence *extKeyUsage = NULL; | |
2336 CERTCertificate *nssCert = NULL; | |
2337 PKIX_PL_OID *pkixOID = NULL; | |
2338 PKIX_List *oidsList = NULL; | |
2339 SECItem **oids = NULL; | |
2340 SECItem encodedExtKeyUsage; | |
2341 SECStatus rv; | |
2342 | |
2343 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); | |
2344 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); | |
2345 | |
2346 /* if we don't have a cached copy from before, we create one */ | |
2347 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ | |
2348 | |
2349 PKIX_OBJECT_LOCK(cert); | |
2350 | |
2351 if ((cert->extKeyUsages == NULL) && | |
2352 (!cert->extKeyUsagesAbsent)){ | |
2353 | |
2354 nssCert = cert->nssCert; | |
2355 | |
2356 rv = CERT_FindCertExtension | |
2357 (nssCert, SEC_OID_X509_EXT_KEY_USAGE, | |
2358 &encodedExtKeyUsage); | |
2359 if (rv != SECSuccess){ | |
2360 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
2361 *pKeyUsage = NULL; | |
2362 goto cleanup; | |
2363 } | |
2364 | |
2365 extKeyUsage = | |
2366 CERT_DecodeOidSequence(&encodedExtKeyUsage); | |
2367 if (extKeyUsage == NULL){ | |
2368 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); | |
2369 } | |
2370 | |
2371 PORT_Free(encodedExtKeyUsage.data); | |
2372 | |
2373 oids = extKeyUsage->oids; | |
2374 | |
2375 if (!oids){ | |
2376 /* no extended key usage extensions found */ | |
2377 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
2378 *pKeyUsage = NULL; | |
2379 goto cleanup; | |
2380 } | |
2381 | |
2382 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), | |
2383 PKIX_LISTCREATEFAILED); | |
2384 | |
2385 while (*oids){ | |
2386 SECItem *oid = *oids++; | |
2387 | |
2388 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
2389 (oid, &pkixOID, plContext), | |
2390 PKIX_OIDCREATEFAILED); | |
2391 | |
2392 PKIX_CHECK(PKIX_List_AppendItem | |
2393 (oidsList, | |
2394 (PKIX_PL_Object *)pkixOID, | |
2395 plContext), | |
2396 PKIX_LISTAPPENDITEMFAILED); | |
2397 PKIX_DECREF(pkixOID); | |
2398 } | |
2399 | |
2400 PKIX_CHECK(PKIX_List_SetImmutable | |
2401 (oidsList, plContext), | |
2402 PKIX_LISTSETIMMUTABLEFAILED); | |
2403 | |
2404 /* save a cached copy in case it is asked for again */ | |
2405 cert->extKeyUsages = oidsList; | |
2406 oidsList = NULL; | |
2407 } | |
2408 | |
2409 PKIX_OBJECT_UNLOCK(cert); | |
2410 } | |
2411 | |
2412 PKIX_INCREF(cert->extKeyUsages); | |
2413 *pKeyUsage = cert->extKeyUsages; | |
2414 | |
2415 cleanup: | |
2416 PKIX_OBJECT_UNLOCK(lockedObject); | |
2417 | |
2418 PKIX_DECREF(pkixOID); | |
2419 PKIX_DECREF(oidsList); | |
2420 CERT_DestroyOidSequence(extKeyUsage); | |
2421 | |
2422 PKIX_RETURN(CERT); | |
2423 } | |
2424 | |
2425 /* | |
2426 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints | |
2427 * (see comments in pkix_pl_pki.h) | |
2428 */ | |
2429 PKIX_Error * | |
2430 PKIX_PL_Cert_GetBasicConstraints( | |
2431 PKIX_PL_Cert *cert, | |
2432 PKIX_PL_CertBasicConstraints **pBasicConstraints, | |
2433 void *plContext) | |
2434 { | |
2435 CERTCertificate *nssCert = NULL; | |
2436 CERTBasicConstraints nssBasicConstraint; | |
2437 SECStatus rv; | |
2438 PKIX_PL_CertBasicConstraints *basic; | |
2439 PKIX_Int32 pathLen = 0; | |
2440 PKIX_Boolean isCA = PKIX_FALSE; | |
2441 enum { | |
2442 realBC, synthBC, absentBC | |
2443 } constraintSource = absentBC; | |
2444 | |
2445 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); | |
2446 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); | |
2447 | |
2448 /* if we don't have a cached copy from before, we create one */ | |
2449 if ((cert->certBasicConstraints == NULL) && | |
2450 (!cert->basicConstraintsAbsent)) { | |
2451 | |
2452 PKIX_OBJECT_LOCK(cert); | |
2453 | |
2454 if ((cert->certBasicConstraints == NULL) && | |
2455 (!cert->basicConstraintsAbsent)) { | |
2456 | |
2457 nssCert = cert->nssCert; | |
2458 | |
2459 PKIX_CERT_DEBUG( | |
2460 "\t\tCalling Cert_FindBasicConstraintExten\n"); | |
2461 rv = CERT_FindBasicConstraintExten | |
2462 (nssCert, &nssBasicConstraint); | |
2463 if (rv == SECSuccess) { | |
2464 constraintSource = realBC; | |
2465 } | |
2466 | |
2467 if (constraintSource == absentBC) { | |
2468 /* can we deduce it's a CA and create a | |
2469 synthetic constraint? | |
2470 */ | |
2471 CERTCertTrust trust; | |
2472 rv = CERT_GetCertTrust(nssCert, &trust); | |
2473 if (rv == SECSuccess) { | |
2474 int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA; | |
2475 if ((trust.sslFlags & anyWantedFlag) | |
2476 || (trust.emailFlags & anyWantedFlag) | |
2477 || (trust.objectSigningFlags & anyWantedFlag)) { | |
2478 | |
2479 constraintSource = synthBC; | |
2480 } | |
2481 } | |
2482 } | |
2483 | |
2484 if (constraintSource == absentBC) { | |
2485 cert->basicConstraintsAbsent = PKIX_TRUE; | |
2486 *pBasicConstraints = NULL; | |
2487 goto cleanup; | |
2488 } | |
2489 } | |
2490 | |
2491 if (constraintSource == synthBC) { | |
2492 isCA = PKIX_TRUE; | |
2493 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
2494 } else { | |
2495 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; | |
2496 | |
2497 /* The pathLen has meaning only for CAs */ | |
2498 if (isCA) { | |
2499 if (CERT_UNLIMITED_PATH_CONSTRAINT == | |
2500 nssBasicConstraint.pathLenConstraint) { | |
2501 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
2502 } else { | |
2503 pathLen = nssBasicConstraint.pathLenConstraint; | |
2504 } | |
2505 } | |
2506 } | |
2507 | |
2508 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create | |
2509 (isCA, pathLen, &basic, plContext), | |
2510 PKIX_CERTBASICCONSTRAINTSCREATEFAILED); | |
2511 | |
2512 /* save a cached copy in case it is asked for again */ | |
2513 cert->certBasicConstraints = basic; | |
2514 } | |
2515 | |
2516 PKIX_INCREF(cert->certBasicConstraints); | |
2517 *pBasicConstraints = cert->certBasicConstraints; | |
2518 | |
2519 cleanup: | |
2520 PKIX_OBJECT_UNLOCK(lockedObject); | |
2521 PKIX_RETURN(CERT); | |
2522 } | |
2523 | |
2524 /* | |
2525 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation | |
2526 * (see comments in pkix_pl_pki.h) | |
2527 */ | |
2528 PKIX_Error * | |
2529 PKIX_PL_Cert_GetPolicyInformation( | |
2530 PKIX_PL_Cert *cert, | |
2531 PKIX_List **pPolicyInfo, | |
2532 void *plContext) | |
2533 { | |
2534 PKIX_List *policyList = NULL; | |
2535 | |
2536 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); | |
2537 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); | |
2538 | |
2539 /* if we don't have a cached copy from before, we create one */ | |
2540 if ((cert->certPolicyInfos == NULL) && | |
2541 (!cert->policyInfoAbsent)) { | |
2542 | |
2543 PKIX_OBJECT_LOCK(cert); | |
2544 | |
2545 if ((cert->certPolicyInfos == NULL) && | |
2546 (!cert->policyInfoAbsent)) { | |
2547 | |
2548 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo | |
2549 (cert->nssCert, &policyList, plContext), | |
2550 PKIX_CERTDECODEPOLICYINFOFAILED); | |
2551 | |
2552 if (!policyList) { | |
2553 cert->policyInfoAbsent = PKIX_TRUE; | |
2554 *pPolicyInfo = NULL; | |
2555 goto cleanup; | |
2556 } | |
2557 } | |
2558 | |
2559 PKIX_OBJECT_UNLOCK(cert); | |
2560 | |
2561 /* save a cached copy in case it is asked for again */ | |
2562 cert->certPolicyInfos = policyList; | |
2563 policyList = NULL; | |
2564 } | |
2565 | |
2566 PKIX_INCREF(cert->certPolicyInfos); | |
2567 *pPolicyInfo = cert->certPolicyInfos; | |
2568 | |
2569 cleanup: | |
2570 PKIX_OBJECT_UNLOCK(lockedObject); | |
2571 | |
2572 PKIX_DECREF(policyList); | |
2573 PKIX_RETURN(CERT); | |
2574 } | |
2575 | |
2576 /* | |
2577 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) | |
2578 */ | |
2579 PKIX_Error * | |
2580 PKIX_PL_Cert_GetPolicyMappings( | |
2581 PKIX_PL_Cert *cert, | |
2582 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ | |
2583 void *plContext) | |
2584 { | |
2585 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ | |
2586 | |
2587 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); | |
2588 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); | |
2589 | |
2590 /* if we don't have a cached copy from before, we create one */ | |
2591 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { | |
2592 | |
2593 PKIX_OBJECT_LOCK(cert); | |
2594 | |
2595 if (!(cert->certPolicyMappings) && | |
2596 !(cert->policyMappingsAbsent)) { | |
2597 | |
2598 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping | |
2599 (cert->nssCert, &policyMappings, plContext), | |
2600 PKIX_CERTDECODEPOLICYMAPPINGFAILED); | |
2601 | |
2602 if (!policyMappings) { | |
2603 cert->policyMappingsAbsent = PKIX_TRUE; | |
2604 *pPolicyMappings = NULL; | |
2605 goto cleanup; | |
2606 } | |
2607 } | |
2608 | |
2609 PKIX_OBJECT_UNLOCK(cert); | |
2610 | |
2611 /* save a cached copy in case it is asked for again */ | |
2612 cert->certPolicyMappings = policyMappings; | |
2613 policyMappings = NULL; | |
2614 } | |
2615 | |
2616 PKIX_INCREF(cert->certPolicyMappings); | |
2617 *pPolicyMappings = cert->certPolicyMappings; | |
2618 | |
2619 cleanup: | |
2620 PKIX_OBJECT_UNLOCK(lockedObject); | |
2621 | |
2622 PKIX_DECREF(policyMappings); | |
2623 PKIX_RETURN(CERT); | |
2624 } | |
2625 | |
2626 /* | |
2627 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy | |
2628 * (see comments in pkix_pl_pki.h) | |
2629 */ | |
2630 PKIX_Error * | |
2631 PKIX_PL_Cert_GetRequireExplicitPolicy( | |
2632 PKIX_PL_Cert *cert, | |
2633 PKIX_Int32 *pSkipCerts, | |
2634 void *plContext) | |
2635 { | |
2636 PKIX_Int32 explicitPolicySkipCerts = 0; | |
2637 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
2638 | |
2639 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); | |
2640 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2641 | |
2642 if (!(cert->policyConstraintsProcessed)) { | |
2643 PKIX_OBJECT_LOCK(cert); | |
2644 | |
2645 if (!(cert->policyConstraintsProcessed)) { | |
2646 | |
2647 /* | |
2648 * If we can't process it now, we probably will be | |
2649 * unable to process it later. Set the default value. | |
2650 */ | |
2651 cert->policyConstraintsProcessed = PKIX_TRUE; | |
2652 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
2653 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
2654 | |
2655 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
2656 (cert->nssCert, | |
2657 &explicitPolicySkipCerts, | |
2658 &inhibitMappingSkipCerts, | |
2659 plContext), | |
2660 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
2661 | |
2662 cert->policyConstraintsExplicitPolicySkipCerts = | |
2663 explicitPolicySkipCerts; | |
2664 cert->policyConstraintsInhibitMappingSkipCerts = | |
2665 inhibitMappingSkipCerts; | |
2666 } | |
2667 | |
2668 PKIX_OBJECT_UNLOCK(cert); | |
2669 } | |
2670 | |
2671 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; | |
2672 | |
2673 cleanup: | |
2674 PKIX_OBJECT_UNLOCK(lockedObject); | |
2675 PKIX_RETURN(CERT); | |
2676 } | |
2677 | |
2678 /* | |
2679 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited | |
2680 * (see comments in pkix_pl_pki.h) | |
2681 */ | |
2682 PKIX_Error * | |
2683 PKIX_PL_Cert_GetPolicyMappingInhibited( | |
2684 PKIX_PL_Cert *cert, | |
2685 PKIX_Int32 *pSkipCerts, | |
2686 void *plContext) | |
2687 { | |
2688 PKIX_Int32 explicitPolicySkipCerts = 0; | |
2689 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
2690 | |
2691 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); | |
2692 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2693 | |
2694 if (!(cert->policyConstraintsProcessed)) { | |
2695 PKIX_OBJECT_LOCK(cert); | |
2696 | |
2697 if (!(cert->policyConstraintsProcessed)) { | |
2698 | |
2699 /* | |
2700 * If we can't process it now, we probably will be | |
2701 * unable to process it later. Set the default value. | |
2702 */ | |
2703 cert->policyConstraintsProcessed = PKIX_TRUE; | |
2704 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
2705 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
2706 | |
2707 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
2708 (cert->nssCert, | |
2709 &explicitPolicySkipCerts, | |
2710 &inhibitMappingSkipCerts, | |
2711 plContext), | |
2712 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
2713 | |
2714 cert->policyConstraintsExplicitPolicySkipCerts = | |
2715 explicitPolicySkipCerts; | |
2716 cert->policyConstraintsInhibitMappingSkipCerts = | |
2717 inhibitMappingSkipCerts; | |
2718 } | |
2719 | |
2720 PKIX_OBJECT_UNLOCK(cert); | |
2721 } | |
2722 | |
2723 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; | |
2724 | |
2725 cleanup: | |
2726 PKIX_OBJECT_UNLOCK(lockedObject); | |
2727 PKIX_RETURN(CERT); | |
2728 } | |
2729 | |
2730 /* | |
2731 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) | |
2732 */ | |
2733 PKIX_Error * | |
2734 PKIX_PL_Cert_GetInhibitAnyPolicy( | |
2735 PKIX_PL_Cert *cert, | |
2736 PKIX_Int32 *pSkipCerts, | |
2737 void *plContext) | |
2738 { | |
2739 PKIX_Int32 skipCerts = 0; | |
2740 | |
2741 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); | |
2742 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
2743 | |
2744 if (!(cert->inhibitAnyPolicyProcessed)) { | |
2745 | |
2746 PKIX_OBJECT_LOCK(cert); | |
2747 | |
2748 if (!(cert->inhibitAnyPolicyProcessed)) { | |
2749 | |
2750 /* | |
2751 * If we can't process it now, we probably will be | |
2752 * unable to process it later. Set the default value. | |
2753 */ | |
2754 cert->inhibitAnyPolicyProcessed = PKIX_TRUE; | |
2755 cert->inhibitAnySkipCerts = -1; | |
2756 | |
2757 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy | |
2758 (cert->nssCert, &skipCerts, plContext), | |
2759 PKIX_CERTDECODEINHIBITANYPOLICYFAILED); | |
2760 | |
2761 cert->inhibitAnySkipCerts = skipCerts; | |
2762 } | |
2763 | |
2764 PKIX_OBJECT_UNLOCK(cert); | |
2765 } | |
2766 | |
2767 cleanup: | |
2768 PKIX_OBJECT_UNLOCK(lockedObject); | |
2769 *pSkipCerts = cert->inhibitAnySkipCerts; | |
2770 PKIX_RETURN(CERT); | |
2771 } | |
2772 | |
2773 /* | |
2774 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical | |
2775 * (see comments in pkix_pl_pki.h) | |
2776 */ | |
2777 PKIX_Error * | |
2778 PKIX_PL_Cert_AreCertPoliciesCritical( | |
2779 PKIX_PL_Cert *cert, | |
2780 PKIX_Boolean *pCritical, | |
2781 void *plContext) | |
2782 { | |
2783 PKIX_Boolean criticality = PKIX_FALSE; | |
2784 | |
2785 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); | |
2786 PKIX_NULLCHECK_TWO(cert, pCritical); | |
2787 | |
2788 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( | |
2789 cert, | |
2790 SEC_OID_X509_CERTIFICATE_POLICIES, | |
2791 &criticality, | |
2792 plContext), | |
2793 PKIX_CERTISEXTENSIONCRITICALFAILED); | |
2794 | |
2795 *pCritical = criticality; | |
2796 | |
2797 cleanup: | |
2798 PKIX_RETURN(CERT); | |
2799 } | |
2800 | |
2801 /* | |
2802 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) | |
2803 */ | |
2804 PKIX_Error * | |
2805 PKIX_PL_Cert_VerifySignature( | |
2806 PKIX_PL_Cert *cert, | |
2807 PKIX_PL_PublicKey *pubKey, | |
2808 void *plContext) | |
2809 { | |
2810 CERTCertificate *nssCert = NULL; | |
2811 SECKEYPublicKey *nssPubKey = NULL; | |
2812 CERTSignedData *tbsCert = NULL; | |
2813 PKIX_PL_Cert *cachedCert = NULL; | |
2814 PKIX_Error *verifySig = NULL; | |
2815 PKIX_Error *cachedSig = NULL; | |
2816 SECStatus status; | |
2817 PKIX_Boolean certEqual = PKIX_FALSE; | |
2818 PKIX_Boolean certInHash = PKIX_FALSE; | |
2819 void* wincx = NULL; | |
2820 | |
2821 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); | |
2822 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); | |
2823 | |
2824 verifySig = PKIX_PL_HashTable_Lookup | |
2825 (cachedCertSigTable, | |
2826 (PKIX_PL_Object *) pubKey, | |
2827 (PKIX_PL_Object **) &cachedCert, | |
2828 plContext); | |
2829 | |
2830 if (cachedCert != NULL && verifySig == NULL) { | |
2831 /* Cached Signature Table lookup succeed */ | |
2832 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, | |
2833 PKIX_OBJECTEQUALSFAILED); | |
2834 if (certEqual == PKIX_TRUE) { | |
2835 goto cleanup; | |
2836 } | |
2837 /* Different PubKey may hash to same value, skip add */ | |
2838 certInHash = PKIX_TRUE; | |
2839 } | |
2840 | |
2841 nssCert = cert->nssCert; | |
2842 tbsCert = &nssCert->signatureWrap; | |
2843 | |
2844 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); | |
2845 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); | |
2846 if (!nssPubKey){ | |
2847 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); | |
2848 } | |
2849 | |
2850 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); | |
2851 | |
2852 PKIX_CHECK(pkix_pl_NssContext_GetWincx | |
2853 ((PKIX_PL_NssContext *)plContext, &wincx), | |
2854 PKIX_NSSCONTEXTGETWINCXFAILED); | |
2855 | |
2856 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); | |
2857 | |
2858 if (status != SECSuccess) { | |
2859 if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { | |
2860 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
2861 } | |
2862 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); | |
2863 } | |
2864 | |
2865 if (certInHash == PKIX_FALSE) { | |
2866 cachedSig = PKIX_PL_HashTable_Add | |
2867 (cachedCertSigTable, | |
2868 (PKIX_PL_Object *) pubKey, | |
2869 (PKIX_PL_Object *) cert, | |
2870 plContext); | |
2871 | |
2872 if (cachedSig != NULL) { | |
2873 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); | |
2874 } | |
2875 } | |
2876 | |
2877 cleanup: | |
2878 if (nssPubKey){ | |
2879 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); | |
2880 SECKEY_DestroyPublicKey(nssPubKey); | |
2881 } | |
2882 | |
2883 PKIX_DECREF(cachedCert); | |
2884 PKIX_DECREF(verifySig); | |
2885 PKIX_DECREF(cachedSig); | |
2886 | |
2887 PKIX_RETURN(CERT); | |
2888 } | |
2889 | |
2890 /* | |
2891 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) | |
2892 */ | |
2893 PKIX_Error * | |
2894 PKIX_PL_Cert_CheckValidity( | |
2895 PKIX_PL_Cert *cert, | |
2896 PKIX_PL_Date *date, | |
2897 void *plContext) | |
2898 { | |
2899 SECCertTimeValidity val; | |
2900 PRTime timeToCheck; | |
2901 PKIX_Boolean allowOverride; | |
2902 SECCertificateUsage requiredUsages; | |
2903 | |
2904 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); | |
2905 PKIX_NULLCHECK_ONE(cert); | |
2906 | |
2907 /* if the caller supplies a date, we use it; else, use current time */ | |
2908 if (date != NULL){ | |
2909 PKIX_CHECK(pkix_pl_Date_GetPRTime | |
2910 (date, &timeToCheck, plContext), | |
2911 PKIX_DATEGETPRTIMEFAILED); | |
2912 } else { | |
2913 timeToCheck = PR_Now(); | |
2914 } | |
2915 | |
2916 requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
2917 allowOverride = | |
2918 (PRBool)((requiredUsages & certificateUsageSSLServer) || | |
2919 (requiredUsages & certificateUsageSSLServerWithStepUp)); | |
2920 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride); | |
2921 if (val != secCertTimeValid){ | |
2922 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); | |
2923 } | |
2924 | |
2925 cleanup: | |
2926 PKIX_RETURN(CERT); | |
2927 } | |
2928 | |
2929 /* | |
2930 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) | |
2931 */ | |
2932 PKIX_Error * | |
2933 PKIX_PL_Cert_GetValidityNotAfter( | |
2934 PKIX_PL_Cert *cert, | |
2935 PKIX_PL_Date **pDate, | |
2936 void *plContext) | |
2937 { | |
2938 PRTime prtime; | |
2939 SECStatus rv = SECFailure; | |
2940 | |
2941 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); | |
2942 PKIX_NULLCHECK_TWO(cert, pDate); | |
2943 | |
2944 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); | |
2945 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); | |
2946 if (rv != SECSuccess){ | |
2947 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); | |
2948 } | |
2949 | |
2950 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime | |
2951 (prtime, pDate, plContext), | |
2952 PKIX_DATECREATEFROMPRTIMEFAILED); | |
2953 | |
2954 cleanup: | |
2955 PKIX_RETURN(CERT); | |
2956 } | |
2957 | |
2958 /* | |
2959 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) | |
2960 */ | |
2961 PKIX_Error * | |
2962 PKIX_PL_Cert_VerifyCertAndKeyType( | |
2963 PKIX_PL_Cert *cert, | |
2964 PKIX_Boolean isChainCert, | |
2965 void *plContext) | |
2966 { | |
2967 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; | |
2968 SECCertificateUsage certificateUsage; | |
2969 SECCertUsage certUsage = 0; | |
2970 unsigned int requiredKeyUsage; | |
2971 unsigned int requiredCertType; | |
2972 unsigned int certType; | |
2973 SECStatus rv = SECSuccess; | |
2974 | |
2975 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); | |
2976 PKIX_NULLCHECK_TWO(cert, plContext); | |
2977 | |
2978 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
2979 | |
2980 /* ensure we obtained a single usage bit only */ | |
2981 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
2982 | |
2983 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
2984 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
2985 | |
2986 /* check key usage and netscape cert type */ | |
2987 cert_GetCertType(cert->nssCert); | |
2988 certType = cert->nssCert->nsCertType; | |
2989 if (isChainCert || | |
2990 (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { | |
2991 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, | |
2992 &requiredKeyUsage, | |
2993 &requiredCertType); | |
2994 if (rv == SECFailure) { | |
2995 PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); | |
2996 } | |
2997 } else { | |
2998 /* use this key usage and cert type for certUsageAnyCA and | |
2999 * certUsageVerifyCA. */ | |
3000 requiredKeyUsage = KU_KEY_CERT_SIGN; | |
3001 requiredCertType = NS_CERT_TYPE_CA; | |
3002 } | |
3003 if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { | |
3004 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
3005 } | |
3006 if (!(certType & requiredCertType)) { | |
3007 PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); | |
3008 } | |
3009 cleanup: | |
3010 PKIX_DECREF(basicConstraints); | |
3011 PKIX_RETURN(CERT); | |
3012 } | |
3013 | |
3014 /* | |
3015 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) | |
3016 */ | |
3017 PKIX_Error * | |
3018 PKIX_PL_Cert_VerifyKeyUsage( | |
3019 PKIX_PL_Cert *cert, | |
3020 PKIX_UInt32 keyUsage, | |
3021 void *plContext) | |
3022 { | |
3023 CERTCertificate *nssCert = NULL; | |
3024 PKIX_UInt32 nssKeyUsage = 0; | |
3025 SECStatus status; | |
3026 | |
3027 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); | |
3028 PKIX_NULLCHECK_TWO(cert, cert->nssCert); | |
3029 | |
3030 nssCert = cert->nssCert; | |
3031 | |
3032 /* if cert doesn't have keyUsage extension, all keyUsages are valid */ | |
3033 if (!nssCert->keyUsagePresent){ | |
3034 goto cleanup; | |
3035 } | |
3036 | |
3037 if (keyUsage & PKIX_DIGITAL_SIGNATURE){ | |
3038 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; | |
3039 } | |
3040 | |
3041 if (keyUsage & PKIX_NON_REPUDIATION){ | |
3042 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; | |
3043 } | |
3044 | |
3045 if (keyUsage & PKIX_KEY_ENCIPHERMENT){ | |
3046 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; | |
3047 } | |
3048 | |
3049 if (keyUsage & PKIX_DATA_ENCIPHERMENT){ | |
3050 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; | |
3051 } | |
3052 | |
3053 if (keyUsage & PKIX_KEY_AGREEMENT){ | |
3054 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; | |
3055 } | |
3056 | |
3057 if (keyUsage & PKIX_KEY_CERT_SIGN){ | |
3058 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; | |
3059 } | |
3060 | |
3061 if (keyUsage & PKIX_CRL_SIGN){ | |
3062 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; | |
3063 } | |
3064 | |
3065 if (keyUsage & PKIX_ENCIPHER_ONLY){ | |
3066 nssKeyUsage = nssKeyUsage | 0x01; | |
3067 } | |
3068 | |
3069 if (keyUsage & PKIX_DECIPHER_ONLY){ | |
3070 /* XXX we should support this once it is fixed in NSS */ | |
3071 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); | |
3072 } | |
3073 | |
3074 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); | |
3075 if (status != SECSuccess) { | |
3076 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
3077 } | |
3078 | |
3079 cleanup: | |
3080 PKIX_RETURN(CERT); | |
3081 } | |
3082 | |
3083 /* | |
3084 * FUNCTION: PKIX_PL_Cert_GetNameConstraints | |
3085 * (see comments in pkix_pl_pki.h) | |
3086 */ | |
3087 PKIX_Error * | |
3088 PKIX_PL_Cert_GetNameConstraints( | |
3089 PKIX_PL_Cert *cert, | |
3090 PKIX_PL_CertNameConstraints **pNameConstraints, | |
3091 void *plContext) | |
3092 { | |
3093 PKIX_PL_CertNameConstraints *nameConstraints = NULL; | |
3094 | |
3095 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); | |
3096 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); | |
3097 | |
3098 /* if we don't have a cached copy from before, we create one */ | |
3099 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { | |
3100 | |
3101 PKIX_OBJECT_LOCK(cert); | |
3102 | |
3103 if (cert->nameConstraints == NULL && | |
3104 !cert->nameConstraintsAbsent) { | |
3105 | |
3106 PKIX_CHECK(pkix_pl_CertNameConstraints_Create | |
3107 (cert->nssCert, &nameConstraints, plContext), | |
3108 PKIX_CERTNAMECONSTRAINTSCREATEFAILED); | |
3109 | |
3110 if (nameConstraints == NULL) { | |
3111 cert->nameConstraintsAbsent = PKIX_TRUE; | |
3112 } | |
3113 | |
3114 cert->nameConstraints = nameConstraints; | |
3115 } | |
3116 | |
3117 PKIX_OBJECT_UNLOCK(cert); | |
3118 | |
3119 } | |
3120 | |
3121 PKIX_INCREF(cert->nameConstraints); | |
3122 | |
3123 *pNameConstraints = cert->nameConstraints; | |
3124 | |
3125 cleanup: | |
3126 PKIX_OBJECT_UNLOCK(lockedObject); | |
3127 PKIX_RETURN(CERT); | |
3128 } | |
3129 | |
3130 /* | |
3131 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints | |
3132 * (see comments in pkix_pl_pki.h) | |
3133 */ | |
3134 PKIX_Error * | |
3135 PKIX_PL_Cert_CheckNameConstraints( | |
3136 PKIX_PL_Cert *cert, | |
3137 PKIX_PL_CertNameConstraints *nameConstraints, | |
3138 PKIX_Boolean treatCommonNameAsDNSName, | |
3139 void *plContext) | |
3140 { | |
3141 PKIX_Boolean checkPass = PKIX_TRUE; | |
3142 CERTGeneralName *nssSubjectNames = NULL; | |
3143 PLArenaPool *arena = NULL; | |
3144 | |
3145 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); | |
3146 PKIX_NULLCHECK_ONE(cert); | |
3147 | |
3148 if (nameConstraints != NULL) { | |
3149 | |
3150 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
3151 if (arena == NULL) { | |
3152 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3153 } | |
3154 | |
3155 /* This NSS call returns Subject Alt Names. If | |
3156 * treatCommonNameAsDNSName is true, it also returns the | |
3157 * Subject Common Name | |
3158 */ | |
3159 PKIX_CERT_DEBUG | |
3160 ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); | |
3161 nssSubjectNames = CERT_GetConstrainedCertificateNames | |
3162 (cert->nssCert, arena, treatCommonNameAsDNSName); | |
3163 | |
3164 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames | |
3165 (nssSubjectNames, | |
3166 nameConstraints, | |
3167 &checkPass, | |
3168 plContext), | |
3169 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); | |
3170 | |
3171 if (checkPass != PKIX_TRUE) { | |
3172 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); | |
3173 } | |
3174 } | |
3175 | |
3176 cleanup: | |
3177 if (arena){ | |
3178 PORT_FreeArena(arena, PR_FALSE); | |
3179 } | |
3180 | |
3181 PKIX_RETURN(CERT); | |
3182 } | |
3183 | |
3184 /* | |
3185 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints | |
3186 * (see comments in pkix_pl_pki.h) | |
3187 */ | |
3188 PKIX_Error * | |
3189 PKIX_PL_Cert_MergeNameConstraints( | |
3190 PKIX_PL_CertNameConstraints *firstNC, | |
3191 PKIX_PL_CertNameConstraints *secondNC, | |
3192 PKIX_PL_CertNameConstraints **pResultNC, | |
3193 void *plContext) | |
3194 { | |
3195 PKIX_PL_CertNameConstraints *mergedNC = NULL; | |
3196 | |
3197 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); | |
3198 PKIX_NULLCHECK_TWO(firstNC, pResultNC); | |
3199 | |
3200 if (secondNC == NULL) { | |
3201 | |
3202 PKIX_INCREF(firstNC); | |
3203 *pResultNC = firstNC; | |
3204 | |
3205 goto cleanup; | |
3206 } | |
3207 | |
3208 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge | |
3209 (firstNC, secondNC, &mergedNC, plContext), | |
3210 PKIX_CERTNAMECONSTRAINTSMERGEFAILED); | |
3211 | |
3212 *pResultNC = mergedNC; | |
3213 | |
3214 cleanup: | |
3215 PKIX_RETURN(CERT); | |
3216 } | |
3217 | |
3218 /* | |
3219 * Find out the state of the NSS trust bits for the requested usage. | |
3220 * Returns SECFailure if the cert is explicitly distrusted. | |
3221 * Returns SECSuccess if the cert can be used to form a chain (normal case), | |
3222 * or it is explicitly trusted. The trusted bool is set to true if it is | |
3223 * explicitly trusted. | |
3224 */ | |
3225 static SECStatus | |
3226 pkix_pl_Cert_GetTrusted(void *plContext, | |
3227 PKIX_PL_Cert *cert, | |
3228 PKIX_Boolean *trusted, | |
3229 PKIX_Boolean isCA) | |
3230 { | |
3231 SECStatus rv; | |
3232 CERTCertificate *nssCert = NULL; | |
3233 SECCertUsage certUsage = 0; | |
3234 SECCertificateUsage certificateUsage; | |
3235 SECTrustType trustType; | |
3236 unsigned int trustFlags; | |
3237 unsigned int requiredFlags; | |
3238 CERTCertTrust trust; | |
3239 | |
3240 *trusted = PKIX_FALSE; | |
3241 | |
3242 /* no key usage information */ | |
3243 if (plContext == NULL) { | |
3244 return SECSuccess; | |
3245 } | |
3246 | |
3247 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
3248 | |
3249 /* ensure we obtained a single usage bit only */ | |
3250 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
3251 | |
3252 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
3253 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
3254 | |
3255 nssCert = cert->nssCert; | |
3256 | |
3257 if (!isCA) { | |
3258 PRBool prTrusted; | |
3259 unsigned int failedFlags; | |
3260 rv = cert_CheckLeafTrust(nssCert, certUsage, | |
3261 &failedFlags, &prTrusted); | |
3262 *trusted = (PKIX_Boolean) prTrusted; | |
3263 return rv; | |
3264 } | |
3265 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, | |
3266 &trustType); | |
3267 if (rv != SECSuccess) { | |
3268 return SECSuccess; | |
3269 } | |
3270 | |
3271 rv = CERT_GetCertTrust(nssCert, &trust); | |
3272 if (rv != SECSuccess) { | |
3273 return SECSuccess; | |
3274 } | |
3275 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); | |
3276 /* normally trustTypeNone usages accept any of the given trust bits | |
3277 * being on as acceptable. If any are distrusted (and none are trusted), | |
3278 * then we will also distrust the cert */ | |
3279 if ((trustFlags == 0) && (trustType == trustTypeNone)) { | |
3280 trustFlags = trust.sslFlags | trust.emailFlags | | |
3281 trust.objectSigningFlags; | |
3282 } | |
3283 if ((trustFlags & requiredFlags) == requiredFlags) { | |
3284 *trusted = PKIX_TRUE; | |
3285 return SECSuccess; | |
3286 } | |
3287 if ((trustFlags & CERTDB_TERMINAL_RECORD) && | |
3288 ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { | |
3289 return SECFailure; | |
3290 } | |
3291 return SECSuccess; | |
3292 } | |
3293 | |
3294 /* | |
3295 * FUNCTION: PKIX_PL_Cert_IsCertTrusted | |
3296 * (see comments in pkix_pl_pki.h) | |
3297 */ | |
3298 PKIX_Error * | |
3299 PKIX_PL_Cert_IsCertTrusted( | |
3300 PKIX_PL_Cert *cert, | |
3301 PKIX_PL_TrustAnchorMode trustAnchorMode, | |
3302 PKIX_Boolean *pTrusted, | |
3303 void *plContext) | |
3304 { | |
3305 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; | |
3306 PKIX_Boolean trusted = PKIX_FALSE; | |
3307 SECStatus rv = SECFailure; | |
3308 | |
3309 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); | |
3310 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
3311 | |
3312 /* Call GetTrusted first to see if we are going to distrust the | |
3313 * certificate */ | |
3314 rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); | |
3315 if (rv != SECSuccess) { | |
3316 /* Failure means the cert is explicitly distrusted, | |
3317 * let the next level know not to use it. */ | |
3318 *pTrusted = PKIX_FALSE; | |
3319 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
3320 } | |
3321 | |
3322 if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || | |
3323 (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && | |
3324 cert->isUserTrustAnchor)) { | |
3325 /* Use the trust anchor's |trusted| value */ | |
3326 *pTrusted = cert->isUserTrustAnchor; | |
3327 goto cleanup; | |
3328 } | |
3329 | |
3330 /* no key usage information or store is not trusted */ | |
3331 if (plContext == NULL || cert->store == NULL) { | |
3332 *pTrusted = PKIX_FALSE; | |
3333 goto cleanup; | |
3334 } | |
3335 | |
3336 PKIX_CHECK(PKIX_CertStore_GetTrustCallback | |
3337 (cert->store, &trustCallback, plContext), | |
3338 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); | |
3339 | |
3340 PKIX_CHECK_ONLY_FATAL(trustCallback | |
3341 (cert->store, cert, &trusted, plContext), | |
3342 PKIX_CHECKTRUSTCALLBACKFAILED); | |
3343 | |
3344 /* allow trust store to override if we can trust the trust | |
3345 * bits */ | |
3346 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { | |
3347 *pTrusted = PKIX_FALSE; | |
3348 goto cleanup; | |
3349 } | |
3350 | |
3351 *pTrusted = trusted; | |
3352 | |
3353 cleanup: | |
3354 PKIX_RETURN(CERT); | |
3355 } | |
3356 | |
3357 /* | |
3358 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted | |
3359 * (see comments in pkix_pl_pki.h) | |
3360 */ | |
3361 PKIX_Error * | |
3362 PKIX_PL_Cert_IsLeafCertTrusted( | |
3363 PKIX_PL_Cert *cert, | |
3364 PKIX_Boolean *pTrusted, | |
3365 void *plContext) | |
3366 { | |
3367 SECStatus rv; | |
3368 | |
3369 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); | |
3370 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
3371 | |
3372 *pTrusted = PKIX_FALSE; | |
3373 | |
3374 rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); | |
3375 if (rv != SECSuccess) { | |
3376 /* Failure means the cert is explicitly distrusted, | |
3377 * let the next level know not to use it. */ | |
3378 *pTrusted = PKIX_FALSE; | |
3379 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
3380 } | |
3381 | |
3382 cleanup: | |
3383 PKIX_RETURN(CERT); | |
3384 } | |
3385 | |
3386 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ | |
3387 PKIX_Error* | |
3388 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, | |
3389 void *plContext) | |
3390 { | |
3391 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); | |
3392 PKIX_NULLCHECK_ONE(cert); | |
3393 | |
3394 cert->isUserTrustAnchor = PKIX_TRUE; | |
3395 | |
3396 PKIX_RETURN(CERT); | |
3397 } | |
3398 | |
3399 /* | |
3400 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) | |
3401 */ | |
3402 PKIX_Error * | |
3403 PKIX_PL_Cert_GetCacheFlag( | |
3404 PKIX_PL_Cert *cert, | |
3405 PKIX_Boolean *pCacheFlag, | |
3406 void *plContext) | |
3407 { | |
3408 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); | |
3409 PKIX_NULLCHECK_TWO(cert, pCacheFlag); | |
3410 | |
3411 *pCacheFlag = cert->cacheFlag; | |
3412 | |
3413 PKIX_RETURN(CERT); | |
3414 } | |
3415 | |
3416 /* | |
3417 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) | |
3418 */ | |
3419 PKIX_Error * | |
3420 PKIX_PL_Cert_SetCacheFlag( | |
3421 PKIX_PL_Cert *cert, | |
3422 PKIX_Boolean cacheFlag, | |
3423 void *plContext) | |
3424 { | |
3425 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); | |
3426 PKIX_NULLCHECK_ONE(cert); | |
3427 | |
3428 cert->cacheFlag = cacheFlag; | |
3429 | |
3430 PKIX_RETURN(CERT); | |
3431 } | |
3432 | |
3433 /* | |
3434 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) | |
3435 */ | |
3436 PKIX_Error * | |
3437 PKIX_PL_Cert_GetTrustCertStore( | |
3438 PKIX_PL_Cert *cert, | |
3439 PKIX_CertStore **pTrustCertStore, | |
3440 void *plContext) | |
3441 { | |
3442 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); | |
3443 PKIX_NULLCHECK_TWO(cert, pTrustCertStore); | |
3444 | |
3445 PKIX_INCREF(cert->store); | |
3446 *pTrustCertStore = cert->store; | |
3447 | |
3448 cleanup: | |
3449 PKIX_RETURN(CERT); | |
3450 } | |
3451 | |
3452 /* | |
3453 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) | |
3454 */ | |
3455 PKIX_Error * | |
3456 PKIX_PL_Cert_SetTrustCertStore( | |
3457 PKIX_PL_Cert *cert, | |
3458 PKIX_CertStore *trustCertStore, | |
3459 void *plContext) | |
3460 { | |
3461 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); | |
3462 PKIX_NULLCHECK_TWO(cert, trustCertStore); | |
3463 | |
3464 PKIX_INCREF(trustCertStore); | |
3465 cert->store = trustCertStore; | |
3466 | |
3467 cleanup: | |
3468 PKIX_RETURN(CERT); | |
3469 } | |
3470 | |
3471 /* | |
3472 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess | |
3473 * (see comments in pkix_pl_pki.h) | |
3474 */ | |
3475 PKIX_Error * | |
3476 PKIX_PL_Cert_GetAuthorityInfoAccess( | |
3477 PKIX_PL_Cert *cert, | |
3478 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ | |
3479 void *plContext) | |
3480 { | |
3481 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ | |
3482 SECItem *encodedAIA = NULL; | |
3483 CERTAuthInfoAccess **aia = NULL; | |
3484 PLArenaPool *arena = NULL; | |
3485 SECStatus rv; | |
3486 | |
3487 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); | |
3488 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); | |
3489 | |
3490 /* if we don't have a cached copy from before, we create one */ | |
3491 if (cert->authorityInfoAccess == NULL) { | |
3492 | |
3493 PKIX_OBJECT_LOCK(cert); | |
3494 | |
3495 if (cert->authorityInfoAccess == NULL) { | |
3496 | |
3497 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, | |
3498 (NULL, NULL, 0)); | |
3499 | |
3500 if (encodedAIA == NULL) { | |
3501 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3502 } | |
3503 | |
3504 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, | |
3505 (cert->nssCert, | |
3506 SEC_OID_X509_AUTH_INFO_ACCESS, | |
3507 encodedAIA)); | |
3508 | |
3509 if (rv == SECFailure) { | |
3510 goto cleanup; | |
3511 } | |
3512 | |
3513 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, | |
3514 (DER_DEFAULT_CHUNKSIZE)); | |
3515 | |
3516 if (arena == NULL) { | |
3517 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3518 } | |
3519 | |
3520 PKIX_PL_NSSCALLRV | |
3521 (CERT, aia, CERT_DecodeAuthInfoAccessExtension, | |
3522 (arena, encodedAIA)); | |
3523 | |
3524 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
3525 (aia, &aiaList, plContext), | |
3526 PKIX_INFOACCESSCREATELISTFAILED); | |
3527 | |
3528 cert->authorityInfoAccess = aiaList; | |
3529 } | |
3530 | |
3531 PKIX_OBJECT_UNLOCK(cert); | |
3532 } | |
3533 | |
3534 PKIX_INCREF(cert->authorityInfoAccess); | |
3535 | |
3536 *pAiaList = cert->authorityInfoAccess; | |
3537 | |
3538 cleanup: | |
3539 PKIX_OBJECT_UNLOCK(lockedObject); | |
3540 if (arena != NULL) { | |
3541 PORT_FreeArena(arena, PR_FALSE); | |
3542 } | |
3543 | |
3544 if (encodedAIA != NULL) { | |
3545 SECITEM_FreeItem(encodedAIA, PR_TRUE); | |
3546 } | |
3547 | |
3548 PKIX_RETURN(CERT); | |
3549 } | |
3550 | |
3551 /* XXX Following defines belongs to NSS */ | |
3552 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, | |
3553 0x07, 0x01, 0x0b}; | |
3554 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } | |
3555 | |
3556 /* | |
3557 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess | |
3558 * (see comments in pkix_pl_pki.h) | |
3559 */ | |
3560 PKIX_Error * | |
3561 PKIX_PL_Cert_GetSubjectInfoAccess( | |
3562 PKIX_PL_Cert *cert, | |
3563 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ | |
3564 void *plContext) | |
3565 { | |
3566 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ | |
3567 SECItem siaOID = OI(siaOIDString); | |
3568 SECItem *encodedSubjInfoAccess = NULL; | |
3569 CERTAuthInfoAccess **subjInfoAccess = NULL; | |
3570 PLArenaPool *arena = NULL; | |
3571 SECStatus rv; | |
3572 | |
3573 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); | |
3574 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); | |
3575 | |
3576 /* XXX | |
3577 * Codes to deal with SubjectInfoAccess OID should be moved to | |
3578 * NSS soon. I implemented them here so we don't touch NSS | |
3579 * source tree, from JP's suggestion. | |
3580 */ | |
3581 | |
3582 /* if we don't have a cached copy from before, we create one */ | |
3583 if (cert->subjectInfoAccess == NULL) { | |
3584 | |
3585 PKIX_OBJECT_LOCK(cert); | |
3586 | |
3587 if (cert->subjectInfoAccess == NULL) { | |
3588 | |
3589 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); | |
3590 if (encodedSubjInfoAccess == NULL) { | |
3591 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3592 } | |
3593 | |
3594 PKIX_CERT_DEBUG | |
3595 ("\t\tCalling CERT_FindCertExtensionByOID).\n"); | |
3596 rv = CERT_FindCertExtensionByOID | |
3597 (cert->nssCert, &siaOID, encodedSubjInfoAccess); | |
3598 | |
3599 if (rv == SECFailure) { | |
3600 goto cleanup; | |
3601 } | |
3602 | |
3603 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
3604 if (arena == NULL) { | |
3605 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
3606 } | |
3607 | |
3608 /* XXX | |
3609 * Decode Subject Information Access - | |
3610 * since its type is the same as Authority Information | |
3611 * Access, reuse the call. NSS- change name to avoid | |
3612 * confusion. | |
3613 */ | |
3614 PKIX_CERT_DEBUG | |
3615 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); | |
3616 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension | |
3617 (arena, encodedSubjInfoAccess); | |
3618 | |
3619 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
3620 (subjInfoAccess, &siaList, plContext), | |
3621 PKIX_INFOACCESSCREATELISTFAILED); | |
3622 | |
3623 cert->subjectInfoAccess = siaList; | |
3624 | |
3625 } | |
3626 | |
3627 PKIX_OBJECT_UNLOCK(cert); | |
3628 } | |
3629 | |
3630 PKIX_INCREF(cert->subjectInfoAccess); | |
3631 *pSiaList = cert->subjectInfoAccess; | |
3632 | |
3633 cleanup: | |
3634 PKIX_OBJECT_UNLOCK(lockedObject); | |
3635 if (arena != NULL) { | |
3636 PORT_FreeArena(arena, PR_FALSE); | |
3637 } | |
3638 | |
3639 if (encodedSubjInfoAccess != NULL) { | |
3640 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); | |
3641 } | |
3642 PKIX_RETURN(CERT); | |
3643 } | |
3644 | |
3645 /* | |
3646 * FUNCTION: PKIX_PL_Cert_GetCrlDp | |
3647 * (see comments in pkix_pl_pki.h) | |
3648 */ | |
3649 PKIX_Error * | |
3650 PKIX_PL_Cert_GetCrlDp( | |
3651 PKIX_PL_Cert *cert, | |
3652 PKIX_List **pDpList, | |
3653 void *plContext) | |
3654 { | |
3655 PKIX_UInt32 dpIndex = 0; | |
3656 pkix_pl_CrlDp *dp = NULL; | |
3657 CERTCrlDistributionPoints *dpoints = NULL; | |
3658 | |
3659 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); | |
3660 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); | |
3661 | |
3662 /* if we don't have a cached copy from before, we create one */ | |
3663 if (cert->crldpList == NULL) { | |
3664 PKIX_OBJECT_LOCK(cert); | |
3665 if (cert->crldpList != NULL) { | |
3666 goto cleanup; | |
3667 } | |
3668 PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), | |
3669 PKIX_LISTCREATEFAILED); | |
3670 dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); | |
3671 if (!dpoints || !dpoints->distPoints) { | |
3672 goto cleanup; | |
3673 } | |
3674 for (;dpoints->distPoints[dpIndex];dpIndex++) { | |
3675 PKIX_CHECK( | |
3676 pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], | |
3677 &cert->nssCert->issuer, | |
3678 &dp, plContext), | |
3679 PKIX_CRLDPCREATEFAILED); | |
3680 /* Create crldp list in reverse order in attempt to get | |
3681 * to the whole crl first. */ | |
3682 PKIX_CHECK( | |
3683 PKIX_List_InsertItem(cert->crldpList, 0, | |
3684 (PKIX_PL_Object*)dp, | |
3685 plContext), | |
3686 PKIX_LISTAPPENDITEMFAILED); | |
3687 PKIX_DECREF(dp); | |
3688 } | |
3689 } | |
3690 cleanup: | |
3691 PKIX_INCREF(cert->crldpList); | |
3692 *pDpList = cert->crldpList; | |
3693 | |
3694 PKIX_OBJECT_UNLOCK(lockedObject); | |
3695 PKIX_DECREF(dp); | |
3696 | |
3697 PKIX_RETURN(CERT); | |
3698 } | |
3699 | |
3700 /* | |
3701 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate | |
3702 * (see comments in pkix_pl_pki.h) | |
3703 */ | |
3704 PKIX_Error * | |
3705 PKIX_PL_Cert_GetCERTCertificate( | |
3706 PKIX_PL_Cert *cert, | |
3707 CERTCertificate **pnssCert, | |
3708 void *plContext) | |
3709 { | |
3710 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); | |
3711 PKIX_NULLCHECK_TWO(cert, pnssCert); | |
3712 | |
3713 *pnssCert = CERT_DupCertificate(cert->nssCert); | |
3714 | |
3715 PKIX_RETURN(CERT); | |
3716 } |