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 &notBeforeString,
933 plContext),
934 PKIX_DATETOSTRINGHELPERFAILED);
935
936 /* Validity: NotAfter */
937 PKIX_CHECK(pkix_pl_Date_ToString_Helper
938 (&(cert->nssCert->validity.notAfter),
939 &notAfterString,
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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)