Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_cert.c
blob0cd8539110cca1c821f3ab0175a8e4f9e63af5ec
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_cert.c
40 * Certificate Object Functions
44 #include "pkix_pl_cert.h"
46 extern PKIX_PL_HashTable *cachedCertSigTable;
48 /* --Private-Cert-Functions------------------------------------- */
51 * FUNCTION: pkix_pl_Cert_IsExtensionCritical
52 * DESCRIPTION:
54 * Checks the Cert specified by "cert" to determine whether the extension
55 * whose tag is the UInt32 value given by "tag" is marked as a critical
56 * extension, and stores the result in "pCritical".
58 * Tags are the index into the table "oids" of SECOidData defined in the
59 * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
60 * are defined in secoidt.h for most of the table entries.
62 * If the specified tag is invalid (not in the list of tags) or if the
63 * extension is not found in the certificate, PKIX_FALSE is stored.
65 * PARAMETERS
66 * "cert"
67 * Address of Cert whose extensions are to be examined. Must be non-NULL.
68 * "tag"
69 * The UInt32 value of the tag for the extension whose criticality is
70 * to be determined
71 * "pCritical"
72 * Address where the Boolean value will be stored. Must be non-NULL.
73 * "plContext"
74 * Platform-specific context pointer.
75 * THREAD SAFETY:
76 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
77 * RETURNS:
78 * Returns NULL if the function succeeds.
79 * Returns a Fatal Error if the function fails in an unrecoverable way.
81 static PKIX_Error *
82 pkix_pl_Cert_IsExtensionCritical(
83 PKIX_PL_Cert *cert,
84 PKIX_UInt32 tag,
85 PKIX_Boolean *pCritical,
86 void *plContext)
88 PKIX_Boolean criticality = PKIX_FALSE;
89 CERTCertExtension **extensions = NULL;
90 SECStatus rv;
92 PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
93 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);
95 extensions = cert->nssCert->extensions;
96 PKIX_NULLCHECK_ONE(extensions);
98 PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
99 rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
100 if (SECSuccess == rv) {
101 *pCritical = criticality;
102 } else {
103 *pCritical = PKIX_FALSE;
106 PKIX_RETURN(CERT);
110 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
111 * DESCRIPTION:
113 * Decodes the contents of the CertificatePolicy extension in the
114 * CERTCertificate pointed to by "nssCert", to create a List of
115 * CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
116 * A CERTCertificate contains the DER representation of the Cert.
117 * If this certificate does not have a CertificatePolicy extension,
118 * NULL will be stored. If a List is returned, it will be immutable.
120 * PARAMETERS
121 * "nssCert"
122 * Address of the Cert data whose extension is to be examined. Must be
123 * non-NULL.
124 * "pCertPolicyInfos"
125 * Address where the List of CertPolicyInfos will be stored. Must be
126 * non-NULL.
127 * "plContext"
128 * Platform-specific context pointer.
129 * THREAD SAFETY:
130 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
131 * RETURNS:
132 * Returns NULL if the function succeeds.
133 * Returns a Cert Error if the function fails in a non-fatal way.
134 * Returns a Fatal Error if the function fails in an unrecoverable way.
136 static PKIX_Error *
137 pkix_pl_Cert_DecodePolicyInfo(
138 CERTCertificate *nssCert,
139 PKIX_List **pCertPolicyInfos,
140 void *plContext)
143 SECStatus rv;
144 SECItem encodedCertPolicyInfo;
146 /* Allocated in the arena; freed in CERT_Destroy... */
147 CERTCertificatePolicies *certPol = NULL;
148 CERTPolicyInfo **policyInfos = NULL;
149 CERTPolicyInfo *policyInfo = NULL;
150 CERTPolicyQualifier **policyQualifiers = NULL;
151 CERTPolicyQualifier *policyQualifier = NULL;
153 /* Holder for the return value */
154 PKIX_List *infos = NULL;
156 char *oidAscii = NULL;
157 PKIX_PL_OID *pkixOID = NULL;
158 PKIX_List *qualifiers = NULL;
159 PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
160 PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
161 PKIX_PL_ByteArray *qualifierArray = NULL;
163 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
164 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);
166 /* get PolicyInfo as a SECItem */
167 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
168 rv = CERT_FindCertExtension
169 (nssCert,
170 SEC_OID_X509_CERTIFICATE_POLICIES,
171 &encodedCertPolicyInfo);
172 if (SECSuccess != rv) {
173 *pCertPolicyInfos = NULL;
174 goto cleanup;
177 /* translate PolicyInfo to CERTCertificatePolicies */
178 PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
179 certPol = CERT_DecodeCertificatePoliciesExtension
180 (&encodedCertPolicyInfo);
182 PKIX_CERT_DEBUG("\t\tCalling PORT_Free).\n");
183 PORT_Free(encodedCertPolicyInfo.data);
185 if (NULL == certPol) {
186 PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
190 * Check whether there are any policyInfos, so we can
191 * avoid creating an unnecessary List
193 policyInfos = certPol->policyInfos;
194 if (!policyInfos) {
195 *pCertPolicyInfos = NULL;
196 goto cleanup;
199 /* create a List of CertPolicyInfo Objects */
200 PKIX_CHECK(PKIX_List_Create(&infos, plContext),
201 PKIX_LISTCREATEFAILED);
204 * Traverse the CERTCertificatePolicies structure,
205 * building each PKIX_PL_CertPolicyInfo object in turn
207 while (*policyInfos != NULL) {
208 policyInfo = *policyInfos;
209 policyQualifiers = policyInfo->policyQualifiers;
210 if (policyQualifiers) {
211 /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
212 PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
213 PKIX_LISTCREATEFAILED);
215 while (*policyQualifiers != NULL) {
216 policyQualifier = *policyQualifiers;
218 /* create the qualifier's OID object */
220 PKIX_CHECK(pkix_pl_oidBytes2Ascii
221 (&(policyQualifier->qualifierID),
222 &oidAscii,
223 plContext),
224 PKIX_OIDBYTES2ASCIIFAILED);
226 PKIX_CHECK(PKIX_PL_OID_Create
227 (oidAscii, &pkixOID, plContext),
228 PKIX_OIDCREATEFAILED);
230 /* create qualifier's ByteArray object */
232 PKIX_CHECK(PKIX_PL_ByteArray_Create
233 (policyQualifier->qualifierValue.data,
234 policyQualifier->qualifierValue.len,
235 &qualifierArray,
236 plContext),
237 PKIX_BYTEARRAYCREATEFAILED);
239 /* create a CertPolicyQualifier object */
241 PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
242 (pkixOID,
243 qualifierArray,
244 &certPolicyQualifier,
245 plContext),
246 PKIX_CERTPOLICYQUALIFIERCREATEFAILED);
248 PKIX_CHECK(PKIX_List_AppendItem
249 (qualifiers,
250 (PKIX_PL_Object *)certPolicyQualifier,
251 plContext),
252 PKIX_LISTAPPENDITEMFAILED);
254 PKIX_FREE(oidAscii);
255 PKIX_DECREF(pkixOID);
256 PKIX_DECREF(qualifierArray);
257 PKIX_DECREF(certPolicyQualifier);
259 policyQualifiers++;
262 PKIX_CHECK(PKIX_List_SetImmutable
263 (qualifiers, plContext),
264 PKIX_LISTSETIMMUTABLEFAILED);
269 * Create an OID object pkixOID from policyInfo->policyID.
270 * (The CERTPolicyInfo structure has an oid field, but it
271 * is of type SECOidTag. This function wants a SECItem.)
274 PKIX_CHECK(pkix_pl_oidBytes2Ascii
275 (&(policyInfo->policyID), &oidAscii, plContext),
276 PKIX_OIDBYTES2ASCIIFAILED);
278 PKIX_CHECK(PKIX_PL_OID_Create
279 (oidAscii, &pkixOID, plContext),
280 PKIX_OIDCREATEFAILED);
282 /* Create a CertPolicyInfo object */
283 PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
284 (pkixOID, qualifiers, &certPolicyInfo, plContext),
285 PKIX_CERTPOLICYINFOCREATEFAILED);
287 /* Append the new CertPolicyInfo object to the list */
288 PKIX_CHECK(PKIX_List_AppendItem
289 (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
290 PKIX_LISTAPPENDITEMFAILED);
292 PKIX_FREE(oidAscii);
293 PKIX_DECREF(pkixOID);
294 PKIX_DECREF(qualifiers);
295 PKIX_DECREF(certPolicyInfo);
297 policyInfos++;
301 * If there were no policies, we went straight to
302 * cleanup, so we don't have to NULLCHECK infos.
304 PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
305 PKIX_LISTSETIMMUTABLEFAILED);
307 *pCertPolicyInfos = infos;
309 cleanup:
311 if (certPol) {
312 PKIX_CERT_DEBUG
313 ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
314 CERT_DestroyCertificatePoliciesExtension(certPol);
317 if (PKIX_ERROR_RECEIVED){
318 PKIX_DECREF(infos);
321 PKIX_FREE(oidAscii);
322 PKIX_DECREF(pkixOID);
323 PKIX_DECREF(qualifiers);
324 PKIX_DECREF(certPolicyInfo);
325 PKIX_DECREF(certPolicyQualifier);
326 PKIX_DECREF(qualifierArray);
327 PKIX_RETURN(CERT);
331 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
332 * DESCRIPTION:
334 * Decodes the contents of the PolicyMapping extension of the CERTCertificate
335 * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
336 * the address pointed to by "pCertPolicyMaps". If this certificate does not
337 * have a PolicyMapping extension, NULL will be stored. If a List is returned,
338 * it will be immutable.
340 * PARAMETERS
341 * "nssCert"
342 * Address of the Cert data whose extension is to be examined. Must be
343 * non-NULL.
344 * "pCertPolicyMaps"
345 * Address where the List of CertPolicyMaps will be stored. Must be
346 * non-NULL.
347 * "plContext"
348 * Platform-specific context pointer.
349 * THREAD SAFETY:
350 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
351 * RETURNS:
352 * Returns NULL if the function succeeds.
353 * Returns a Cert Error if the function fails in a non-fatal way.
354 * Returns a Fatal Error if the function fails in an unrecoverable way.
356 static PKIX_Error *
357 pkix_pl_Cert_DecodePolicyMapping(
358 CERTCertificate *nssCert,
359 PKIX_List **pCertPolicyMaps,
360 void *plContext)
362 SECStatus rv;
363 SECItem encodedCertPolicyMaps;
365 /* Allocated in the arena; freed in CERT_Destroy... */
366 CERTCertificatePolicyMappings *certPolMaps = NULL;
367 CERTPolicyMap **policyMaps = NULL;
368 CERTPolicyMap *policyMap = NULL;
370 /* Holder for the return value */
371 PKIX_List *maps = NULL;
373 char *issuerPolicyOIDAscii = NULL;
374 char *subjectPolicyOIDAscii = NULL;
375 PKIX_PL_OID *issuerDomainOID = NULL;
376 PKIX_PL_OID *subjectDomainOID = NULL;
377 PKIX_PL_CertPolicyMap *certPolicyMap = NULL;
379 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
380 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);
382 /* get PolicyMappings as a SECItem */
383 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
384 rv = CERT_FindCertExtension
385 (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
386 if (SECSuccess != rv) {
387 *pCertPolicyMaps = NULL;
388 goto cleanup;
391 /* translate PolicyMaps to CERTCertificatePolicyMappings */
392 certPolMaps = CERT_DecodePolicyMappingsExtension
393 (&encodedCertPolicyMaps);
395 PKIX_CERT_DEBUG("\t\tCalling PORT_Free).\n");
396 PORT_Free(encodedCertPolicyMaps.data);
398 if (!certPolMaps) {
399 PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
402 PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);
404 policyMaps = certPolMaps->policyMaps;
406 /* create a List of CertPolicyMap Objects */
407 PKIX_CHECK(PKIX_List_Create(&maps, plContext),
408 PKIX_LISTCREATEFAILED);
411 * Traverse the CERTCertificatePolicyMappings structure,
412 * building each CertPolicyMap object in turn
414 do {
415 policyMap = *policyMaps;
417 /* create the OID for the issuer Domain Policy */
419 PKIX_CHECK(pkix_pl_oidBytes2Ascii
420 (&(policyMap->issuerDomainPolicy),
421 &issuerPolicyOIDAscii,
422 plContext),
423 PKIX_OIDBYTES2ASCIIFAILED);
425 PKIX_CHECK(PKIX_PL_OID_Create
426 (issuerPolicyOIDAscii, &issuerDomainOID, plContext),
427 PKIX_OIDCREATEFAILED);
429 /* create the OID for the subject Domain Policy */
431 PKIX_CHECK(pkix_pl_oidBytes2Ascii
432 (&(policyMap->subjectDomainPolicy),
433 &subjectPolicyOIDAscii,
434 plContext),
435 PKIX_OIDBYTES2ASCIIFAILED);
437 PKIX_CHECK(PKIX_PL_OID_Create
438 (subjectPolicyOIDAscii, &subjectDomainOID, plContext),
439 PKIX_OIDCREATEFAILED);
441 /* create the CertPolicyMap */
443 PKIX_CHECK(pkix_pl_CertPolicyMap_Create
444 (issuerDomainOID,
445 subjectDomainOID,
446 &certPolicyMap,
447 plContext),
448 PKIX_CERTPOLICYMAPCREATEFAILED);
450 PKIX_CHECK(PKIX_List_AppendItem
451 (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
452 PKIX_LISTAPPENDITEMFAILED);
454 PKIX_FREE(issuerPolicyOIDAscii);
455 PKIX_FREE(subjectPolicyOIDAscii);
456 PKIX_DECREF(issuerDomainOID);
457 PKIX_DECREF(subjectDomainOID);
458 PKIX_DECREF(certPolicyMap);
460 policyMaps++;
461 } while (*policyMaps != NULL);
463 PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
464 PKIX_LISTSETIMMUTABLEFAILED);
466 *pCertPolicyMaps = maps;
468 cleanup:
470 if (certPolMaps) {
471 PKIX_CERT_DEBUG
472 ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
473 CERT_DestroyPolicyMappingsExtension(certPolMaps);
476 PKIX_FREE(issuerPolicyOIDAscii);
477 PKIX_FREE(subjectPolicyOIDAscii);
478 PKIX_DECREF(issuerDomainOID);
479 PKIX_DECREF(subjectDomainOID);
480 PKIX_DECREF(certPolicyMap);
482 PKIX_RETURN(CERT);
486 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
487 * DESCRIPTION:
489 * Decodes the contents of the PolicyConstraints extension in the
490 * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
491 * which are stored at the addresses "pExplicitPolicySkipCerts" and
492 * "pInhibitMappingSkipCerts", respectively. If this certificate does
493 * not have an PolicyConstraints extension, or if either of the optional
494 * components is not supplied, this function stores a value of -1 for any
495 * missing component.
497 * PARAMETERS
498 * "nssCert"
499 * Address of the Cert data whose extension is to be examined. Must be
500 * non-NULL.
501 * "pExplicitPolicySkipCerts"
502 * Address where the SkipCert value for the requireExplicitPolicy
503 * component will be stored. Must be non-NULL.
504 * "pInhibitMappingSkipCerts"
505 * Address where the SkipCert value for the inhibitPolicyMapping
506 * component will be stored. Must be non-NULL.
507 * "plContext"
508 * Platform-specific context pointer.
509 * THREAD SAFETY:
510 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
511 * RETURNS:
512 * Returns NULL if the function succeeds.
513 * Returns a Cert Error if the function fails in a non-fatal way.
514 * Returns a Fatal Error if the function fails in an unrecoverable way.
516 static PKIX_Error *
517 pkix_pl_Cert_DecodePolicyConstraints(
518 CERTCertificate *nssCert,
519 PKIX_Int32 *pExplicitPolicySkipCerts,
520 PKIX_Int32 *pInhibitMappingSkipCerts,
521 void *plContext)
523 CERTCertificatePolicyConstraints policyConstraints;
524 SECStatus rv;
525 SECItem encodedCertPolicyConstraints;
526 PKIX_Int32 explicitPolicySkipCerts = -1;
527 PKIX_Int32 inhibitMappingSkipCerts = -1;
529 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
530 PKIX_NULLCHECK_THREE
531 (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);
533 /* get the two skipCert values as SECItems */
534 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
535 rv = CERT_FindCertExtension
536 (nssCert,
537 SEC_OID_X509_POLICY_CONSTRAINTS,
538 &encodedCertPolicyConstraints);
540 if (rv == SECSuccess) {
542 policyConstraints.explicitPolicySkipCerts.data =
543 (unsigned char *)&explicitPolicySkipCerts;
544 policyConstraints.inhibitMappingSkipCerts.data =
545 (unsigned char *)&inhibitMappingSkipCerts;
547 /* translate DER to CERTCertificatePolicyConstraints */
548 rv = CERT_DecodePolicyConstraintsExtension
549 (&policyConstraints, &encodedCertPolicyConstraints);
551 PKIX_CERT_DEBUG("\t\tCalling PORT_Free).\n");
552 PORT_Free(encodedCertPolicyConstraints.data);
554 if (rv != SECSuccess) {
555 PKIX_ERROR
556 (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
560 *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
561 *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;
563 cleanup:
565 PKIX_RETURN(CERT);
569 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
570 * DESCRIPTION:
572 * Decodes the contents of the InhibitAnyPolicy extension in the
573 * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
574 * which is stored at the address "pSkipCerts". If this certificate does
575 * not have an InhibitAnyPolicy extension, -1 will be stored.
577 * PARAMETERS
578 * "nssCert"
579 * Address of the Cert data whose InhibitAnyPolicy extension is to be
580 * processed. Must be non-NULL.
581 * "pSkipCerts"
582 * Address where the SkipCert value from the InhibitAnyPolicy extension
583 * will be stored. Must be non-NULL.
584 * "plContext"
585 * Platform-specific context pointer.
586 * THREAD SAFETY:
587 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
588 * RETURNS:
589 * Returns NULL if the function succeeds.
590 * Returns a Cert Error if the function fails in a non-fatal way.
591 * Returns a Fatal Error if the function fails in an unrecoverable way.
593 PKIX_Error *
594 pkix_pl_Cert_DecodeInhibitAnyPolicy(
595 CERTCertificate *nssCert,
596 PKIX_Int32 *pSkipCerts,
597 void *plContext)
599 CERTCertificateInhibitAny inhibitAny;
600 SECStatus rv;
601 SECItem encodedCertInhibitAny;
602 PKIX_Int32 skipCerts = -1;
604 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
605 PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);
607 /* get InhibitAny as a SECItem */
608 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
609 rv = CERT_FindCertExtension
610 (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);
612 if (rv == SECSuccess) {
613 inhibitAny.inhibitAnySkipCerts.data =
614 (unsigned char *)&skipCerts;
616 /* translate DER to CERTCertificateInhibitAny */
617 rv = CERT_DecodeInhibitAnyExtension
618 (&inhibitAny, &encodedCertInhibitAny);
620 PKIX_CERT_DEBUG("\t\tCalling PORT_Free).\n");
621 PORT_Free(encodedCertInhibitAny.data);
623 if (rv != SECSuccess) {
624 PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
628 *pSkipCerts = skipCerts;
630 cleanup:
632 PKIX_RETURN(CERT);
636 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
637 * DESCRIPTION:
639 * Retrieves the Subject Alternative Names of the certificate specified by
640 * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
641 * Name extension is not present, NULL is returned at "pNssSubjAltNames".
642 * If the Subject Alternative Names has not been previously decoded, it is
643 * decoded here with lock on the "cert" unless the flag "hasLock" indicates
644 * the lock had been obtained at a higher call level.
646 * PARAMETERS
647 * "cert"
648 * Address of the certificate whose Subject Alternative Names extensions
649 * is retrieved. Must be non-NULL.
650 * "hasLock"
651 * Boolean indicates caller has acquired a lock.
652 * Must be non-NULL.
653 * "pNssSubjAltNames"
654 * Address where the returned Subject Alternative Names will be stored.
655 * Must be non-NULL.
656 * "plContext"
657 * Platform-specific context pointer.
658 * THREAD SAFETY:
659 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
660 * RETURNS:
661 * Returns NULL if the function succeeds.
662 * Returns a Cert Error if the function fails in a non-fatal way.
663 * Returns a Fatal Error if the function fails in an unrecoverable way.
665 static PKIX_Error *
666 pkix_pl_Cert_GetNssSubjectAltNames(
667 PKIX_PL_Cert *cert,
668 PKIX_Boolean hasLock,
669 CERTGeneralName **pNssSubjAltNames,
670 void *plContext)
672 CERTCertificate *nssCert = NULL;
673 CERTGeneralName *nssOriginalAltName = NULL;
674 PLArenaPool *arena = NULL;
675 SECItem altNameExtension = {siBuffer, NULL, 0};
676 SECStatus rv = SECFailure;
678 PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
679 PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);
681 nssCert = cert->nssCert;
683 if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
685 if (!hasLock) {
686 PKIX_OBJECT_LOCK(cert);
689 if ((cert->nssSubjAltNames == NULL) &&
690 (!cert->subjAltNamesAbsent)){
692 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
693 (nssCert,
694 SEC_OID_X509_SUBJECT_ALT_NAME,
695 &altNameExtension));
697 if (rv != SECSuccess) {
698 *pNssSubjAltNames = NULL;
699 cert->subjAltNamesAbsent = PKIX_TRUE;
700 goto cleanup;
703 if (cert->arenaNameConstraints == NULL) {
704 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
705 (DER_DEFAULT_CHUNKSIZE));
707 if (arena == NULL) {
708 PKIX_ERROR(PKIX_PORTNEWARENAFAILED);
710 cert->arenaNameConstraints = arena;
713 PKIX_PL_NSSCALLRV
714 (CERT,
715 nssOriginalAltName,
716 (CERTGeneralName *) CERT_DecodeAltNameExtension,
717 (cert->arenaNameConstraints, &altNameExtension));
719 PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));
721 if (nssOriginalAltName == NULL) {
722 PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
724 cert->nssSubjAltNames = nssOriginalAltName;
728 if (!hasLock) {
729 PKIX_OBJECT_UNLOCK(cert);
733 *pNssSubjAltNames = cert->nssSubjAltNames;
735 cleanup:
736 if (objectIsLocked == PKIX_TRUE) {
737 PKIX_OBJECT_UNLOCK(lockedObject);
740 PKIX_RETURN(CERT);
744 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
745 * DESCRIPTION:
747 * For each of the ON bit in "requiredExtendedKeyUsages" that represents its
748 * SECCertUsageEnum type, this function checks "cert"'s certType (extended
749 * key usage) and key usage with what is required for SECCertUsageEnum type.
751 * PARAMETERS
752 * "cert"
753 * Address of the certificate whose Extended Key Usage extensions
754 * is retrieved. Must be non-NULL.
755 * "requiredExtendedKeyUsages"
756 * An unsigned integer, its bit location is ON based on the required key
757 * usage value representing in SECCertUsageEnum.
758 * "pPass"
759 * Address where the return value, indicating key usage check passed, is
760 * stored. Must be non-NULL.
761 * "plContext"
762 * Platform-specific context pointer.
763 * THREAD SAFETY:
764 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
765 * RETURNS:
766 * Returns NULL if the function succeeds.
767 * Returns a Cert Error if the function fails in a non-fatal way.
768 * Returns a Fatal Error if the function fails in an unrecoverable way.
770 PKIX_Error *
771 pkix_pl_Cert_CheckExtendedKeyUsage(
772 PKIX_PL_Cert *cert,
773 PKIX_UInt32 requiredExtendedKeyUsages,
774 PKIX_Boolean *pPass,
775 void *plContext)
777 PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
778 PKIX_UInt32 certType = 0;
779 PKIX_UInt32 requiredKeyUsage = 0;
780 PKIX_UInt32 requiredCertType = 0;
781 PKIX_UInt32 requiredExtendedKeyUsage = 0;
782 PKIX_UInt32 i;
783 PKIX_Boolean isCA = PKIX_FALSE;
784 SECStatus rv = SECFailure;
786 PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
787 PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);
789 *pPass = PKIX_FALSE;
791 PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
792 cert_GetCertType(cert->nssCert);
793 certType = cert->nssCert->nsCertType;
795 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
796 (cert,
797 &basicConstraints,
798 plContext),
799 PKIX_CERTGETBASICCONSTRAINTFAILED);
801 if (basicConstraints != NULL) {
802 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
803 (basicConstraints, &isCA, plContext),
804 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
807 i = 0;
808 while (requiredExtendedKeyUsages != 0) {
810 /* Find the bit location of the right-most non-zero bit */
811 while (requiredExtendedKeyUsages != 0) {
812 if (((1 << i) & requiredExtendedKeyUsages) != 0) {
813 requiredExtendedKeyUsage = 1 << i;
814 break;
816 i++;
818 requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;
820 requiredExtendedKeyUsage = i;
822 PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
823 (requiredExtendedKeyUsage,
824 isCA,
825 &requiredKeyUsage,
826 &requiredCertType));
828 if (!(certType & requiredCertType)) {
829 goto cleanup;
832 PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
833 (cert->nssCert, requiredKeyUsage));
834 if (rv != SECSuccess) {
835 goto cleanup;
837 i++;
841 *pPass = PKIX_TRUE;
843 cleanup:
845 PKIX_DECREF(basicConstraints);
847 PKIX_RETURN(CERT);
851 * FUNCTION: pkix_pl_Cert_ToString_Helper
852 * DESCRIPTION:
854 * Helper function that creates a string representation of the Cert pointed
855 * to by "cert" and stores it at "pString", where the value of
856 * "partialString" determines whether a full or partial representation of
857 * the Cert is stored.
859 * PARAMETERS
860 * "cert"
861 * Address of Cert whose string representation is desired.
862 * Must be non-NULL.
863 * "partialString"
864 * Boolean indicating whether a partial Cert representation is desired.
865 * "pString"
866 * Address where object pointer will be stored. Must be non-NULL.
867 * "plContext"
868 * Platform-specific context pointer.
869 * THREAD SAFETY:
870 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
871 * RETURNS:
872 * Returns NULL if the function succeeds.
873 * Returns a Cert Error if the function fails in a non-fatal way.
874 * Returns a Fatal Error if the function fails in an unrecoverable way.
876 PKIX_Error *
877 pkix_pl_Cert_ToString_Helper(
878 PKIX_PL_Cert *cert,
879 PKIX_Boolean partialString,
880 PKIX_PL_String **pString,
881 void *plContext)
883 PKIX_PL_String *certString = NULL;
884 char *asciiFormat = NULL;
885 PKIX_PL_String *formatString = NULL;
886 PKIX_UInt32 certVersion;
887 PKIX_PL_BigInt *certSN = NULL;
888 PKIX_PL_String *certSNString = NULL;
889 PKIX_PL_X500Name *certIssuer = NULL;
890 PKIX_PL_String *certIssuerString = NULL;
891 PKIX_PL_X500Name *certSubject = NULL;
892 PKIX_PL_String *certSubjectString = NULL;
893 PKIX_PL_String *notBeforeString = NULL;
894 PKIX_PL_String *notAfterString = NULL;
895 PKIX_List *subjAltNames = NULL;
896 PKIX_PL_String *subjAltNamesString = NULL;
897 PKIX_PL_ByteArray *authKeyId = NULL;
898 PKIX_PL_String *authKeyIdString = NULL;
899 PKIX_PL_ByteArray *subjKeyId = NULL;
900 PKIX_PL_String *subjKeyIdString = NULL;
901 PKIX_PL_PublicKey *nssPubKey = NULL;
902 PKIX_PL_String *nssPubKeyString = NULL;
903 PKIX_List *critExtOIDs = NULL;
904 PKIX_PL_String *critExtOIDsString = NULL;
905 PKIX_List *extKeyUsages = NULL;
906 PKIX_PL_String *extKeyUsagesString = NULL;
907 PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
908 PKIX_PL_String *certBasicConstraintsString = NULL;
909 PKIX_List *policyInfo = NULL;
910 PKIX_PL_String *certPolicyInfoString = NULL;
911 PKIX_List *certPolicyMappings = NULL;
912 PKIX_PL_String *certPolicyMappingsString = NULL;
913 PKIX_Int32 certExplicitPolicy = 0;
914 PKIX_Int32 certInhibitMapping = 0;
915 PKIX_Int32 certInhibitAnyPolicy = 0;
916 PKIX_PL_CertNameConstraints *nameConstraints = NULL;
917 PKIX_PL_String *nameConstraintsString = NULL;
918 PKIX_List *authorityInfoAccess = NULL;
919 PKIX_PL_String *authorityInfoAccessString = NULL;
920 PKIX_List *subjectInfoAccess = NULL;
921 PKIX_PL_String *subjectInfoAccessString = NULL;
923 PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
924 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);
927 * XXX Add to this format as certificate components are developed.
930 if (partialString){
931 asciiFormat =
932 "\t[Issuer: %s\n"
933 "\t Subject: %s]";
934 } else {
935 asciiFormat =
936 "[\n"
937 "\tVersion: v%d\n"
938 "\tSerialNumber: %s\n"
939 "\tIssuer: %s\n"
940 "\tSubject: %s\n"
941 "\tValidity: [From: %s\n"
942 "\t To: %s]\n"
943 "\tSubjectAltNames: %s\n"
944 "\tAuthorityKeyId: %s\n"
945 "\tSubjectKeyId: %s\n"
946 "\tSubjPubKeyAlgId: %s\n"
947 "\tCritExtOIDs: %s\n"
948 "\tExtKeyUsages: %s\n"
949 "\tBasicConstraint: %s\n"
950 "\tCertPolicyInfo: %s\n"
951 "\tPolicyMappings: %s\n"
952 "\tExplicitPolicy: %d\n"
953 "\tInhibitMapping: %d\n"
954 "\tInhibitAnyPolicy:%d\n"
955 "\tNameConstraints: %s\n"
956 "\tAuthorityInfoAccess: %s\n"
957 "\tSubjectInfoAccess: %s\n"
958 "\tCacheFlag: %d\n"
959 "]\n";
964 PKIX_CHECK(PKIX_PL_String_Create
965 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
966 PKIX_STRINGCREATEFAILED);
968 /* Issuer */
969 PKIX_CHECK(PKIX_PL_Cert_GetIssuer
970 (cert, &certIssuer, plContext),
971 PKIX_CERTGETISSUERFAILED);
973 PKIX_CHECK(PKIX_PL_Object_ToString
974 ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
975 PKIX_X500NAMETOSTRINGFAILED);
977 /* Subject */
978 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
979 PKIX_CERTGETSUBJECTFAILED);
981 PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
982 PKIX_X500NAMETOSTRINGFAILED);
984 if (partialString){
985 PKIX_CHECK(PKIX_PL_Sprintf
986 (&certString,
987 plContext,
988 formatString,
989 certIssuerString,
990 certSubjectString),
991 PKIX_SPRINTFFAILED);
993 *pString = certString;
994 goto cleanup;
997 /* Version */
998 PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
999 PKIX_CERTGETVERSIONFAILED);
1001 /* SerialNumber */
1002 PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
1003 PKIX_CERTGETSERIALNUMBERFAILED);
1005 PKIX_CHECK(PKIX_PL_Object_ToString
1006 ((PKIX_PL_Object *)certSN, &certSNString, plContext),
1007 PKIX_BIGINTTOSTRINGFAILED);
1009 /* Validity: NotBefore */
1010 PKIX_CHECK(pkix_pl_Date_ToString_Helper
1011 (&(cert->nssCert->validity.notBefore),
1012 &notBeforeString,
1013 plContext),
1014 PKIX_DATETOSTRINGHELPERFAILED);
1016 /* Validity: NotAfter */
1017 PKIX_CHECK(pkix_pl_Date_ToString_Helper
1018 (&(cert->nssCert->validity.notAfter),
1019 &notAfterString,
1020 plContext),
1021 PKIX_DATETOSTRINGHELPERFAILED);
1023 /* SubjectAltNames */
1024 PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
1025 (cert, &subjAltNames, plContext),
1026 PKIX_CERTGETSUBJECTALTNAMESFAILED);
1028 PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
1029 PKIX_LISTTOSTRINGFAILED);
1031 /* AuthorityKeyIdentifier */
1032 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
1033 (cert, &authKeyId, plContext),
1034 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
1036 PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
1037 PKIX_BYTEARRAYTOSTRINGFAILED);
1039 /* SubjectKeyIdentifier */
1040 PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
1041 (cert, &subjKeyId, plContext),
1042 PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
1044 PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
1045 PKIX_BYTEARRAYTOSTRINGFAILED);
1047 /* SubjectPublicKey */
1048 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
1049 (cert, &nssPubKey, plContext),
1050 PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
1052 PKIX_CHECK(PKIX_PL_Object_ToString
1053 ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
1054 PKIX_PUBLICKEYTOSTRINGFAILED);
1056 /* CriticalExtensionOIDs */
1057 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
1058 (cert, &critExtOIDs, plContext),
1059 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
1061 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
1062 PKIX_LISTTOSTRINGFAILED);
1064 /* ExtendedKeyUsages */
1065 PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
1066 (cert, &extKeyUsages, plContext),
1067 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
1069 PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
1070 PKIX_LISTTOSTRINGFAILED);
1072 /* CertBasicConstraints */
1073 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
1074 (cert, &basicConstraint, plContext),
1075 PKIX_CERTGETBASICCONSTRAINTSFAILED);
1077 PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
1078 PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);
1080 /* CertPolicyInfo */
1081 PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
1082 (cert, &policyInfo, plContext),
1083 PKIX_CERTGETPOLICYINFORMATIONFAILED);
1085 PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
1086 PKIX_LISTTOSTRINGFAILED);
1088 /* Advanced Policies */
1089 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
1090 (cert, &certPolicyMappings, plContext),
1091 PKIX_CERTGETPOLICYMAPPINGSFAILED);
1093 PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
1094 PKIX_LISTTOSTRINGFAILED);
1096 PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
1097 (cert, &certExplicitPolicy, plContext),
1098 PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
1100 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
1101 (cert, &certInhibitMapping, plContext),
1102 PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
1104 PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
1105 (cert, &certInhibitAnyPolicy, plContext),
1106 PKIX_CERTGETINHIBITANYPOLICYFAILED);
1108 /* Name Constraints */
1109 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
1110 (cert, &nameConstraints, plContext),
1111 PKIX_CERTGETNAMECONSTRAINTSFAILED);
1113 PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
1114 PKIX_LISTTOSTRINGFAILED);
1116 /* Authority Information Access */
1117 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
1118 (cert, &authorityInfoAccess, plContext),
1119 PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
1121 PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
1122 PKIX_LISTTOSTRINGFAILED);
1124 /* Subject Information Access */
1125 PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
1126 (cert, &subjectInfoAccess, plContext),
1127 PKIX_CERTGETSUBJECTINFOACCESSFAILED);
1129 PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
1130 PKIX_LISTTOSTRINGFAILED);
1132 PKIX_CHECK(PKIX_PL_Sprintf
1133 (&certString,
1134 plContext,
1135 formatString,
1136 certVersion + 1,
1137 certSNString,
1138 certIssuerString,
1139 certSubjectString,
1140 notBeforeString,
1141 notAfterString,
1142 subjAltNamesString,
1143 authKeyIdString,
1144 subjKeyIdString,
1145 nssPubKeyString,
1146 critExtOIDsString,
1147 extKeyUsagesString,
1148 certBasicConstraintsString,
1149 certPolicyInfoString,
1150 certPolicyMappingsString,
1151 certExplicitPolicy, /* an Int32, not a String */
1152 certInhibitMapping, /* an Int32, not a String */
1153 certInhibitAnyPolicy, /* an Int32, not a String */
1154 nameConstraintsString,
1155 authorityInfoAccessString,
1156 subjectInfoAccessString,
1157 cert->cacheFlag), /* a boolean */
1158 PKIX_SPRINTFFAILED);
1160 *pString = certString;
1162 cleanup:
1164 PKIX_DECREF(certSN);
1165 PKIX_DECREF(certSNString);
1166 PKIX_DECREF(certIssuer);
1167 PKIX_DECREF(certIssuerString);
1168 PKIX_DECREF(certSubject);
1169 PKIX_DECREF(certSubjectString);
1170 PKIX_DECREF(notBeforeString);
1171 PKIX_DECREF(notAfterString);
1172 PKIX_DECREF(subjAltNames);
1173 PKIX_DECREF(subjAltNamesString);
1174 PKIX_DECREF(authKeyId);
1175 PKIX_DECREF(authKeyIdString);
1176 PKIX_DECREF(subjKeyId);
1177 PKIX_DECREF(subjKeyIdString);
1178 PKIX_DECREF(nssPubKey);
1179 PKIX_DECREF(nssPubKeyString);
1180 PKIX_DECREF(critExtOIDs);
1181 PKIX_DECREF(critExtOIDsString);
1182 PKIX_DECREF(extKeyUsages);
1183 PKIX_DECREF(extKeyUsagesString);
1184 PKIX_DECREF(basicConstraint);
1185 PKIX_DECREF(certBasicConstraintsString);
1186 PKIX_DECREF(policyInfo);
1187 PKIX_DECREF(certPolicyInfoString);
1188 PKIX_DECREF(certPolicyMappings);
1189 PKIX_DECREF(certPolicyMappingsString);
1190 PKIX_DECREF(nameConstraints);
1191 PKIX_DECREF(nameConstraintsString);
1192 PKIX_DECREF(authorityInfoAccess);
1193 PKIX_DECREF(authorityInfoAccessString);
1194 PKIX_DECREF(subjectInfoAccess);
1195 PKIX_DECREF(subjectInfoAccessString);
1196 PKIX_DECREF(formatString);
1198 PKIX_RETURN(CERT);
1202 * FUNCTION: pkix_pl_Cert_Destroy
1203 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
1205 static PKIX_Error *
1206 pkix_pl_Cert_Destroy(
1207 PKIX_PL_Object *object,
1208 void *plContext)
1210 PKIX_PL_Cert *cert = NULL;
1212 PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
1213 PKIX_NULLCHECK_ONE(object);
1215 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1216 PKIX_OBJECTNOTCERT);
1218 cert = (PKIX_PL_Cert*)object;
1220 PKIX_DECREF(cert->subject);
1221 PKIX_DECREF(cert->issuer);
1222 PKIX_DECREF(cert->subjAltNames);
1223 PKIX_DECREF(cert->publicKeyAlgId);
1224 PKIX_DECREF(cert->publicKey);
1225 PKIX_DECREF(cert->serialNumber);
1226 PKIX_DECREF(cert->critExtOids);
1227 PKIX_DECREF(cert->authKeyId);
1228 PKIX_DECREF(cert->subjKeyId);
1229 PKIX_DECREF(cert->extKeyUsages);
1230 PKIX_DECREF(cert->certBasicConstraints);
1231 PKIX_DECREF(cert->certPolicyInfos);
1232 PKIX_DECREF(cert->certPolicyMappings);
1233 PKIX_DECREF(cert->nameConstraints);
1234 PKIX_DECREF(cert->store);
1235 PKIX_DECREF(cert->authorityInfoAccess);
1236 PKIX_DECREF(cert->subjectInfoAccess);
1238 if (cert->arenaNameConstraints){
1239 /* This arena was allocated for SubjectAltNames */
1240 PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
1241 (cert->arenaNameConstraints, PR_FALSE));
1243 cert->arenaNameConstraints = NULL;
1244 cert->nssSubjAltNames = NULL;
1247 PKIX_PL_NSSCALL(CERT, CERT_DestroyCertificate, (cert->nssCert));
1249 cert->nssCert = NULL;
1251 cleanup:
1253 PKIX_RETURN(CERT);
1257 * FUNCTION: pkix_pl_Cert_ToString
1258 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
1260 static PKIX_Error *
1261 pkix_pl_Cert_ToString(
1262 PKIX_PL_Object *object,
1263 PKIX_PL_String **pString,
1264 void *plContext)
1266 PKIX_PL_String *certString = NULL;
1267 PKIX_PL_Cert *pkixCert = NULL;
1269 PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
1270 PKIX_NULLCHECK_TWO(object, pString);
1272 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1273 PKIX_OBJECTNOTCERT);
1275 pkixCert = (PKIX_PL_Cert *)object;
1277 PKIX_CHECK(pkix_pl_Cert_ToString_Helper
1278 (pkixCert, PKIX_FALSE, &certString, plContext),
1279 PKIX_CERTTOSTRINGHELPERFAILED);
1281 *pString = certString;
1283 cleanup:
1285 PKIX_RETURN(CERT);
1289 * FUNCTION: pkix_pl_Cert_Hashcode
1290 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
1292 static PKIX_Error *
1293 pkix_pl_Cert_Hashcode(
1294 PKIX_PL_Object *object,
1295 PKIX_UInt32 *pHashcode,
1296 void *plContext)
1298 PKIX_PL_Cert *pkixCert = NULL;
1299 CERTCertificate *nssCert = NULL;
1300 unsigned char *derBytes = NULL;
1301 PKIX_UInt32 derLength;
1302 PKIX_UInt32 certHash;
1304 PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
1305 PKIX_NULLCHECK_TWO(object, pHashcode);
1307 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1308 PKIX_OBJECTNOTCERT);
1310 pkixCert = (PKIX_PL_Cert *)object;
1312 nssCert = pkixCert->nssCert;
1313 derBytes = (nssCert->derCert).data;
1314 derLength = (nssCert->derCert).len;
1316 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
1317 PKIX_HASHFAILED);
1319 *pHashcode = certHash;
1321 cleanup:
1323 PKIX_RETURN(CERT);
1328 * FUNCTION: pkix_pl_Cert_Equals
1329 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
1331 static PKIX_Error *
1332 pkix_pl_Cert_Equals(
1333 PKIX_PL_Object *firstObject,
1334 PKIX_PL_Object *secondObject,
1335 PKIX_Boolean *pResult,
1336 void *plContext)
1338 CERTCertificate *firstCert = NULL;
1339 CERTCertificate *secondCert = NULL;
1340 PKIX_UInt32 secondType;
1341 PKIX_Boolean cmpResult;
1343 PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
1344 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
1346 /* test that firstObject is a Cert */
1347 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
1348 PKIX_FIRSTOBJECTNOTCERT);
1351 * Since we know firstObject is a Cert, if both references are
1352 * identical, they must be equal
1354 if (firstObject == secondObject){
1355 *pResult = PKIX_TRUE;
1356 goto cleanup;
1360 * If secondObject isn't a Cert, we don't throw an error.
1361 * We simply return a Boolean result of FALSE
1363 *pResult = PKIX_FALSE;
1364 PKIX_CHECK(PKIX_PL_Object_GetType
1365 (secondObject, &secondType, plContext),
1366 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
1367 if (secondType != PKIX_CERT_TYPE) goto cleanup;
1369 firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
1370 secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;
1372 PKIX_NULLCHECK_TWO(firstCert, secondCert);
1374 /* CERT_CompareCerts does byte comparison on DER encodings of certs */
1375 PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
1376 cmpResult = CERT_CompareCerts(firstCert, secondCert);
1378 *pResult = cmpResult;
1380 cleanup:
1382 PKIX_RETURN(CERT);
1386 * FUNCTION: pkix_pl_Cert_RegisterSelf
1387 * DESCRIPTION:
1388 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
1389 * THREAD SAFETY:
1390 * Not Thread Safe - for performance and complexity reasons
1392 * Since this function is only called by PKIX_PL_Initialize, which should
1393 * only be called once, it is acceptable that this function is not
1394 * thread-safe.
1396 PKIX_Error *
1397 pkix_pl_Cert_RegisterSelf(void *plContext)
1400 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1401 pkix_ClassTable_Entry entry;
1403 PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");
1405 entry.description = "Cert";
1406 entry.destructor = pkix_pl_Cert_Destroy;
1407 entry.equalsFunction = pkix_pl_Cert_Equals;
1408 entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
1409 entry.toStringFunction = pkix_pl_Cert_ToString;
1410 entry.comparator = NULL;
1411 entry.duplicateFunction = pkix_duplicateImmutable;
1413 systemClasses[PKIX_CERT_TYPE] = entry;
1415 PKIX_RETURN(CERT);
1419 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
1420 * DESCRIPTION:
1422 * Creates a new certificate using the CERTCertificate pointed to by "nssCert"
1423 * and stores it at "pCert". Once created, a Cert is immutable.
1425 * This function is primarily used as a convenience function for the
1426 * performance tests that have easy access to a CERTCertificate.
1428 * PARAMETERS:
1429 * "nssCert"
1430 * Address of CERTCertificate representing the NSS certificate.
1431 * Must be non-NULL.
1432 * "pCert"
1433 * Address where object pointer will be stored. Must be non-NULL.
1434 * "plContext"
1435 * Platform-specific context pointer.
1436 * THREAD SAFETY:
1437 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1438 * RETURNS:
1439 * Returns NULL if the function succeeds.
1440 * Returns a Cert Error if the function fails in a non-fatal way.
1441 * Returns a Fatal Error if the function fails in an unrecoverable way.
1443 PKIX_Error *
1444 pkix_pl_Cert_CreateWithNSSCert(
1445 CERTCertificate *nssCert,
1446 PKIX_PL_Cert **pCert,
1447 void *plContext)
1449 PKIX_PL_Cert *cert = NULL;
1451 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNSSCert");
1452 PKIX_NULLCHECK_TWO(pCert, nssCert);
1454 /* create a PKIX_PL_Cert object */
1455 PKIX_CHECK(PKIX_PL_Object_Alloc
1456 (PKIX_CERT_TYPE,
1457 sizeof (PKIX_PL_Cert),
1458 (PKIX_PL_Object **)&cert,
1459 plContext),
1460 PKIX_COULDNOTCREATEOBJECT);
1462 /* populate the nssCert field */
1463 cert->nssCert = nssCert;
1465 /* initialize remaining fields */
1467 * Fields ending with Absent are initialized to PKIX_FALSE so that the
1468 * first time we need the value we will look for it. If we find it is
1469 * actually absent, the flag will at that time be set to PKIX_TRUE to
1470 * prevent searching for it later.
1471 * Fields ending with Processed are those where a value is defined
1472 * for the Absent case, and a value of zero is possible. When the
1473 * flag is still true we have to look for the field, set the default
1474 * value if necessary, and set the Processed flag to PKIX_TRUE.
1476 cert->subject = NULL;
1477 cert->issuer = NULL;
1478 cert->subjAltNames = NULL;
1479 cert->subjAltNamesAbsent = PKIX_FALSE;
1480 cert->publicKeyAlgId = NULL;
1481 cert->publicKey = NULL;
1482 cert->serialNumber = NULL;
1483 cert->critExtOids = NULL;
1484 cert->subjKeyId = NULL;
1485 cert->subjKeyIdAbsent = PKIX_FALSE;
1486 cert->authKeyId = NULL;
1487 cert->authKeyIdAbsent = PKIX_FALSE;
1488 cert->extKeyUsages = NULL;
1489 cert->extKeyUsagesAbsent = PKIX_FALSE;
1490 cert->certBasicConstraints = NULL;
1491 cert->basicConstraintsAbsent = PKIX_FALSE;
1492 cert->certPolicyInfos = NULL;
1493 cert->policyInfoAbsent = PKIX_FALSE;
1494 cert->policyMappingsAbsent = PKIX_FALSE;
1495 cert->certPolicyMappings = NULL;
1496 cert->policyConstraintsProcessed = PKIX_FALSE;
1497 cert->policyConstraintsExplicitPolicySkipCerts = 0;
1498 cert->policyConstraintsInhibitMappingSkipCerts = 0;
1499 cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
1500 cert->inhibitAnySkipCerts = 0;
1501 cert->nameConstraints = NULL;
1502 cert->nameConstraintsAbsent = PKIX_FALSE;
1503 cert->arenaNameConstraints = NULL;
1504 cert->nssSubjAltNames = NULL;
1505 cert->cacheFlag = PKIX_FALSE;
1506 cert->store = NULL;
1507 cert->authorityInfoAccess = NULL;
1508 cert->subjectInfoAccess = NULL;
1510 *pCert = cert;
1512 cleanup:
1514 PKIX_RETURN(CERT);
1518 * FUNCTION: pkix_pl_Cert_CreateToList
1519 * DESCRIPTION:
1521 * Creates a new certificate using the DER-encoding pointed to by "derCertItem"
1522 * and appends it to the list pointed to by "certList". If Cert creation fails,
1523 * the function returns with certList unchanged, but any decoding Error is
1524 * discarded.
1526 * PARAMETERS:
1527 * "derCertItem"
1528 * Address of SECItem containing the DER representation of a certificate.
1529 * Must be non-NULL.
1530 * "certList"
1531 * Address of List to which the Cert will be appended, if successfully
1532 * created. May be empty, but must be non-NULL.
1533 * "plContext"
1534 * Platform-specific context pointer.
1535 * THREAD SAFETY:
1536 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1537 * RETURNS:
1538 * Returns NULL if the function succeeds.
1539 * Returns a Cert Error if the function fails in a non-fatal way.
1540 * Returns a Fatal Error if the function fails in an unrecoverable way.
1542 PKIX_Error *
1543 pkix_pl_Cert_CreateToList(
1544 SECItem *derCertItem,
1545 PKIX_List *certList,
1546 void *plContext)
1548 CERTCertificate *nssCert = NULL;
1549 PKIX_PL_Cert *cert = NULL;
1551 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
1552 PKIX_NULLCHECK_TWO(derCertItem, certList);
1554 PKIX_PL_NSSCALLRV(CERT, nssCert, CERT_DecodeDERCertificate,
1555 (derCertItem, PR_TRUE, NULL));
1557 if (nssCert) {
1558 PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert
1559 (nssCert, &cert, plContext),
1560 PKIX_CERTCREATEWITHNSSCERTFAILED);
1562 /* skip bad certs and append good ones */
1563 if (!PKIX_ERROR_RECEIVED) {
1564 PKIX_CHECK(PKIX_List_AppendItem
1565 (certList, (PKIX_PL_Object *) cert, plContext),
1566 PKIX_LISTAPPENDITEMFAILED);
1569 PKIX_DECREF(cert);
1572 cleanup:
1574 PKIX_DECREF(cert);
1576 PKIX_RETURN(CERT);
1579 /* --Public-Functions------------------------------------------------------- */
1582 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
1583 * XXX We may want to cache the cert after parsing it, so it can be reused
1584 * XXX Are the NSS/NSPR functions thread safe
1586 PKIX_Error *
1587 PKIX_PL_Cert_Create(
1588 PKIX_PL_ByteArray *byteArray,
1589 PKIX_PL_Cert **pCert,
1590 void *plContext)
1592 CERTCertificate *nssCert = NULL;
1593 SECItem *derCertItem = NULL;
1594 void *derBytes = NULL;
1595 PKIX_UInt32 derLength;
1596 PKIX_Boolean copyDER;
1597 PKIX_PL_Cert *cert = NULL;
1599 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
1600 PKIX_NULLCHECK_TWO(pCert, byteArray);
1602 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
1603 (byteArray, &derBytes, plContext),
1604 PKIX_BYTEARRAYGETPOINTERFAILED);
1606 PKIX_CHECK(PKIX_PL_ByteArray_GetLength
1607 (byteArray, &derLength, plContext),
1608 PKIX_BYTEARRAYGETLENGTHFAILED);
1610 PKIX_CERT_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
1611 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
1612 if (derCertItem == NULL){
1613 PKIX_ERROR(PKIX_UNABLETOALLOCATESECITEM);
1616 PKIX_CERT_DEBUG("\t\tCalling PORT_Memcpy).\n");
1617 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);
1620 * setting copyDER to true forces NSS to make its own copy of the DER,
1621 * allowing us to free our copy without worrying about whether NSS
1622 * is still using it
1624 copyDER = PKIX_TRUE;
1625 PKIX_CERT_DEBUG("\t\tCalling CERT_DecodeDERCertificate).\n");
1626 nssCert = CERT_DecodeDERCertificate(derCertItem, copyDER, NULL);
1627 if (!nssCert){
1628 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
1631 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
1632 (nssCert, &cert, plContext),
1633 PKIX_CERTCREATEWITHNSSCERTFAILED);
1635 *pCert = cert;
1637 cleanup:
1638 if (derCertItem){
1639 PKIX_CERT_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
1640 SECITEM_FreeItem(derCertItem, PKIX_TRUE);
1643 if (nssCert && PKIX_ERROR_RECEIVED){
1644 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
1645 CERT_DestroyCertificate(nssCert);
1646 nssCert = NULL;
1649 PKIX_FREE(derBytes);
1651 PKIX_RETURN(CERT);
1656 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
1658 PKIX_Error *
1659 PKIX_PL_Cert_GetVersion(
1660 PKIX_PL_Cert *cert,
1661 PKIX_UInt32 *pVersion,
1662 void *plContext)
1664 CERTCertificate *nssCert = NULL;
1665 PKIX_UInt32 myVersion;
1667 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
1668 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);
1670 nssCert = cert->nssCert;
1671 myVersion = *(nssCert->version.data);
1673 if (myVersion > 2){
1674 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
1677 *pVersion = myVersion;
1679 cleanup:
1681 PKIX_RETURN(CERT);
1685 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
1687 PKIX_Error *
1688 PKIX_PL_Cert_GetSerialNumber(
1689 PKIX_PL_Cert *cert,
1690 PKIX_PL_BigInt **pSerialNumber,
1691 void *plContext)
1693 CERTCertificate *nssCert = NULL;
1694 SECItem serialNumItem;
1695 PKIX_PL_BigInt *serialNumber = NULL;
1696 char *bytes = NULL;
1697 PKIX_UInt32 length;
1699 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
1700 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);
1702 if (cert->serialNumber == NULL){
1704 PKIX_OBJECT_LOCK(cert);
1706 if (cert->serialNumber == NULL){
1708 nssCert = cert->nssCert;
1709 serialNumItem = nssCert->serialNumber;
1711 length = serialNumItem.len;
1712 bytes = (char *)serialNumItem.data;
1714 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
1715 (bytes, length, &serialNumber, plContext),
1716 PKIX_BIGINTCREATEWITHBYTESFAILED);
1718 /* save a cached copy in case it is asked for again */
1719 cert->serialNumber = serialNumber;
1722 PKIX_OBJECT_UNLOCK(cert);
1725 PKIX_INCREF(cert->serialNumber);
1726 *pSerialNumber = cert->serialNumber;
1728 cleanup:
1729 if (objectIsLocked == PKIX_TRUE) {
1730 PKIX_OBJECT_UNLOCK(lockedObject);
1734 PKIX_RETURN(CERT);
1738 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
1740 PKIX_Error *
1741 PKIX_PL_Cert_GetSubject(
1742 PKIX_PL_Cert *cert,
1743 PKIX_PL_X500Name **pCertSubject,
1744 void *plContext)
1746 PKIX_PL_X500Name *pkixSubject = NULL;
1747 CERTCertificate *nssCert = NULL;
1748 char *utf8Subject = NULL;
1750 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
1751 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);
1753 /* if we don't have a cached copy from before, we create one */
1754 if (cert->subject == NULL){
1756 PKIX_OBJECT_LOCK(cert);
1758 if (cert->subject == NULL){
1760 nssCert = cert->nssCert;
1761 utf8Subject = nssCert->subjectName;
1763 /* if there is no subject name */
1764 if (utf8Subject == NULL) {
1766 pkixSubject = NULL;
1768 } else {
1770 PKIX_CHECK(pkix_pl_X500Name_CreateFromUtf8
1771 (utf8Subject, &pkixSubject, plContext),
1772 PKIX_X500NAMECREATEFROMUTF8FAILED);
1775 /* save a cached copy in case it is asked for again */
1776 cert->subject = pkixSubject;
1779 PKIX_OBJECT_UNLOCK(cert);
1782 PKIX_INCREF(cert->subject);
1783 *pCertSubject = cert->subject;
1785 cleanup:
1786 if (objectIsLocked == PKIX_TRUE) {
1787 PKIX_OBJECT_UNLOCK(lockedObject);
1791 PKIX_RETURN(CERT);
1796 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
1798 PKIX_Error *
1799 PKIX_PL_Cert_GetIssuer(
1800 PKIX_PL_Cert *cert,
1801 PKIX_PL_X500Name **pCertIssuer,
1802 void *plContext)
1804 PKIX_PL_X500Name *pkixIssuer = NULL;
1805 CERTCertificate *nssCert = NULL;
1806 char *utf8Issuer = NULL;
1808 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
1809 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);
1811 /* if we don't have a cached copy from before, we create one */
1812 if (cert->issuer == NULL){
1814 PKIX_OBJECT_LOCK(cert);
1816 if (cert->issuer == NULL){
1818 nssCert = cert->nssCert;
1819 utf8Issuer = nssCert->issuerName;
1821 PKIX_CHECK(pkix_pl_X500Name_CreateFromUtf8
1822 (utf8Issuer, &pkixIssuer, plContext),
1823 PKIX_X500NAMECREATEFROMUTF8FAILED);
1825 /* save a cached copy in case it is asked for again */
1826 cert->issuer = pkixIssuer;
1829 PKIX_OBJECT_UNLOCK(cert);
1832 PKIX_INCREF(cert->issuer);
1833 *pCertIssuer = cert->issuer;
1835 cleanup:
1837 PKIX_RETURN(CERT);
1842 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
1844 PKIX_Error *
1845 PKIX_PL_Cert_GetSubjectAltNames(
1846 PKIX_PL_Cert *cert,
1847 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */
1848 void *plContext)
1850 PKIX_PL_GeneralName *pkixAltName = NULL;
1851 PKIX_List *altNamesList = NULL;
1853 CERTGeneralName *nssOriginalAltName = NULL;
1854 CERTGeneralName *nssTempAltName = NULL;
1856 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
1857 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);
1859 /* if we don't have a cached copy from before, we create one */
1860 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
1862 PKIX_OBJECT_LOCK(cert);
1864 if ((cert->subjAltNames == NULL) &&
1865 (!cert->subjAltNamesAbsent)){
1867 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
1868 (cert,
1869 PKIX_TRUE,
1870 &nssOriginalAltName,
1871 plContext),
1872 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
1874 if (nssOriginalAltName == NULL) {
1875 cert->subjAltNamesAbsent = PKIX_TRUE;
1876 pSubjectAltNames = NULL;
1877 goto cleanup;
1880 nssTempAltName = nssOriginalAltName;
1882 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
1883 PKIX_LISTCREATEFAILED);
1885 do {
1886 PKIX_CHECK(pkix_pl_GeneralName_Create
1887 (nssTempAltName, &pkixAltName, plContext),
1888 PKIX_GENERALNAMECREATEFAILED);
1890 PKIX_CHECK(PKIX_List_AppendItem
1891 (altNamesList,
1892 (PKIX_PL_Object *)pkixAltName,
1893 plContext),
1894 PKIX_LISTAPPENDITEMFAILED);
1896 PKIX_DECREF(pkixAltName);
1898 PKIX_CERT_DEBUG
1899 ("\t\tCalling CERT_GetNextGeneralName).\n");
1900 nssTempAltName = CERT_GetNextGeneralName
1901 (nssTempAltName);
1903 } while (nssTempAltName != nssOriginalAltName);
1905 /* save a cached copy in case it is asked for again */
1906 cert->subjAltNames = altNamesList;
1907 PKIX_CHECK(PKIX_List_SetImmutable
1908 (cert->subjAltNames, plContext),
1909 PKIX_LISTSETIMMUTABLEFAILED);
1913 PKIX_OBJECT_UNLOCK(cert);
1916 PKIX_INCREF(cert->subjAltNames);
1918 *pSubjectAltNames = cert->subjAltNames;
1920 cleanup:
1922 PKIX_DECREF(pkixAltName);
1924 if (PKIX_ERROR_RECEIVED){
1925 PKIX_DECREF(altNamesList);
1928 PKIX_RETURN(CERT);
1932 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
1934 PKIX_Error *
1935 PKIX_PL_Cert_GetAllSubjectNames(
1936 PKIX_PL_Cert *cert,
1937 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */
1938 void *plContext)
1940 CERTGeneralName *nssOriginalSubjectName = NULL;
1941 CERTGeneralName *nssTempSubjectName = NULL;
1942 PKIX_List *allSubjectNames = NULL;
1943 PKIX_PL_GeneralName *pkixSubjectName = NULL;
1944 PRArenaPool *arena = NULL;
1946 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames");
1947 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames);
1950 if (cert->nssCert->subjectName == NULL){
1951 /* if there is no subject DN, just get altnames */
1953 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
1954 (cert,
1955 PKIX_FALSE, /* hasLock */
1956 &nssOriginalSubjectName,
1957 plContext),
1958 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
1960 } else { /* get subject DN and altnames */
1962 PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena\n");
1963 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1964 if (arena == NULL) {
1965 PKIX_ERROR(PKIX_PORTNEWARENAFAILED);
1968 /* This NSS call returns both Subject and Subject Alt Names */
1969 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
1970 nssOriginalSubjectName =
1971 CERT_GetCertificateNames(cert->nssCert, arena);
1974 if (nssOriginalSubjectName == NULL) {
1975 pAllSubjectNames = NULL;
1976 goto cleanup;
1979 nssTempSubjectName = nssOriginalSubjectName;
1981 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext),
1982 PKIX_LISTCREATEFAILED);
1984 do {
1985 PKIX_CHECK(pkix_pl_GeneralName_Create
1986 (nssTempSubjectName, &pkixSubjectName, plContext),
1987 PKIX_GENERALNAMECREATEFAILED);
1989 PKIX_CHECK(PKIX_List_AppendItem
1990 (allSubjectNames,
1991 (PKIX_PL_Object *)pkixSubjectName,
1992 plContext),
1993 PKIX_LISTAPPENDITEMFAILED);
1995 PKIX_DECREF(pkixSubjectName);
1997 PKIX_CERT_DEBUG
1998 ("\t\tCalling CERT_GetNextGeneralName).\n");
1999 nssTempSubjectName = CERT_GetNextGeneralName
2000 (nssTempSubjectName);
2001 } while (nssTempSubjectName != nssOriginalSubjectName);
2003 *pAllSubjectNames = allSubjectNames;
2005 cleanup:
2007 if (PKIX_ERROR_RECEIVED){
2008 PKIX_DECREF(allSubjectNames);
2011 if (arena){
2012 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
2013 PORT_FreeArena(arena, PR_FALSE);
2016 PKIX_DECREF(pkixSubjectName);
2018 PKIX_RETURN(CERT);
2022 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
2023 * (see comments in pkix_pl_pki.h)
2025 PKIX_Error *
2026 PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
2027 PKIX_PL_Cert *cert,
2028 PKIX_PL_OID **pSubjKeyAlgId,
2029 void *plContext)
2031 CERTCertificate *nssCert = NULL;
2032 PKIX_PL_OID *pubKeyAlgId = NULL;
2033 SECAlgorithmID algorithm;
2034 SECItem algBytes;
2035 char *asciiOID = NULL;
2037 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
2038 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId);
2040 /* if we don't have a cached copy from before, we create one */
2041 if (cert->publicKeyAlgId == NULL){
2043 PKIX_OBJECT_LOCK(cert);
2045 if (cert->publicKeyAlgId == NULL){
2047 nssCert = cert->nssCert;
2048 algorithm = nssCert->subjectPublicKeyInfo.algorithm;
2049 algBytes = algorithm.algorithm;
2051 PKIX_NULLCHECK_ONE(algBytes.data);
2052 if (algBytes.len == 0) {
2053 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0);
2056 PKIX_CHECK(pkix_pl_oidBytes2Ascii
2057 (&algBytes, &asciiOID, plContext),
2058 PKIX_OIDBYTES2ASCIIFAILED);
2060 PKIX_CHECK(PKIX_PL_OID_Create
2061 (asciiOID, &pubKeyAlgId, plContext),
2062 PKIX_OIDCREATEFAILED);
2064 /* save a cached copy in case it is asked for again */
2065 cert->publicKeyAlgId = pubKeyAlgId;
2068 PKIX_OBJECT_UNLOCK(cert);
2071 PKIX_INCREF(cert->publicKeyAlgId);
2072 *pSubjKeyAlgId = cert->publicKeyAlgId;
2074 cleanup:
2076 PKIX_FREE(asciiOID);
2078 PKIX_RETURN(CERT);
2082 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h)
2084 PKIX_Error *
2085 PKIX_PL_Cert_GetSubjectPublicKey(
2086 PKIX_PL_Cert *cert,
2087 PKIX_PL_PublicKey **pPublicKey,
2088 void *plContext)
2090 PKIX_PL_PublicKey *pkixPubKey = NULL;
2091 SECStatus rv;
2093 CERTSubjectPublicKeyInfo *from = NULL;
2094 CERTSubjectPublicKeyInfo *to = NULL;
2095 SECItem *fromItem = NULL;
2096 SECItem *toItem = NULL;
2098 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey");
2099 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey);
2101 /* if we don't have a cached copy from before, we create one */
2102 if (cert->publicKey == NULL){
2104 PKIX_OBJECT_LOCK(cert);
2106 if (cert->publicKey == NULL){
2108 /* create a PKIX_PL_PublicKey object */
2109 PKIX_CHECK(PKIX_PL_Object_Alloc
2110 (PKIX_PUBLICKEY_TYPE,
2111 sizeof (PKIX_PL_PublicKey),
2112 (PKIX_PL_Object **)&pkixPubKey,
2113 plContext),
2114 PKIX_COULDNOTCREATEOBJECT);
2116 /* initialize fields */
2117 pkixPubKey->nssSPKI = NULL;
2119 /* populate the SPKI field */
2120 PKIX_CHECK(PKIX_PL_Malloc
2121 (sizeof (CERTSubjectPublicKeyInfo),
2122 (void **)&pkixPubKey->nssSPKI,
2123 plContext),
2124 PKIX_MALLOCFAILED);
2126 to = pkixPubKey->nssSPKI;
2127 from = &cert->nssCert->subjectPublicKeyInfo;
2129 PKIX_NULLCHECK_TWO(to, from);
2131 PKIX_CERT_DEBUG
2132 ("\t\tCalling SECOID_CopyAlgorithmID).\n");
2133 rv = SECOID_CopyAlgorithmID
2134 (NULL, &to->algorithm, &from->algorithm);
2135 if (rv != SECSuccess) {
2136 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED);
2140 * NSS stores the length of subjectPublicKey in bits.
2141 * Therefore, we use that length converted to bytes
2142 * using ((length+7)>>3) before calling PORT_Memcpy
2143 * in order to avoid "read from uninitialized memory"
2144 * errors.
2147 toItem = &to->subjectPublicKey;
2148 fromItem = &from->subjectPublicKey;
2150 PKIX_NULLCHECK_TWO(toItem, fromItem);
2152 toItem->type = fromItem->type;
2154 PKIX_CERT_DEBUG("\t\tCalling PORT_ZAlloc).\n");
2155 toItem->data =
2156 (unsigned char*) PORT_ZAlloc(fromItem->len);
2157 if (!toItem->data){
2158 PKIX_ERROR(PKIX_PORTZALLOCFAILED);
2161 PKIX_CERT_DEBUG("\t\tCalling PORT_Memcpy).\n");
2162 (void) PORT_Memcpy(toItem->data,
2163 fromItem->data,
2164 (fromItem->len + 7)>>3);
2165 toItem->len = fromItem->len;
2167 /* save a cached copy in case it is asked for again */
2168 cert->publicKey = pkixPubKey;
2171 PKIX_OBJECT_UNLOCK(cert);
2174 PKIX_INCREF(cert->publicKey);
2175 *pPublicKey = cert->publicKey;
2177 cleanup:
2178 if (objectIsLocked == PKIX_TRUE) {
2179 PKIX_OBJECT_UNLOCK(lockedObject);
2183 if (PKIX_ERROR_RECEIVED){
2184 PKIX_DECREF(pkixPubKey);
2187 PKIX_RETURN(CERT);
2191 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
2192 * (see comments in pkix_pl_pki.h)
2194 PKIX_Error *
2195 PKIX_PL_Cert_GetCriticalExtensionOIDs(
2196 PKIX_PL_Cert *cert,
2197 PKIX_List **pList, /* list of PKIX_PL_OID */
2198 void *plContext)
2200 PKIX_List *oidsList = NULL;
2201 CERTCertExtension **extensions = NULL;
2202 CERTCertificate *nssCert = NULL;
2204 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs");
2205 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList);
2207 /* if we don't have a cached copy from before, we create one */
2208 if (cert->critExtOids == NULL) {
2210 PKIX_OBJECT_LOCK(cert);
2212 if (cert->critExtOids == NULL) {
2214 nssCert = cert->nssCert;
2217 * ASN.1 for Extension
2219 * Extension ::= SEQUENCE {
2220 * extnID OBJECT IDENTIFIER,
2221 * critical BOOLEAN DEFAULT FALSE,
2222 * extnValue OCTET STRING }
2226 extensions = nssCert->extensions;
2228 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
2229 (extensions, &oidsList, plContext),
2230 PKIX_GETCRITICALEXTENSIONOIDSFAILED);
2232 /* save a cached copy in case it is asked for again */
2233 cert->critExtOids = oidsList;
2236 PKIX_OBJECT_UNLOCK(cert);
2239 /* We should return a copy of the List since this list changes */
2240 PKIX_DUPLICATE(cert->critExtOids, pList, plContext,
2241 PKIX_OBJECTDUPLICATELISTFAILED);
2243 cleanup:
2244 if (objectIsLocked == PKIX_TRUE) {
2245 PKIX_OBJECT_UNLOCK(lockedObject);
2249 PKIX_RETURN(CERT);
2253 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
2254 * (see comments in pkix_pl_pki.h)
2256 PKIX_Error *
2257 PKIX_PL_Cert_GetAuthorityKeyIdentifier(
2258 PKIX_PL_Cert *cert,
2259 PKIX_PL_ByteArray **pAuthKeyId,
2260 void *plContext)
2262 PKIX_PL_ByteArray *authKeyId = NULL;
2263 CERTCertificate *nssCert = NULL;
2264 CERTAuthKeyID *authKeyIdExtension = NULL;
2265 PRArenaPool *arena = NULL;
2266 SECItem retItem;
2268 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier");
2269 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId);
2271 /* if we don't have a cached copy from before, we create one */
2272 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
2274 PKIX_OBJECT_LOCK(cert);
2276 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
2278 PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
2279 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2280 if (arena == NULL) {
2281 PKIX_ERROR(PKIX_PORTNEWARENAFAILED);
2284 nssCert = cert->nssCert;
2286 authKeyIdExtension =
2287 CERT_FindAuthKeyIDExten(arena, nssCert);
2288 if (authKeyIdExtension == NULL){
2289 cert->authKeyIdAbsent = PKIX_TRUE;
2290 *pAuthKeyId = NULL;
2291 goto cleanup;
2294 retItem = authKeyIdExtension->keyID;
2296 if (retItem.len == 0){
2297 cert->authKeyIdAbsent = PKIX_TRUE;
2298 *pAuthKeyId = NULL;
2299 goto cleanup;
2302 PKIX_CHECK(PKIX_PL_ByteArray_Create
2303 (retItem.data,
2304 retItem.len,
2305 &authKeyId,
2306 plContext),
2307 PKIX_BYTEARRAYCREATEFAILED);
2309 /* save a cached copy in case it is asked for again */
2310 cert->authKeyId = authKeyId;
2313 PKIX_OBJECT_UNLOCK(cert);
2316 PKIX_INCREF(cert->authKeyId);
2317 *pAuthKeyId = cert->authKeyId;
2319 cleanup:
2320 if (objectIsLocked == PKIX_TRUE) {
2321 PKIX_OBJECT_UNLOCK(lockedObject);
2325 if (arena){
2326 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
2327 PORT_FreeArena(arena, PR_FALSE);
2330 PKIX_RETURN(CERT);
2334 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
2335 * (see comments in pkix_pl_pki.h)
2337 PKIX_Error *
2338 PKIX_PL_Cert_GetSubjectKeyIdentifier(
2339 PKIX_PL_Cert *cert,
2340 PKIX_PL_ByteArray **pSubjKeyId,
2341 void *plContext)
2343 PKIX_PL_ByteArray *subjKeyId = NULL;
2344 CERTCertificate *nssCert = NULL;
2345 SECItem *retItem = NULL;
2346 SECStatus status;
2348 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier");
2349 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId);
2351 /* if we don't have a cached copy from before, we create one */
2352 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
2354 PKIX_OBJECT_LOCK(cert);
2356 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
2358 PKIX_CERT_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
2359 retItem = SECITEM_AllocItem(NULL, NULL, 0);
2360 if (retItem == NULL){
2361 PKIX_ERROR(PKIX_UNABLETOALLOCATESECITEM);
2364 nssCert = cert->nssCert;
2366 status = CERT_FindSubjectKeyIDExtension
2367 (nssCert, retItem);
2368 if (status != SECSuccess) {
2369 cert->subjKeyIdAbsent = PKIX_TRUE;
2370 *pSubjKeyId = NULL;
2371 goto cleanup;
2374 PKIX_CHECK(PKIX_PL_ByteArray_Create
2375 (retItem->data,
2376 retItem->len,
2377 &subjKeyId,
2378 plContext),
2379 PKIX_BYTEARRAYCREATEFAILED);
2381 /* save a cached copy in case it is asked for again */
2382 cert->subjKeyId = subjKeyId;
2385 PKIX_OBJECT_UNLOCK(cert);
2388 PKIX_INCREF(cert->subjKeyId);
2389 *pSubjKeyId = cert->subjKeyId;
2391 cleanup:
2392 if (objectIsLocked == PKIX_TRUE) {
2393 PKIX_OBJECT_UNLOCK(lockedObject);
2397 if (retItem){
2398 PKIX_CERT_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
2399 SECITEM_FreeItem(retItem, PKIX_TRUE);
2402 PKIX_RETURN(CERT);
2406 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h)
2408 PKIX_Error *
2409 PKIX_PL_Cert_GetExtendedKeyUsage(
2410 PKIX_PL_Cert *cert,
2411 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */
2412 void *plContext)
2414 CERTOidSequence *extKeyUsage = NULL;
2415 CERTCertificate *nssCert = NULL;
2416 PKIX_PL_OID *pkixOID = NULL;
2417 PKIX_List *oidsList = NULL;
2418 char *oidAscii = NULL;
2419 SECItem **oids = NULL;
2420 SECItem *oid = NULL;
2421 SECItem encodedExtKeyUsage;
2422 SECStatus rv;
2424 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage");
2425 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage);
2427 /* if we don't have a cached copy from before, we create one */
2428 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){
2430 PKIX_OBJECT_LOCK(cert);
2432 if ((cert->extKeyUsages == NULL) &&
2433 (!cert->extKeyUsagesAbsent)){
2435 nssCert = cert->nssCert;
2437 rv = CERT_FindCertExtension
2438 (nssCert, SEC_OID_X509_EXT_KEY_USAGE,
2439 &encodedExtKeyUsage);
2440 if (rv != SECSuccess){
2441 cert->extKeyUsagesAbsent = PKIX_TRUE;
2442 *pKeyUsage = NULL;
2443 goto cleanup;
2446 extKeyUsage =
2447 CERT_DecodeOidSequence(&encodedExtKeyUsage);
2448 if (extKeyUsage == NULL){
2449 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED);
2452 PKIX_CERT_DEBUG("\t\tCalling PORT_Free).\n");
2453 PORT_Free(encodedExtKeyUsage.data);
2455 oids = extKeyUsage->oids;
2457 if (!oids){
2458 /* no extended key usage extensions found */
2459 cert->extKeyUsagesAbsent = PKIX_TRUE;
2460 *pKeyUsage = NULL;
2461 goto cleanup;
2464 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
2465 PKIX_LISTCREATEFAILED);
2467 while (*oids){
2468 oid = *oids++;
2470 PKIX_CHECK(pkix_pl_oidBytes2Ascii
2471 (oid, &oidAscii, plContext),
2472 PKIX_OIDBYTES2ASCIIFAILED);
2474 PKIX_CHECK(PKIX_PL_OID_Create
2475 (oidAscii, &pkixOID, plContext),
2476 PKIX_OIDCREATEFAILED);
2478 PKIX_CHECK(PKIX_List_AppendItem
2479 (oidsList,
2480 (PKIX_PL_Object *)pkixOID,
2481 plContext),
2482 PKIX_LISTAPPENDITEMFAILED);
2484 PKIX_FREE(oidAscii);
2486 PKIX_DECREF(pkixOID);
2489 /* save a cached copy in case it is asked for again */
2490 cert->extKeyUsages = oidsList;
2493 PKIX_OBJECT_UNLOCK(cert);
2496 if (cert->extKeyUsages){
2498 PKIX_INCREF(cert->extKeyUsages);
2500 PKIX_CHECK(PKIX_List_SetImmutable
2501 (cert->extKeyUsages, plContext),
2502 PKIX_LISTSETIMMUTABLEFAILED);
2505 *pKeyUsage = cert->extKeyUsages;
2507 cleanup:
2508 if (objectIsLocked == PKIX_TRUE) {
2509 PKIX_OBJECT_UNLOCK(lockedObject);
2512 PKIX_FREE(oidAscii);
2513 PKIX_DECREF(pkixOID);
2515 CERT_DestroyOidSequence(extKeyUsage);
2517 if (PKIX_ERROR_RECEIVED){
2518 PKIX_DECREF(oidsList);
2521 PKIX_RETURN(CERT);
2525 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
2526 * (see comments in pkix_pl_pki.h)
2528 PKIX_Error *
2529 PKIX_PL_Cert_GetBasicConstraints(
2530 PKIX_PL_Cert *cert,
2531 PKIX_PL_CertBasicConstraints **pBasicConstraints,
2532 void *plContext)
2534 CERTCertificate *nssCert = NULL;
2535 CERTBasicConstraints nssBasicConstraint;
2536 SECStatus rv;
2537 PKIX_PL_CertBasicConstraints *basic;
2538 PKIX_Int32 pathLen = 0;
2539 PKIX_Boolean isCA = PKIX_FALSE;
2541 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints");
2542 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints);
2544 /* if we don't have a cached copy from before, we create one */
2545 if ((cert->certBasicConstraints == NULL) &&
2546 (!cert->basicConstraintsAbsent)) {
2548 PKIX_OBJECT_LOCK(cert);
2550 if ((cert->certBasicConstraints == NULL) &&
2551 (!cert->basicConstraintsAbsent)) {
2553 nssCert = cert->nssCert;
2555 PKIX_CERT_DEBUG(
2556 "\t\tCalling Cert_FindBasicConstraintExten\n");
2557 rv = CERT_FindBasicConstraintExten
2558 (nssCert, &nssBasicConstraint);
2559 if (rv != SECSuccess) {
2560 cert->basicConstraintsAbsent = PKIX_TRUE;
2561 *pBasicConstraints = NULL;
2562 goto cleanup;
2566 PKIX_OBJECT_UNLOCK(cert);
2568 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE;
2570 /* The pathLen has meaning only for CAs */
2571 if (isCA) {
2572 if (CERT_UNLIMITED_PATH_CONSTRAINT ==
2573 nssBasicConstraint.pathLenConstraint) {
2574 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
2575 } else {
2576 pathLen = nssBasicConstraint.pathLenConstraint;
2580 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create
2581 (isCA, pathLen, &basic, plContext),
2582 PKIX_CERTBASICCONSTRAINTSCREATEFAILED);
2584 /* save a cached copy in case it is asked for again */
2585 cert->certBasicConstraints = basic;
2588 PKIX_INCREF(cert->certBasicConstraints);
2589 *pBasicConstraints = cert->certBasicConstraints;
2591 cleanup:
2592 if (objectIsLocked == PKIX_TRUE) {
2593 PKIX_OBJECT_UNLOCK(lockedObject);
2597 PKIX_RETURN(CERT);
2601 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
2602 * (see comments in pkix_pl_pki.h)
2604 PKIX_Error *
2605 PKIX_PL_Cert_GetPolicyInformation(
2606 PKIX_PL_Cert *cert,
2607 PKIX_List **pPolicyInfo,
2608 void *plContext)
2610 PKIX_List *policyList = NULL;
2612 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation");
2613 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo);
2615 /* if we don't have a cached copy from before, we create one */
2616 if ((cert->certPolicyInfos == NULL) &&
2617 (!cert->policyInfoAbsent)) {
2619 PKIX_OBJECT_LOCK(cert);
2621 if ((cert->certPolicyInfos == NULL) &&
2622 (!cert->policyInfoAbsent)) {
2624 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo
2625 (cert->nssCert, &policyList, plContext),
2626 PKIX_CERTDECODEPOLICYINFOFAILED);
2628 if (!policyList) {
2629 cert->policyInfoAbsent = PKIX_TRUE;
2630 *pPolicyInfo = NULL;
2631 goto cleanup;
2635 PKIX_OBJECT_UNLOCK(cert);
2637 /* save a cached copy in case it is asked for again */
2638 cert->certPolicyInfos = policyList;
2641 PKIX_INCREF(cert->certPolicyInfos);
2643 *pPolicyInfo = cert->certPolicyInfos;
2645 cleanup:
2646 if (objectIsLocked == PKIX_TRUE) {
2647 PKIX_OBJECT_UNLOCK(lockedObject);
2650 PKIX_RETURN(CERT);
2654 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h)
2656 PKIX_Error *
2657 PKIX_PL_Cert_GetPolicyMappings(
2658 PKIX_PL_Cert *cert,
2659 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
2660 void *plContext)
2662 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */
2664 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings");
2665 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings);
2667 /* if we don't have a cached copy from before, we create one */
2668 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) {
2670 PKIX_OBJECT_LOCK(cert);
2672 if (!(cert->certPolicyMappings) &&
2673 !(cert->policyMappingsAbsent)) {
2675 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping
2676 (cert->nssCert, &policyMappings, plContext),
2677 PKIX_CERTDECODEPOLICYMAPPINGFAILED);
2679 if (!policyMappings) {
2680 cert->policyMappingsAbsent = PKIX_TRUE;
2681 *pPolicyMappings = NULL;
2682 goto cleanup;
2686 PKIX_OBJECT_UNLOCK(cert);
2688 /* save a cached copy in case it is asked for again */
2689 cert->certPolicyMappings = policyMappings;
2692 PKIX_INCREF(cert->certPolicyMappings);
2693 *pPolicyMappings = cert->certPolicyMappings;
2695 cleanup:
2696 if (objectIsLocked == PKIX_TRUE) {
2697 PKIX_OBJECT_UNLOCK(lockedObject);
2700 PKIX_RETURN(CERT);
2704 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
2705 * (see comments in pkix_pl_pki.h)
2707 PKIX_Error *
2708 PKIX_PL_Cert_GetRequireExplicitPolicy(
2709 PKIX_PL_Cert *cert,
2710 PKIX_Int32 *pSkipCerts,
2711 void *plContext)
2713 PKIX_Int32 explicitPolicySkipCerts = 0;
2714 PKIX_Int32 inhibitMappingSkipCerts = 0;
2716 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy");
2717 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2719 if (!(cert->policyConstraintsProcessed)) {
2720 PKIX_OBJECT_LOCK(cert);
2722 if (!(cert->policyConstraintsProcessed)) {
2725 * If we can't process it now, we probably will be
2726 * unable to process it later. Set the default value.
2728 cert->policyConstraintsProcessed = PKIX_TRUE;
2729 cert->policyConstraintsExplicitPolicySkipCerts = -1;
2730 cert->policyConstraintsInhibitMappingSkipCerts = -1;
2732 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
2733 (cert->nssCert,
2734 &explicitPolicySkipCerts,
2735 &inhibitMappingSkipCerts,
2736 plContext),
2737 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
2739 cert->policyConstraintsExplicitPolicySkipCerts =
2740 explicitPolicySkipCerts;
2741 cert->policyConstraintsInhibitMappingSkipCerts =
2742 inhibitMappingSkipCerts;
2745 PKIX_OBJECT_UNLOCK(cert);
2748 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts;
2750 cleanup:
2752 if (objectIsLocked == PKIX_TRUE) {
2753 PKIX_OBJECT_UNLOCK(lockedObject);
2756 PKIX_RETURN(CERT);
2760 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
2761 * (see comments in pkix_pl_pki.h)
2763 PKIX_Error *
2764 PKIX_PL_Cert_GetPolicyMappingInhibited(
2765 PKIX_PL_Cert *cert,
2766 PKIX_Int32 *pSkipCerts,
2767 void *plContext)
2769 PKIX_Int32 explicitPolicySkipCerts = 0;
2770 PKIX_Int32 inhibitMappingSkipCerts = 0;
2772 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited");
2773 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2775 if (!(cert->policyConstraintsProcessed)) {
2776 PKIX_OBJECT_LOCK(cert);
2778 if (!(cert->policyConstraintsProcessed)) {
2781 * If we can't process it now, we probably will be
2782 * unable to process it later. Set the default value.
2784 cert->policyConstraintsProcessed = PKIX_TRUE;
2785 cert->policyConstraintsExplicitPolicySkipCerts = -1;
2786 cert->policyConstraintsInhibitMappingSkipCerts = -1;
2788 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
2789 (cert->nssCert,
2790 &explicitPolicySkipCerts,
2791 &inhibitMappingSkipCerts,
2792 plContext),
2793 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
2795 cert->policyConstraintsExplicitPolicySkipCerts =
2796 explicitPolicySkipCerts;
2797 cert->policyConstraintsInhibitMappingSkipCerts =
2798 inhibitMappingSkipCerts;
2801 PKIX_OBJECT_UNLOCK(cert);
2804 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts;
2806 cleanup:
2808 if (objectIsLocked == PKIX_TRUE) {
2809 PKIX_OBJECT_UNLOCK(lockedObject);
2812 PKIX_RETURN(CERT);
2816 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h)
2818 PKIX_Error *
2819 PKIX_PL_Cert_GetInhibitAnyPolicy(
2820 PKIX_PL_Cert *cert,
2821 PKIX_Int32 *pSkipCerts,
2822 void *plContext)
2824 PKIX_Int32 skipCerts = 0;
2826 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy");
2827 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2829 if (!(cert->inhibitAnyPolicyProcessed)) {
2831 PKIX_OBJECT_LOCK(cert);
2833 if (!(cert->inhibitAnyPolicyProcessed)) {
2836 * If we can't process it now, we probably will be
2837 * unable to process it later. Set the default value.
2839 cert->inhibitAnyPolicyProcessed = PKIX_TRUE;
2840 cert->inhibitAnySkipCerts = -1;
2842 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy
2843 (cert->nssCert, &skipCerts, plContext),
2844 PKIX_CERTDECODEINHIBITANYPOLICYFAILED);
2846 cert->inhibitAnySkipCerts = skipCerts;
2849 PKIX_OBJECT_UNLOCK(cert);
2852 cleanup:
2854 if (objectIsLocked == PKIX_TRUE) {
2855 PKIX_OBJECT_UNLOCK(lockedObject);
2858 *pSkipCerts = cert->inhibitAnySkipCerts;
2860 PKIX_RETURN(CERT);
2864 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
2865 * (see comments in pkix_pl_pki.h)
2867 PKIX_Error *
2868 PKIX_PL_Cert_AreCertPoliciesCritical(
2869 PKIX_PL_Cert *cert,
2870 PKIX_Boolean *pCritical,
2871 void *plContext)
2873 PKIX_Boolean criticality = PKIX_FALSE;
2875 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical");
2876 PKIX_NULLCHECK_TWO(cert, pCritical);
2878 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical(
2879 cert,
2880 SEC_OID_X509_CERTIFICATE_POLICIES,
2881 &criticality,
2882 plContext),
2883 PKIX_CERTISEXTENSIONCRITICALFAILED);
2885 *pCritical = criticality;
2887 cleanup:
2889 PKIX_RETURN(CERT);
2893 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h)
2895 PKIX_Error *
2896 PKIX_PL_Cert_VerifySignature(
2897 PKIX_PL_Cert *cert,
2898 PKIX_PL_PublicKey *pubKey,
2899 void *plContext)
2901 CERTCertificate *nssCert = NULL;
2902 SECKEYPublicKey *nssPubKey = NULL;
2903 CERTSignedData *tbsCert = NULL;
2904 PKIX_PL_Cert *cachedCert = NULL;
2905 PKIX_Error *verifySig = NULL;
2906 PKIX_Error *cachedSig = NULL;
2907 SECStatus status;
2908 PKIX_Boolean certEqual = PKIX_FALSE;
2909 PKIX_Boolean certInHash = PKIX_FALSE;
2911 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature");
2912 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey);
2914 verifySig = PKIX_PL_HashTable_Lookup
2915 (cachedCertSigTable,
2916 (PKIX_PL_Object *) pubKey,
2917 (PKIX_PL_Object **) &cachedCert,
2918 plContext);
2920 if (cachedCert != NULL && verifySig == NULL) {
2921 /* Cached Signature Table lookup succeed */
2922 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext,
2923 PKIX_OBJECTEQUALSFAILED);
2924 if (certEqual == PKIX_TRUE) {
2925 goto cleanup;
2927 /* Different PubKey may hash to same value, skip add */
2928 certInHash = PKIX_TRUE;
2931 nssCert = cert->nssCert;
2932 tbsCert = &nssCert->signatureWrap;
2934 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n");
2935 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
2936 if (!nssPubKey){
2937 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
2940 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n");
2941 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, NULL);
2943 if (status != SECSuccess) {
2944 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHISPUBLICKEY);
2947 if (certInHash == PKIX_FALSE) {
2948 cachedSig = PKIX_PL_HashTable_Add
2949 (cachedCertSigTable,
2950 (PKIX_PL_Object *) pubKey,
2951 (PKIX_PL_Object *) cert,
2952 plContext);
2954 if (cachedSig != NULL) {
2955 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
2959 cleanup:
2961 if (nssPubKey){
2962 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n");
2963 SECKEY_DestroyPublicKey(nssPubKey);
2966 PKIX_DECREF(cachedCert);
2967 PKIX_DECREF(verifySig);
2968 PKIX_DECREF(cachedSig);
2970 PKIX_RETURN(CERT);
2974 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h)
2976 PKIX_Error *
2977 PKIX_PL_Cert_CheckValidity(
2978 PKIX_PL_Cert *cert,
2979 PKIX_PL_Date *date,
2980 void *plContext)
2982 SECCertTimeValidity val;
2983 PRTime timeToCheck;
2985 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity");
2986 PKIX_NULLCHECK_ONE(cert);
2988 /* if the caller supplies a date, we use it; else, use current time */
2989 if (date != NULL){
2990 PKIX_CHECK(pkix_pl_Date_GetPRTime
2991 (date, &timeToCheck, plContext),
2992 PKIX_DATEGETPRTIMEFAILED);
2993 } else {
2994 PKIX_CERT_DEBUG("\t\tCalling PR_Now).\n");
2995 timeToCheck = PR_Now();
2998 PKIX_CERT_DEBUG("\t\tCalling CERT_CheckCertValidTimes).\n");
2999 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, PKIX_FALSE);
3000 if (val != secCertTimeValid){
3001 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED);
3004 cleanup:
3006 PKIX_RETURN(CERT);
3010 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h)
3012 PKIX_Error *
3013 PKIX_PL_Cert_GetValidityNotAfter(
3014 PKIX_PL_Cert *cert,
3015 PKIX_PL_Date **pDate,
3016 void *plContext)
3018 PRTime prtime;
3019 SECStatus rv = SECFailure;
3021 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter");
3022 PKIX_NULLCHECK_TWO(cert, pDate);
3024 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
3025 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter));
3026 if (rv != SECSuccess){
3027 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
3030 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime
3031 (prtime, pDate, plContext),
3032 PKIX_DATECREATEFROMPRTIMEFAILED);
3034 cleanup:
3036 PKIX_RETURN(CERT);
3040 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h)
3042 PKIX_Error *
3043 PKIX_PL_Cert_VerifyKeyUsage(
3044 PKIX_PL_Cert *cert,
3045 PKIX_UInt32 keyUsage,
3046 void *plContext)
3048 CERTCertificate *nssCert = NULL;
3049 PKIX_UInt32 nssKeyUsage = 0;
3050 SECStatus status;
3052 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage");
3053 PKIX_NULLCHECK_TWO(cert, cert->nssCert);
3055 nssCert = cert->nssCert;
3057 /* if cert doesn't have keyUsage extension, all keyUsages are valid */
3058 if (!nssCert->keyUsagePresent){
3059 goto cleanup;
3062 if (keyUsage & PKIX_DIGITAL_SIGNATURE){
3063 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
3066 if (keyUsage & PKIX_NON_REPUDIATION){
3067 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION;
3070 if (keyUsage & PKIX_KEY_ENCIPHERMENT){
3071 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT;
3074 if (keyUsage & PKIX_DATA_ENCIPHERMENT){
3075 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT;
3078 if (keyUsage & PKIX_KEY_AGREEMENT){
3079 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT;
3082 if (keyUsage & PKIX_KEY_CERT_SIGN){
3083 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN;
3086 if (keyUsage & PKIX_CRL_SIGN){
3087 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN;
3090 if (keyUsage & PKIX_ENCIPHER_ONLY){
3091 nssKeyUsage = nssKeyUsage | 0x01;
3094 if (keyUsage & PKIX_DECIPHER_ONLY){
3095 /* XXX we should support this once it is fixed in NSS */
3096 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED);
3099 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage);
3100 if (status != SECSuccess) {
3101 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
3104 cleanup:
3106 PKIX_RETURN(CERT);
3110 * FUNCTION: PKIX_PL_Cert_GetNameConstraints
3111 * (see comments in pkix_pl_pki.h)
3113 PKIX_Error *
3114 PKIX_PL_Cert_GetNameConstraints(
3115 PKIX_PL_Cert *cert,
3116 PKIX_PL_CertNameConstraints **pNameConstraints,
3117 void *plContext)
3119 PKIX_PL_CertNameConstraints *nameConstraints = NULL;
3121 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints");
3122 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints);
3124 /* if we don't have a cached copy from before, we create one */
3125 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) {
3127 PKIX_OBJECT_LOCK(cert);
3129 if (cert->nameConstraints == NULL &&
3130 !cert->nameConstraintsAbsent) {
3132 PKIX_CHECK(pkix_pl_CertNameConstraints_Create
3133 (cert->nssCert, &nameConstraints, plContext),
3134 PKIX_CERTNAMECONSTRAINTSCREATEFAILED);
3136 if (nameConstraints == NULL) {
3137 cert->nameConstraintsAbsent = PKIX_TRUE;
3140 cert->nameConstraints = nameConstraints;
3143 PKIX_OBJECT_UNLOCK(cert);
3147 PKIX_INCREF(cert->nameConstraints);
3149 *pNameConstraints = cert->nameConstraints;
3151 cleanup:
3153 if (objectIsLocked == PKIX_TRUE) {
3154 PKIX_OBJECT_UNLOCK(lockedObject);
3157 PKIX_RETURN(CERT);
3161 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
3162 * (see comments in pkix_pl_pki.h)
3164 PKIX_Error *
3165 PKIX_PL_Cert_CheckNameConstraints(
3166 PKIX_PL_Cert *cert,
3167 PKIX_PL_CertNameConstraints *nameConstraints,
3168 void *plContext)
3170 PKIX_Boolean checkPass = PKIX_TRUE;
3171 CERTGeneralName *nssSubjectNames = NULL;
3172 PRArenaPool *arena = NULL;
3174 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints");
3175 PKIX_NULLCHECK_ONE(cert);
3177 if (nameConstraints != NULL) {
3179 PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena\n");
3180 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3181 if (arena == NULL) {
3182 PKIX_ERROR(PKIX_PORTNEWARENAFAILED);
3185 /* This NSS call returns both Subject and Subject Alt Names */
3186 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
3187 nssSubjectNames = CERT_GetCertificateNames
3188 (cert->nssCert, arena);
3190 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
3191 (nssSubjectNames,
3192 nameConstraints,
3193 &checkPass,
3194 plContext),
3195 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED);
3197 if (checkPass != PKIX_TRUE) {
3198 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING);
3202 cleanup:
3204 if (arena){
3205 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
3206 PORT_FreeArena(arena, PR_FALSE);
3209 PKIX_RETURN(CERT);
3213 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
3214 * (see comments in pkix_pl_pki.h)
3216 PKIX_Error *
3217 PKIX_PL_Cert_MergeNameConstraints(
3218 PKIX_PL_CertNameConstraints *firstNC,
3219 PKIX_PL_CertNameConstraints *secondNC,
3220 PKIX_PL_CertNameConstraints **pResultNC,
3221 void *plContext)
3223 PKIX_PL_CertNameConstraints *mergedNC = NULL;
3225 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints");
3226 PKIX_NULLCHECK_TWO(firstNC, pResultNC);
3228 if (secondNC == NULL) {
3230 PKIX_INCREF(firstNC);
3231 *pResultNC = firstNC;
3233 goto cleanup;
3236 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge
3237 (firstNC, secondNC, &mergedNC, plContext),
3238 PKIX_CERTNAMECONSTRAINTSMERGEFAILED);
3240 *pResultNC = mergedNC;
3242 cleanup:
3244 PKIX_RETURN(CERT);
3248 * FUNCTION: PKIX_PL_Cert_IsCertTrusted
3249 * (see comments in pkix_pl_pki.h)
3251 PKIX_Error *
3252 PKIX_PL_Cert_IsCertTrusted(
3253 PKIX_PL_Cert *cert,
3254 PKIX_Boolean *pTrusted,
3255 void *plContext)
3257 PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
3258 SECCertUsage certUsage = 0;
3259 PKIX_Boolean trusted = PKIX_FALSE;
3260 SECStatus rv = SECFailure;
3261 unsigned int requiredFlags;
3262 unsigned int certFlags;
3263 SECTrustType trustType;
3264 CERTCertTrust trust;
3265 CERTCertificate *nssCert = NULL;
3266 SECCertificateUsage certificateUsage;
3268 PKIX_ENTER(CERT, "pkix_pl_Cert_IsCertTrusted");
3269 PKIX_NULLCHECK_TWO(cert, pTrusted);
3271 /* no key usage information and store is not trusted */
3272 if (plContext == NULL || cert->store == NULL) {
3273 *pTrusted = PKIX_FALSE;
3274 goto cleanup;
3277 if (cert->store) {
3278 PKIX_CHECK(PKIX_CertStore_GetTrustCallback
3279 (cert->store, &trustCallback, plContext),
3280 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
3282 PKIX_CHECK_ONLY_FATAL(trustCallback
3283 (cert->store, cert, &trusted, plContext),
3284 PKIX_CHECKTRUSTCALLBACKFAILED);
3286 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) {
3288 *pTrusted = PKIX_FALSE;
3289 goto cleanup;
3294 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
3296 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
3297 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
3299 PKIX_PL_NSSCALLRV
3300 (CERT,
3302 CERT_TrustFlagsForCACertUsage,
3303 (certUsage, &requiredFlags, &trustType));
3305 if (rv != SECSuccess) {
3306 requiredFlags = 0;
3307 trustType = trustSSL;
3310 nssCert = cert->nssCert;
3312 PKIX_PL_NSSCALLRV(CERT, rv, CERT_GetCertTrust, (nssCert, &trust));
3314 if (rv == SECSuccess) {
3316 certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType);
3317 if ((certFlags & CERTDB_VALID_CA) &&
3318 ((certFlags & requiredFlags) == requiredFlags)) {
3319 trusted = PKIX_TRUE;
3323 *pTrusted = trusted;
3325 cleanup:
3327 PKIX_RETURN(CERT);
3331 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h)
3333 PKIX_Error *
3334 PKIX_PL_Cert_GetCacheFlag(
3335 PKIX_PL_Cert *cert,
3336 PKIX_Boolean *pCacheFlag,
3337 void *plContext)
3339 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag");
3340 PKIX_NULLCHECK_TWO(cert, pCacheFlag);
3342 *pCacheFlag = cert->cacheFlag;
3344 PKIX_RETURN(CERT);
3348 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h)
3350 PKIX_Error *
3351 PKIX_PL_Cert_SetCacheFlag(
3352 PKIX_PL_Cert *cert,
3353 PKIX_Boolean cacheFlag,
3354 void *plContext)
3356 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag");
3357 PKIX_NULLCHECK_ONE(cert);
3359 cert->cacheFlag = cacheFlag;
3361 PKIX_RETURN(CERT);
3365 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h)
3367 PKIX_Error *
3368 PKIX_PL_Cert_GetTrustCertStore(
3369 PKIX_PL_Cert *cert,
3370 PKIX_CertStore **pTrustCertStore,
3371 void *plContext)
3373 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore");
3374 PKIX_NULLCHECK_TWO(cert, pTrustCertStore);
3376 PKIX_INCREF(cert->store);
3377 *pTrustCertStore = cert->store;
3379 PKIX_RETURN(CERT);
3383 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h)
3385 PKIX_Error *
3386 PKIX_PL_Cert_SetTrustCertStore(
3387 PKIX_PL_Cert *cert,
3388 PKIX_CertStore *trustCertStore,
3389 void *plContext)
3391 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore");
3392 PKIX_NULLCHECK_TWO(cert, trustCertStore);
3394 PKIX_INCREF(trustCertStore);
3395 cert->store = trustCertStore;
3397 PKIX_RETURN(CERT);
3401 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
3402 * (see comments in pkix_pl_pki.h)
3404 PKIX_Error *
3405 PKIX_PL_Cert_GetAuthorityInfoAccess(
3406 PKIX_PL_Cert *cert,
3407 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
3408 void *plContext)
3410 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */
3411 SECItem *encodedAIA = NULL;
3412 CERTAuthInfoAccess **aia = NULL;
3413 PRArenaPool *arena = NULL;
3414 SECStatus rv;
3416 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess");
3417 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList);
3419 /* if we don't have a cached copy from before, we create one */
3420 if (cert->authorityInfoAccess == NULL) {
3422 PKIX_OBJECT_LOCK(cert);
3424 if (cert->authorityInfoAccess == NULL) {
3426 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem,
3427 (NULL, NULL, 0));
3429 if (encodedAIA == NULL) {
3430 goto cleanup;
3433 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
3434 (cert->nssCert,
3435 SEC_OID_X509_AUTH_INFO_ACCESS,
3436 encodedAIA));
3438 if (rv == SECFailure) {
3439 goto cleanup;
3442 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
3443 (DER_DEFAULT_CHUNKSIZE));
3445 if (arena == NULL) {
3446 goto cleanup;
3449 PKIX_PL_NSSCALLRV
3450 (CERT, aia, CERT_DecodeAuthInfoAccessExtension,
3451 (arena, encodedAIA));
3453 PKIX_CHECK(pkix_pl_InfoAccess_CreateList
3454 (aia, &aiaList, plContext),
3455 PKIX_INFOACCESSCREATELISTFAILED);
3457 cert->authorityInfoAccess = aiaList;
3460 PKIX_OBJECT_UNLOCK(cert);
3463 PKIX_INCREF(cert->authorityInfoAccess);
3465 *pAiaList = cert->authorityInfoAccess;
3467 cleanup:
3468 if (objectIsLocked == PKIX_TRUE) {
3469 PKIX_OBJECT_UNLOCK(lockedObject);
3472 if (arena != NULL) {
3473 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
3474 PORT_FreeArena(arena, PR_FALSE);
3477 if (encodedAIA != NULL) {
3478 PKIX_CERT_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
3479 SECITEM_FreeItem(encodedAIA, PR_TRUE);
3482 PKIX_RETURN(CERT);
3485 /* XXX Following defines belongs to NSS */
3486 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
3487 0x07, 0x01, 0x0b};
3488 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
3491 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
3492 * (see comments in pkix_pl_pki.h)
3494 PKIX_Error *
3495 PKIX_PL_Cert_GetSubjectInfoAccess(
3496 PKIX_PL_Cert *cert,
3497 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
3498 void *plContext)
3500 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */
3501 SECItem siaOID = OI(siaOIDString);
3502 SECItem *encodedSubjInfoAccess = NULL;
3503 CERTAuthInfoAccess **subjInfoAccess = NULL;
3504 PRArenaPool *arena = NULL;
3505 SECStatus rv;
3507 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess");
3508 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList);
3510 /* XXX
3511 * Codes to deal with SubjectInfoAccess OID should be moved to
3512 * NSS soon. I implemented them here so we don't touch NSS
3513 * source tree, from JP's suggestion.
3516 /* if we don't have a cached copy from before, we create one */
3517 if (cert->subjectInfoAccess == NULL) {
3519 PKIX_OBJECT_LOCK(cert);
3521 if (cert->subjectInfoAccess == NULL) {
3523 PKIX_CERT_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
3524 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
3525 if (encodedSubjInfoAccess == NULL) {
3526 goto cleanup;
3529 PKIX_CERT_DEBUG
3530 ("\t\tCalling CERT_FindCertExtensionByOID).\n");
3531 rv = CERT_FindCertExtensionByOID
3532 (cert->nssCert, &siaOID, encodedSubjInfoAccess);
3534 if (rv == SECFailure) {
3535 goto cleanup;
3538 PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
3539 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3540 if (arena == NULL) {
3541 goto cleanup;
3544 /* XXX
3545 * Decode Subject Information Access -
3546 * since its type is the same as Authority Information
3547 * Access, reuse the call. NSS- change name to avoid
3548 * confusion.
3550 PKIX_CERT_DEBUG
3551 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n");
3552 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension
3553 (arena, encodedSubjInfoAccess);
3555 PKIX_CHECK(pkix_pl_InfoAccess_CreateList
3556 (subjInfoAccess, &siaList, plContext),
3557 PKIX_INFOACCESSCREATELISTFAILED);
3559 cert->subjectInfoAccess = siaList;
3563 PKIX_OBJECT_UNLOCK(cert);
3566 PKIX_INCREF(cert->subjectInfoAccess);
3568 *pSiaList = cert->subjectInfoAccess;
3570 cleanup:
3571 if (objectIsLocked == PKIX_TRUE) {
3572 PKIX_OBJECT_UNLOCK(lockedObject);
3575 if (arena != NULL) {
3576 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
3577 PORT_FreeArena(arena, PR_FALSE);
3580 if (encodedSubjInfoAccess != NULL) {
3581 PKIX_CERT_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
3582 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE);
3585 PKIX_RETURN(CERT);