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
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.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
50 #endif /* NSS_3_4_CODE */
59 * Check the validity times of a certificate
62 CERT_CertTimesValid(CERTCertificate
*c
)
64 SECCertTimeValidity valid
= CERT_CheckCertValidTimes(c
, PR_Now(), PR_TRUE
);
65 return (valid
== secCertTimeValid
) ? SECSuccess
: SECFailure
;
69 * verify the signature of a signed data object with the given DER publickey
72 CERT_VerifySignedDataWithPublicKey(CERTSignedData
*sd
,
73 SECKEYPublicKey
*pubKey
,
79 if ( !pubKey
|| !sd
) {
80 PORT_SetError(PR_INVALID_ARGUMENT_ERROR
);
84 /* check the signature */
86 /* convert sig->len from bit counts to byte count. */
87 DER_ConvertBitString(&sig
);
89 rv
= VFY_VerifyDataWithAlgorithmID(sd
->data
.data
, sd
->data
.len
, pubKey
,
90 &sig
, &sd
->signatureAlgorithm
, NULL
, wincx
);
92 return rv
? SECFailure
: SECSuccess
;
96 * verify the signature of a signed data object with the given DER publickey
99 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData
*sd
,
100 CERTSubjectPublicKeyInfo
*pubKeyInfo
,
103 SECKEYPublicKey
*pubKey
;
104 SECStatus rv
= SECFailure
;
106 /* get cert's public key */
107 pubKey
= SECKEY_ExtractPublicKey(pubKeyInfo
);
109 rv
= CERT_VerifySignedDataWithPublicKey(sd
, pubKey
, wincx
);
110 SECKEY_DestroyPublicKey(pubKey
);
116 * verify the signature of a signed data object with the given certificate
119 CERT_VerifySignedData(CERTSignedData
*sd
, CERTCertificate
*cert
,
120 int64 t
, void *wincx
)
122 SECKEYPublicKey
*pubKey
= 0;
123 SECStatus rv
= SECFailure
;
124 SECCertTimeValidity validity
;
126 /* check the certificate's validity */
127 validity
= CERT_CheckCertValidTimes(cert
, t
, PR_FALSE
);
128 if ( validity
!= secCertTimeValid
) {
132 /* get cert's public key */
133 pubKey
= CERT_ExtractPublicKey(cert
);
135 rv
= CERT_VerifySignedDataWithPublicKey(sd
, pubKey
, wincx
);
136 SECKEY_DestroyPublicKey(pubKey
);
142 /* Software FORTEZZA installation hack. The software fortezza installer does
143 * not have access to the krl and cert.db file. Accept FORTEZZA Certs without
144 * KRL's in this case.
146 static int dont_use_krl
= 0;
147 /* not a public exposed function... */
148 void sec_SetCheckKRLState(int value
) { dont_use_krl
= value
; }
151 SEC_CheckKRL(CERTCertDBHandle
*handle
,SECKEYPublicKey
*key
,
152 CERTCertificate
*rootCert
, int64 t
, void * wincx
)
154 CERTSignedCrl
*crl
= NULL
;
155 SECStatus rv
= SECFailure
;
157 CERTCrlEntry
**crlEntry
;
158 SECCertTimeValidity validity
;
159 CERTCertificate
*issuerCert
= NULL
;
161 if (dont_use_krl
) return SECSuccess
;
163 /* first look up the KRL */
164 crl
= SEC_FindCrlByName(handle
,&rootCert
->derSubject
, SEC_KRL_TYPE
);
166 PORT_SetError(SEC_ERROR_NO_KRL
);
170 /* get the issuing certificate */
171 issuerCert
= CERT_FindCertByName(handle
, &crl
->crl
.derName
);
172 if (issuerCert
== NULL
) {
173 PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE
);
178 /* now verify the KRL signature */
179 rv2
= CERT_VerifySignedData(&crl
->signatureWrap
, issuerCert
, t
, wincx
);
180 if (rv2
!= SECSuccess
) {
181 PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE
);
185 /* Verify the date validity of the KRL */
186 validity
= SEC_CheckCrlTimes(&crl
->crl
, t
);
187 if (validity
== secCertTimeExpired
) {
188 PORT_SetError(SEC_ERROR_KRL_EXPIRED
);
192 /* now make sure the key in this cert is still valid */
193 if (key
->keyType
!= fortezzaKey
) {
194 PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN
);
195 goto done
; /* This should be an assert? */
198 /* now make sure the key is not on the revocation list */
199 for (crlEntry
= crl
->crl
.entries
; crlEntry
&& *crlEntry
; crlEntry
++) {
200 if (PORT_Memcmp((*crlEntry
)->serialNumber
.data
,
201 key
->u
.fortezza
.KMID
,
202 (*crlEntry
)->serialNumber
.len
) == 0) {
203 PORT_SetError(SEC_ERROR_REVOKED_KEY
);
210 if (issuerCert
) CERT_DestroyCertificate(issuerCert
);
211 if (crl
) SEC_DestroyCrl(crl
);
216 SEC_CheckCRL(CERTCertDBHandle
*handle
,CERTCertificate
*cert
,
217 CERTCertificate
*caCert
, int64 t
, void * wincx
)
219 return CERT_CheckCRL(cert
, caCert
, NULL
, t
, wincx
);
223 * Find the issuer of a cert. Use the authorityKeyID if it exists.
226 CERT_FindCertIssuer(CERTCertificate
*cert
, int64 validTime
, SECCertUsage usage
)
229 CERTAuthKeyID
* authorityKeyID
= NULL
;
230 CERTCertificate
* issuerCert
= NULL
;
232 PRArenaPool
*tmpArena
= NULL
;
234 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
239 authorityKeyID
= CERT_FindAuthKeyIDExten(tmpArena
,cert
);
241 if ( authorityKeyID
!= NULL
) {
242 /* has the authority key ID extension */
243 if ( authorityKeyID
->keyID
.data
!= NULL
) {
244 /* extension contains a key ID, so lookup based on it */
245 issuerCert
= CERT_FindCertByKeyID(cert
->dbhandle
, &cert
->derIssuer
,
246 &authorityKeyID
->keyID
);
247 if ( issuerCert
== NULL
) {
248 PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER
);
252 } else if ( authorityKeyID
->authCertIssuer
!= NULL
) {
253 /* no key ID, so try issuer and serial number */
254 caName
= (SECItem
*)CERT_GetGeneralNameByType(authorityKeyID
->authCertIssuer
,
255 certDirectoryName
, PR_TRUE
);
258 * caName is NULL when the authCertIssuer field is not
259 * being used, or other name form is used instead.
260 * If the directoryName format and serialNumber fields are
261 * used, we use them to find the CA cert.
263 * By the time it gets here, we known for sure that if the
264 * authCertIssuer exists, then the authCertSerialNumber
265 * must also exists (CERT_DecodeAuthKeyID() ensures this).
266 * We don't need to check again.
269 if (caName
!= NULL
) {
270 CERTIssuerAndSN issuerSN
;
272 issuerSN
.derIssuer
.data
= caName
->data
;
273 issuerSN
.derIssuer
.len
= caName
->len
;
274 issuerSN
.serialNumber
.data
=
275 authorityKeyID
->authCertSerialNumber
.data
;
276 issuerSN
.serialNumber
.len
=
277 authorityKeyID
->authCertSerialNumber
.len
;
278 issuerCert
= CERT_FindCertByIssuerAndSN(cert
->dbhandle
,
280 if ( issuerCert
== NULL
) {
281 PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER
);
287 if ( issuerCert
== NULL
) {
288 /* if there is not authorityKeyID, then try to find the issuer */
289 /* find a valid CA cert with correct usage */
290 issuerCert
= CERT_FindMatchingCert(cert
->dbhandle
,
292 certOwnerCA
, usage
, PR_TRUE
,
295 /* if that fails, then fall back to grabbing any cert with right name*/
296 if ( issuerCert
== NULL
) {
297 issuerCert
= CERT_FindCertByName(cert
->dbhandle
, &cert
->derIssuer
);
298 if ( issuerCert
== NULL
) {
299 PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER
);
305 if (tmpArena
!= NULL
) {
306 PORT_FreeArena(tmpArena
, PR_FALSE
);
315 NSSCryptoContext
*cc
;
316 NSSCertificate
*chain
[3];
320 me
= STAN_GetNSSCertificate(cert
);
322 PORT_SetError(SEC_ERROR_NO_MEMORY
);
325 nssTime
= NSSTime_SetPRTime(NULL
, validTime
);
326 nssUsage
.anyUsage
= PR_FALSE
;
327 nssUsage
.nss3usage
= usage
;
328 nssUsage
.nss3lookingForCA
= PR_TRUE
;
329 memset(chain
, 0, 3*sizeof(NSSCertificate
*));
330 td
= STAN_GetDefaultTrustDomain();
331 cc
= STAN_GetDefaultCryptoContext();
332 (void)NSSCertificate_BuildChain(me
, nssTime
, &nssUsage
, NULL
,
333 chain
, 2, NULL
, &status
, td
, cc
);
334 nss_ZFreeIf(nssTime
);
335 if (status
== PR_SUCCESS
) {
336 PORT_Assert(me
== chain
[0]);
337 /* if it's a root, the chain will only have one cert */
339 /* already has a reference from the call to BuildChain */
342 NSSCertificate_Destroy(chain
[0]); /* the first cert in the chain */
343 return STAN_GetCERTCertificate(chain
[1]); /* return the 2nd */
346 PORT_Assert(me
== chain
[0]);
347 NSSCertificate_Destroy(chain
[0]); /* the first cert in the chain */
349 PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER
);
355 * return required trust flags for various cert usages for CAs
358 CERT_TrustFlagsForCACertUsage(SECCertUsage usage
,
359 unsigned int *retFlags
,
360 SECTrustType
*retTrustType
)
362 unsigned int requiredFlags
;
363 SECTrustType trustType
;
366 case certUsageSSLClient
:
367 requiredFlags
= CERTDB_TRUSTED_CLIENT_CA
;
368 trustType
= trustSSL
;
370 case certUsageSSLServer
:
372 requiredFlags
= CERTDB_TRUSTED_CA
;
373 trustType
= trustSSL
;
375 case certUsageSSLServerWithStepUp
:
376 requiredFlags
= CERTDB_TRUSTED_CA
| CERTDB_GOVT_APPROVED_CA
;
377 trustType
= trustSSL
;
379 case certUsageEmailSigner
:
380 case certUsageEmailRecipient
:
381 requiredFlags
= CERTDB_TRUSTED_CA
;
382 trustType
= trustEmail
;
384 case certUsageObjectSigner
:
385 requiredFlags
= CERTDB_TRUSTED_CA
;
386 trustType
= trustObjectSigning
;
388 case certUsageVerifyCA
:
390 case certUsageStatusResponder
:
391 requiredFlags
= CERTDB_TRUSTED_CA
;
392 trustType
= trustTypeNone
;
398 if ( retFlags
!= NULL
) {
399 *retFlags
= requiredFlags
;
401 if ( retTrustType
!= NULL
) {
402 *retTrustType
= trustType
;
415 AddToVerifyLog(CERTVerifyLog
*log
, CERTCertificate
*cert
, unsigned long error
,
416 unsigned int depth
, void *arg
)
418 CERTVerifyLogNode
*node
, *tnode
;
420 PORT_Assert(log
!= NULL
);
422 node
= (CERTVerifyLogNode
*)PORT_ArenaAlloc(log
->arena
,
423 sizeof(CERTVerifyLogNode
));
424 if ( node
!= NULL
) {
425 node
->cert
= CERT_DupCertificate(cert
);
430 if ( log
->tail
== NULL
) {
432 log
->head
= log
->tail
= node
;
435 } else if ( depth
>= log
->tail
->depth
) {
437 node
->prev
= log
->tail
;
438 log
->tail
->next
= node
;
441 } else if ( depth
< log
->head
->depth
) {
444 node
->next
= log
->head
;
445 log
->head
->prev
= node
;
450 while ( tnode
!= NULL
) {
451 if ( depth
>= tnode
->depth
) {
452 /* insert after tnode */
454 node
->next
= tnode
->next
;
455 tnode
->next
->prev
= node
;
469 #define EXIT_IF_NOT_LOGGING(log) \
470 if ( log == NULL ) { \
474 #define LOG_ERROR_OR_EXIT(log,cert,depth,arg) \
475 if ( log != NULL ) { \
476 AddToVerifyLog(log, cert, PORT_GetError(), depth, (void *)arg); \
481 #define LOG_ERROR(log,cert,depth,arg) \
482 if ( log != NULL ) { \
483 AddToVerifyLog(log, cert, PORT_GetError(), depth, (void *)arg); \
487 typedef enum { cbd_None
, cbd_User
, cbd_CA
} cbd_FortezzaType
;
490 cert_VerifyFortezzaV1Cert(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
491 cbd_FortezzaType
*next_type
, cbd_FortezzaType last_type
,
492 int64 t
, void *wincx
)
494 unsigned char priv
= 0;
495 SECKEYPublicKey
*key
;
501 key
= CERT_ExtractPublicKey(cert
);
503 /* Cant' get Key? fail. */
505 PORT_SetError(SEC_ERROR_BAD_KEY
);
510 /* if the issuer is not an old fortezza cert, we bail */
511 if (key
->keyType
!= fortezzaKey
) {
512 SECKEY_DestroyPublicKey(key
);
513 /* CA Cert not fortezza */
514 PORT_SetError(SEC_ERROR_NOT_FORTEZZA_ISSUER
);
518 /* get the privilege mask */
519 if (key
->u
.fortezza
.DSSpriviledge
.len
> 0) {
520 priv
= key
->u
.fortezza
.DSSpriviledge
.data
[0];
524 * make sure the CA's keys are OK
527 rv
= SEC_CheckKRL(handle
, key
, NULL
, t
, wincx
);
528 SECKEY_DestroyPublicKey(key
);
529 if (rv
!= SECSuccess
) {
535 /* first check for subordination */
536 /*rv = FortezzaSubordinateCheck(cert,issuerCert);*/
539 /* now check for issuer privilege */
540 if ((rv
!= SECSuccess
) || ((priv
& 0x10) == 0)) {
542 PORT_SetError (SEC_ERROR_CA_CERT_INVALID
);
547 if ((priv
& 0x20) == 0) {
549 PORT_SetError (SEC_ERROR_CA_CERT_INVALID
);
554 *next_type
= (priv
& 0x30) ? cbd_CA
: cbd_User
;
557 /* bail */ /* shouldn't ever happen */
558 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER
);
566 cert_VerifyCertChain(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
567 PRBool checkSig
, PRBool
* sigerror
,
568 SECCertUsage certUsage
, int64 t
, void *wincx
,
569 CERTVerifyLog
*log
, PRBool
* revoked
)
571 SECTrustType trustType
;
572 CERTBasicConstraints basicConstraint
;
573 CERTCertificate
*issuerCert
= NULL
;
574 CERTCertificate
*subjectCert
= NULL
;
575 CERTCertificate
*badCert
= NULL
;
577 PRBool isFortezzaV1
= PR_FALSE
;
579 SECStatus rvFinal
= SECSuccess
;
581 int currentPathLen
= 0;
582 int pathLengthLimit
= CERT_UNLIMITED_PATH_CONSTRAINT
;
584 unsigned int caCertType
;
585 unsigned int requiredCAKeyUsage
;
586 unsigned int requiredFlags
;
587 PRArenaPool
*arena
= NULL
;
588 CERTGeneralName
*namesList
= NULL
;
589 CERTCertificate
**certsList
= NULL
;
590 int certsListLen
= 16;
592 PRBool subjectCertIsSelfIssued
;
594 cbd_FortezzaType last_type
= cbd_None
;
600 if (CERT_KeyUsageAndTypeForCertUsage(certUsage
, PR_TRUE
,
605 EXIT_IF_NOT_LOGGING(log
);
606 requiredCAKeyUsage
= 0;
610 switch ( certUsage
) {
611 case certUsageSSLClient
:
612 case certUsageSSLServer
:
614 case certUsageSSLServerWithStepUp
:
615 case certUsageEmailSigner
:
616 case certUsageEmailRecipient
:
617 case certUsageObjectSigner
:
618 case certUsageVerifyCA
:
619 case certUsageStatusResponder
:
620 if ( CERT_TrustFlagsForCACertUsage(certUsage
, &requiredFlags
,
621 &trustType
) != SECSuccess
) {
623 EXIT_IF_NOT_LOGGING(log
);
625 trustType
= trustSSL
;
630 EXIT_IF_NOT_LOGGING(log
);
632 trustType
= trustSSL
;/* This used to be 0, but we need something
633 * that matches the enumeration type.
638 subjectCert
= CERT_DupCertificate(cert
);
639 if ( subjectCert
== NULL
) {
643 /* determine if the cert is fortezza.
645 isFortezzaV1
= (PRBool
)
646 (CERT_GetCertKeyType(&subjectCert
->subjectPublicKeyInfo
)
650 rv
= cert_VerifyFortezzaV1Cert(handle
, subjectCert
, &last_type
,
652 if (rv
== SECFailure
) {
653 /**** PORT_SetError is already set by cert_VerifyFortezzaV1Cert **/
654 LOG_ERROR_OR_EXIT(log
,subjectCert
,0,0);
658 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
663 certsList
= PORT_ZNewArray(CERTCertificate
*, certsListLen
);
664 if (certsList
== NULL
)
667 /* RFC 3280 says that the name constraints will apply to the names
668 ** in the leaf (EE) cert, whether it is self issued or not, so
669 ** we pretend that it is not.
671 subjectCertIsSelfIssued
= PR_FALSE
;
672 for ( count
= 0; count
< CERT_MAX_CERT_CHAIN
; count
++ ) {
673 PRBool validCAOverride
= PR_FALSE
;
675 /* Construct a list of names for the current and all previous
676 * certifcates (except leaf (EE) certs, root CAs, and self-issued
677 * intermediate CAs) to be verified against the name constraints
678 * extension of the issuer certificate.
680 if (subjectCertIsSelfIssued
== PR_FALSE
) {
681 CERTGeneralName
*subjectNameList
;
682 int subjectNameListLen
;
684 subjectNameList
= CERT_GetCertificateNames(subjectCert
, arena
);
685 subjectNameListLen
= CERT_GetNamesLength(subjectNameList
);
686 if (certsListLen
<= namesCount
+ subjectNameListLen
) {
687 CERTCertificate
**tmpCertsList
;
688 certsListLen
= (namesCount
+ subjectNameListLen
) * 2;
690 (CERTCertificate
**)PORT_Realloc(certsList
,
691 certsListLen
* sizeof(CERTCertificate
*));
692 if (tmpCertsList
== NULL
) {
695 certsList
= tmpCertsList
;
697 for (i
= 0; i
< subjectNameListLen
; i
++) {
698 certsList
[namesCount
+ i
] = subjectCert
;
700 namesCount
+= subjectNameListLen
;
701 namesList
= cert_CombineNamesLists(namesList
, subjectNameList
);
704 /* check if the cert has an unsupported critical extension */
705 if ( subjectCert
->options
.bits
.hasUnsupportedCriticalExt
) {
706 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION
);
707 LOG_ERROR_OR_EXIT(log
,subjectCert
,count
,0);
710 /* find the certificate of the issuer */
711 issuerCert
= CERT_FindCertIssuer(subjectCert
, t
, certUsage
);
712 if ( ! issuerCert
) {
713 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER
);
714 LOG_ERROR(log
,subjectCert
,count
,0);
718 /* verify the signature on the cert */
720 rv
= CERT_VerifySignedData(&subjectCert
->signatureWrap
,
721 issuerCert
, t
, wincx
);
723 if ( rv
!= SECSuccess
) {
727 if ( PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE
) {
728 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
);
729 LOG_ERROR_OR_EXIT(log
,issuerCert
,count
+1,0);
731 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
732 LOG_ERROR_OR_EXIT(log
,subjectCert
,count
,0);
738 * XXX - fortezza may need error logging stuff added
741 rv
= cert_VerifyFortezzaV1Cert(handle
, issuerCert
, &last_type
,
742 last_type
, t
, wincx
);
743 if (rv
== SECFailure
) {
744 /**** PORT_SetError is already set by *
745 * cert_VerifyFortezzaV1Cert **/
746 LOG_ERROR_OR_EXIT(log
,subjectCert
,0,0);
750 /* If the basicConstraint extension is included in an immediate CA
751 * certificate, make sure that the isCA flag is on. If the
752 * pathLenConstraint component exists, it must be greater than the
753 * number of CA certificates we have seen so far. If the extension
754 * is omitted, we will assume that this is a CA certificate with
755 * an unlimited pathLenConstraint (since it already passes the
756 * netscape-cert-type extension checking).
758 * In the fortezza (V1) case, we've already checked the CA bits
759 * in the key, so we're presumed to be a CA; however we really don't
760 * want to bypass Basic constraint or netscape extension parsing.
762 * In Fortezza V2, basicConstraint will be set for every CA,PCA,PAA
765 rv
= CERT_FindBasicConstraintExten(issuerCert
, &basicConstraint
);
766 if ( rv
!= SECSuccess
) {
767 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND
) {
768 LOG_ERROR_OR_EXIT(log
,issuerCert
,count
+1,0);
770 pathLengthLimit
= CERT_UNLIMITED_PATH_CONSTRAINT
;
771 /* no basic constraints found, if we're fortezza, CA bit is already
772 * verified (isca = PR_TRUE). otherwise, we aren't (yet) a ca
776 if ( basicConstraint
.isCA
== PR_FALSE
) {
777 PORT_SetError (SEC_ERROR_CA_CERT_INVALID
);
778 LOG_ERROR_OR_EXIT(log
,issuerCert
,count
+1,0);
780 pathLengthLimit
= basicConstraint
.pathLenConstraint
;
783 /* make sure that the path len constraint is properly set.*/
784 if (pathLengthLimit
>= 0 && currentPathLen
> pathLengthLimit
) {
785 PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID
);
786 LOG_ERROR_OR_EXIT(log
, issuerCert
, count
+1, pathLengthLimit
);
789 /* XXX - the error logging may need to go down into CRL stuff at some
792 /* check revoked list (issuer) */
793 rv
= SEC_CheckCRL(handle
, subjectCert
, issuerCert
, t
, wincx
);
794 if (rv
== SECFailure
) {
798 LOG_ERROR_OR_EXIT(log
,subjectCert
,count
,0);
799 } else if (rv
== SECWouldBlock
) {
800 /* We found something fishy, so we intend to issue an
801 * error to the user, but the user may wish to continue
802 * processing, in which case we better make sure nothing
803 * worse has happened... so keep cranking the loop */
804 rvFinal
= SECFailure
;
808 LOG_ERROR(log
,subjectCert
,count
,0);
811 if ( issuerCert
->trust
) {
812 /* we have some trust info, but this does NOT imply that this
813 * cert is actually trusted for any purpose. The cert may be
814 * explicitly UNtrusted. We won't know until we examine the
817 if (certUsage
== certUsageStatusResponder
) {
818 /* XXX NSS has done this for years, but it seems incorrect. */
824 * check the trust parms of the issuer
826 if ( certUsage
== certUsageVerifyCA
) {
827 if ( subjectCert
->nsCertType
& NS_CERT_TYPE_EMAIL_CA
) {
828 trustType
= trustEmail
;
829 } else if ( subjectCert
->nsCertType
& NS_CERT_TYPE_SSL_CA
) {
830 trustType
= trustSSL
;
832 trustType
= trustObjectSigning
;
836 flags
= SEC_GET_TRUST_FLAGS(issuerCert
->trust
, trustType
);
838 if (flags
& CERTDB_VALID_CA
) {
839 if ( ( flags
& requiredFlags
) == requiredFlags
) {
840 /* we found a trusted one, so return */
844 validCAOverride
= PR_TRUE
;
848 if (!validCAOverride
) {
850 * Make sure that if this is an intermediate CA in the chain that
851 * it was given permission by its signer to be a CA.
854 * if basicConstraints says it is a ca, then we check the
855 * nsCertType. If the nsCertType has any CA bits set, then
856 * it must have the right one.
858 if (!isca
|| (issuerCert
->nsCertType
& NS_CERT_TYPE_CA
)) {
859 isca
= (issuerCert
->nsCertType
& caCertType
) ? PR_TRUE
: PR_FALSE
;
863 PORT_SetError(SEC_ERROR_CA_CERT_INVALID
);
864 LOG_ERROR_OR_EXIT(log
,issuerCert
,count
+1,0);
867 /* make sure key usage allows cert signing */
868 if (CERT_CheckKeyUsage(issuerCert
, requiredCAKeyUsage
) != SECSuccess
) {
869 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE
);
870 LOG_ERROR_OR_EXIT(log
,issuerCert
,count
+1,requiredCAKeyUsage
);
874 /* make sure that the entire chain is within the name space of the
875 ** current issuer certificate.
877 rv
= CERT_CompareNameSpace(issuerCert
, namesList
, certsList
,
879 if (rv
!= SECSuccess
|| badCert
!= NULL
) {
880 PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE
);
881 LOG_ERROR_OR_EXIT(log
, badCert
, count
+ 1, 0);
884 /* make sure that the issuer is not self signed. If it is, then
885 * stop here to prevent looping.
887 if (issuerCert
->isRoot
) {
888 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER
);
889 LOG_ERROR(log
, issuerCert
, count
+1, 0);
892 /* The issuer cert will be the subject cert in the next loop.
893 * A cert is self-issued if its subject and issuer are equal and
894 * both are of non-zero length.
896 subjectCertIsSelfIssued
= (PRBool
)
897 SECITEM_ItemsAreEqual(&issuerCert
->derIssuer
,
898 &issuerCert
->derSubject
) &&
899 issuerCert
->derSubject
.len
> 0;
900 if (subjectCertIsSelfIssued
== PR_FALSE
) {
901 /* RFC 3280 says only non-self-issued intermediate CA certs
902 * count in path length.
907 CERT_DestroyCertificate(subjectCert
);
908 subjectCert
= issuerCert
;
912 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER
);
913 LOG_ERROR(log
,subjectCert
,count
,0);
917 if (certsList
!= NULL
) {
918 PORT_Free(certsList
);
921 CERT_DestroyCertificate(issuerCert
);
925 CERT_DestroyCertificate(subjectCert
);
928 if ( arena
!= NULL
) {
929 PORT_FreeArena(arena
, PR_FALSE
);
935 CERT_VerifyCertChain(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
936 PRBool checkSig
, SECCertUsage certUsage
, int64 t
,
937 void *wincx
, CERTVerifyLog
*log
)
939 return cert_VerifyCertChain(handle
, cert
, checkSig
, NULL
, certUsage
, t
,
944 * verify that a CA can sign a certificate with the requested usage.
945 * XXX This function completely ignores cert path length constraints!
948 CERT_VerifyCACertForUsage(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
949 PRBool checkSig
, SECCertUsage certUsage
, int64 t
,
950 void *wincx
, CERTVerifyLog
*log
)
952 SECTrustType trustType
;
953 CERTBasicConstraints basicConstraint
;
955 PRBool validCAOverride
= PR_FALSE
;
957 SECComparison rvCompare
;
958 SECStatus rvFinal
= SECSuccess
;
960 unsigned int caCertType
;
961 unsigned int requiredCAKeyUsage
;
962 unsigned int requiredFlags
;
963 CERTCertificate
*issuerCert
;
966 if (CERT_KeyUsageAndTypeForCertUsage(certUsage
, PR_TRUE
,
968 &caCertType
) != SECSuccess
) {
970 EXIT_IF_NOT_LOGGING(log
);
971 requiredCAKeyUsage
= 0;
975 switch ( certUsage
) {
976 case certUsageSSLClient
:
977 case certUsageSSLServer
:
979 case certUsageSSLServerWithStepUp
:
980 case certUsageEmailSigner
:
981 case certUsageEmailRecipient
:
982 case certUsageObjectSigner
:
983 case certUsageVerifyCA
:
984 case certUsageStatusResponder
:
985 if ( CERT_TrustFlagsForCACertUsage(certUsage
, &requiredFlags
,
986 &trustType
) != SECSuccess
) {
988 EXIT_IF_NOT_LOGGING(log
);
990 trustType
= trustSSL
;
995 EXIT_IF_NOT_LOGGING(log
);
997 trustType
= trustSSL
;/* This used to be 0, but we need something
998 * that matches the enumeration type.
1003 /* If the basicConstraint extension is included in an intermmediate CA
1004 * certificate, make sure that the isCA flag is on. If the
1005 * pathLenConstraint component exists, it must be greater than the
1006 * number of CA certificates we have seen so far. If the extension
1007 * is omitted, we will assume that this is a CA certificate with
1008 * an unlimited pathLenConstraint (since it already passes the
1009 * netscape-cert-type extension checking).
1011 * In the fortezza (V1) case, we've already checked the CA bits
1012 * in the key, so we're presumed to be a CA; however we really don't
1013 * want to bypass Basic constraint or netscape extension parsing.
1015 * In Fortezza V2, basicConstraint will be set for every CA,PCA,PAA
1018 rv
= CERT_FindBasicConstraintExten(cert
, &basicConstraint
);
1019 if ( rv
!= SECSuccess
) {
1020 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND
) {
1021 LOG_ERROR_OR_EXIT(log
,cert
,0,0);
1023 /* no basic constraints found, if we're fortezza, CA bit is already
1024 * verified (isca = PR_TRUE). otherwise, we aren't (yet) a ca
1025 * isca = PR_FALSE */
1028 if ( basicConstraint
.isCA
== PR_FALSE
) {
1029 PORT_SetError (SEC_ERROR_CA_CERT_INVALID
);
1030 LOG_ERROR_OR_EXIT(log
,cert
,0,0);
1033 /* can't check path length if we don't know the previous path */
1037 if ( cert
->trust
) {
1038 /* we have some trust info, but this does NOT imply that this
1039 * cert is actually trusted for any purpose. The cert may be
1040 * explicitly UNtrusted. We won't know until we examine the
1043 if (certUsage
== certUsageStatusResponder
) {
1044 /* Check the special case of certUsageStatusResponder */
1045 issuerCert
= CERT_FindCertIssuer(cert
, t
, certUsage
);
1047 if (SEC_CheckCRL(handle
, cert
, issuerCert
, t
, wincx
)
1049 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE
);
1050 CERT_DestroyCertificate(issuerCert
);
1053 CERT_DestroyCertificate(issuerCert
);
1055 /* XXX We have NOT determined that this cert is trusted.
1056 * For years, NSS has treated this as trusted,
1057 * but it seems incorrect.
1064 * check the trust parms of the issuer
1066 flags
= SEC_GET_TRUST_FLAGS(cert
->trust
, trustType
);
1068 if (flags
& CERTDB_VALID_CA
) {
1069 if ( ( flags
& requiredFlags
) == requiredFlags
) {
1070 /* we found a trusted one, so return */
1074 validCAOverride
= PR_TRUE
;
1077 if (!validCAOverride
) {
1079 * Make sure that if this is an intermediate CA in the chain that
1080 * it was given permission by its signer to be a CA.
1083 * if basicConstraints says it is a ca, then we check the
1084 * nsCertType. If the nsCertType has any CA bits set, then
1085 * it must have the right one.
1087 if (!isca
|| (cert
->nsCertType
& NS_CERT_TYPE_CA
)) {
1088 isca
= (cert
->nsCertType
& caCertType
) ? PR_TRUE
: PR_FALSE
;
1092 PORT_SetError(SEC_ERROR_CA_CERT_INVALID
);
1093 LOG_ERROR_OR_EXIT(log
,cert
,0,0);
1096 /* make sure key usage allows cert signing */
1097 if (CERT_CheckKeyUsage(cert
, requiredCAKeyUsage
) != SECSuccess
) {
1098 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE
);
1099 LOG_ERROR_OR_EXIT(log
,cert
,0,requiredCAKeyUsage
);
1102 /* make sure that the issuer is not self signed. If it is, then
1103 * stop here to prevent looping.
1105 rvCompare
= SECITEM_CompareItem(&cert
->derSubject
, &cert
->derIssuer
);
1106 if (rvCompare
== SECEqual
) {
1107 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER
);
1108 LOG_ERROR(log
, cert
, 0, 0);
1112 return CERT_VerifyCertChain(handle
, cert
, checkSig
, certUsage
, t
,
1120 #define NEXT_USAGE() { \
1126 #define VALID_USAGE() { \
1130 #define INVALID_USAGE() { \
1131 if (returnedUsages) { \
1132 *returnedUsages &= (~i); \
1134 if (PR_TRUE == requiredUsage) { \
1135 valid = SECFailure; \
1141 * verify a certificate by checking if it's valid and that we
1144 * certificateUsage contains a bitfield of all cert usages that are
1145 * required for verification to succeed
1147 * a bitfield of cert usages is returned in *returnedUsages
1148 * if requiredUsages is non-zero, the returned bitmap is only
1149 * for those required usages, otherwise it is for all usages
1153 CERT_VerifyCertificate(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
1154 PRBool checkSig
, SECCertificateUsage requiredUsages
, int64 t
,
1155 void *wincx
, CERTVerifyLog
*log
, SECCertificateUsage
* returnedUsages
)
1159 unsigned int requiredKeyUsage
;
1160 unsigned int requiredCertType
;
1162 unsigned int certType
;
1163 PRBool allowOverride
;
1164 SECCertTimeValidity validity
;
1165 CERTStatusConfig
*statusConfig
;
1167 SECCertUsage certUsage
= 0;
1168 PRBool checkedOCSP
= PR_FALSE
;
1169 PRBool checkAllUsages
= PR_FALSE
;
1170 PRBool revoked
= PR_FALSE
;
1171 PRBool sigerror
= PR_FALSE
;
1173 if (!requiredUsages
) {
1174 /* there are no required usages, so the user probably wants to
1175 get status for all usages */
1176 checkAllUsages
= PR_TRUE
;
1179 if (returnedUsages
) {
1180 *returnedUsages
= 0;
1182 /* we don't have a place to return status for all usages,
1183 so we can skip checks for usages that aren't required */
1184 checkAllUsages
= PR_FALSE
;
1186 valid
= SECSuccess
; /* start off assuming cert is valid */
1188 /* make sure that the cert is valid at time t */
1189 allowOverride
= (PRBool
)((requiredUsages
& certificateUsageSSLServer
) ||
1190 (requiredUsages
& certificateUsageSSLServerWithStepUp
));
1191 validity
= CERT_CheckCertValidTimes(cert
, t
, allowOverride
);
1192 if ( validity
!= secCertTimeValid
) {
1194 LOG_ERROR_OR_EXIT(log
,cert
,0,validity
);
1197 /* check key usage and netscape cert type */
1198 cert_GetCertType(cert
);
1199 certType
= cert
->nsCertType
;
1201 for (i
=1; i
<=certificateUsageHighest
&&
1202 (SECSuccess
== valid
|| returnedUsages
|| log
) ; ) {
1203 PRBool requiredUsage
= (i
& requiredUsages
) ? PR_TRUE
: PR_FALSE
;
1204 if (PR_FALSE
== requiredUsage
&& PR_FALSE
== checkAllUsages
) {
1207 if (returnedUsages
) {
1208 *returnedUsages
|= i
; /* start off assuming this usage is valid */
1210 switch ( certUsage
) {
1211 case certUsageSSLClient
:
1212 case certUsageSSLServer
:
1213 case certUsageSSLServerWithStepUp
:
1214 case certUsageSSLCA
:
1215 case certUsageEmailSigner
:
1216 case certUsageEmailRecipient
:
1217 case certUsageObjectSigner
:
1218 case certUsageStatusResponder
:
1219 rv
= CERT_KeyUsageAndTypeForCertUsage(certUsage
, PR_FALSE
,
1222 if ( rv
!= SECSuccess
) {
1224 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
1225 requiredKeyUsage
= 0;
1226 requiredCertType
= 0;
1231 case certUsageAnyCA
:
1232 case certUsageProtectedObjectSigner
:
1233 case certUsageUserCertImport
:
1234 case certUsageVerifyCA
:
1235 /* these usages cannot be verified */
1240 requiredKeyUsage
= 0;
1241 requiredCertType
= 0;
1244 if ( CERT_CheckKeyUsage(cert
, requiredKeyUsage
) != SECSuccess
) {
1245 if (PR_TRUE
== requiredUsage
) {
1246 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE
);
1248 LOG_ERROR(log
,cert
,0,requiredKeyUsage
);
1251 if ( !( certType
& requiredCertType
) ) {
1252 if (PR_TRUE
== requiredUsage
) {
1253 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE
);
1255 LOG_ERROR(log
,cert
,0,requiredCertType
);
1259 /* check trust flags to see if this cert is directly trusted */
1260 if ( cert
->trust
) { /* the cert is in the DB */
1261 switch ( certUsage
) {
1262 case certUsageSSLClient
:
1263 case certUsageSSLServer
:
1264 flags
= cert
->trust
->sslFlags
;
1266 /* is the cert directly trusted or not trusted ? */
1267 if ( flags
& CERTDB_VALID_PEER
) {/*the trust record is valid*/
1268 if ( flags
& CERTDB_TRUSTED
) { /* trust this cert */
1270 } else { /* don't trust this cert */
1271 if (PR_TRUE
== requiredUsage
) {
1272 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
1274 LOG_ERROR(log
,cert
,0,flags
);
1279 case certUsageSSLServerWithStepUp
:
1280 /* XXX - step up certs can't be directly trusted */
1282 case certUsageSSLCA
:
1284 case certUsageEmailSigner
:
1285 case certUsageEmailRecipient
:
1286 flags
= cert
->trust
->emailFlags
;
1288 /* is the cert directly trusted or not trusted ? */
1289 if ( ( flags
& ( CERTDB_VALID_PEER
| CERTDB_TRUSTED
) ) ==
1290 ( CERTDB_VALID_PEER
| CERTDB_TRUSTED
) ) {
1294 case certUsageObjectSigner
:
1295 flags
= cert
->trust
->objectSigningFlags
;
1297 /* is the cert directly trusted or not trusted ? */
1298 if ( flags
& CERTDB_VALID_PEER
) {/*the trust record is valid*/
1299 if ( flags
& CERTDB_TRUSTED
) { /* trust this cert */
1301 } else { /* don't trust this cert */
1302 if (PR_TRUE
== requiredUsage
) {
1303 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
1305 LOG_ERROR(log
,cert
,0,flags
);
1310 case certUsageVerifyCA
:
1311 case certUsageStatusResponder
:
1312 flags
= cert
->trust
->sslFlags
;
1313 /* is the cert directly trusted or not trusted ? */
1314 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1315 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1318 flags
= cert
->trust
->emailFlags
;
1319 /* is the cert directly trusted or not trusted ? */
1320 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1321 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1324 flags
= cert
->trust
->objectSigningFlags
;
1325 /* is the cert directly trusted or not trusted ? */
1326 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1327 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1331 case certUsageAnyCA
:
1332 case certUsageProtectedObjectSigner
:
1333 case certUsageUserCertImport
:
1334 /* XXX to make the compiler happy. Should these be
1335 * explicitly handled?
1341 if (PR_TRUE
== revoked
|| PR_TRUE
== sigerror
) {
1345 rv
= cert_VerifyCertChain(handle
, cert
,
1346 checkSig
, &sigerror
,
1347 certUsage
, t
, wincx
, log
,
1350 if (rv
!= SECSuccess
) {
1351 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
1356 * Check OCSP revocation status, but only if the cert we are checking
1357 * is not a status reponder itself. We only do this in the case
1358 * where we checked the cert chain (above); explicit trust "wins"
1359 * (avoids status checking, just as it avoids CRL checking) by
1360 * bypassing this code.
1363 if (PR_FALSE
== checkedOCSP
) {
1364 checkedOCSP
= PR_TRUE
; /* only check OCSP once */
1365 statusConfig
= CERT_GetStatusConfig(handle
);
1366 if (requiredUsages
!= certificateUsageStatusResponder
&&
1367 statusConfig
!= NULL
) {
1368 if (statusConfig
->statusChecker
!= NULL
) {
1369 rv
= (* statusConfig
->statusChecker
)(handle
, cert
,
1371 if (rv
!= SECSuccess
) {
1372 LOG_ERROR(log
,cert
,0,0);
1387 /* obsolete, do not use for new code */
1389 CERT_VerifyCert(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
1390 PRBool checkSig
, SECCertUsage certUsage
, int64 t
,
1391 void *wincx
, CERTVerifyLog
*log
)
1394 unsigned int requiredKeyUsage
;
1395 unsigned int requiredCertType
;
1397 unsigned int certType
;
1398 PRBool allowOverride
;
1399 SECCertTimeValidity validity
;
1400 CERTStatusConfig
*statusConfig
;
1403 /* check if this cert is in the Evil list */
1404 rv
= CERT_CheckForEvilCert(cert
);
1405 if ( rv
!= SECSuccess
) {
1406 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE
);
1407 LOG_ERROR_OR_EXIT(log
,cert
,0,0);
1411 /* make sure that the cert is valid at time t */
1412 allowOverride
= (PRBool
)((certUsage
== certUsageSSLServer
) ||
1413 (certUsage
== certUsageSSLServerWithStepUp
));
1414 validity
= CERT_CheckCertValidTimes(cert
, t
, allowOverride
);
1415 if ( validity
!= secCertTimeValid
) {
1416 LOG_ERROR_OR_EXIT(log
,cert
,0,validity
);
1419 /* check key usage and netscape cert type */
1420 cert_GetCertType(cert
);
1421 certType
= cert
->nsCertType
;
1422 switch ( certUsage
) {
1423 case certUsageSSLClient
:
1424 case certUsageSSLServer
:
1425 case certUsageSSLServerWithStepUp
:
1426 case certUsageSSLCA
:
1427 case certUsageEmailSigner
:
1428 case certUsageEmailRecipient
:
1429 case certUsageObjectSigner
:
1430 case certUsageStatusResponder
:
1431 rv
= CERT_KeyUsageAndTypeForCertUsage(certUsage
, PR_FALSE
,
1434 if ( rv
!= SECSuccess
) {
1436 EXIT_IF_NOT_LOGGING(log
);
1437 requiredKeyUsage
= 0;
1438 requiredCertType
= 0;
1441 case certUsageVerifyCA
:
1442 requiredKeyUsage
= KU_KEY_CERT_SIGN
;
1443 requiredCertType
= NS_CERT_TYPE_CA
;
1444 if ( ! ( certType
& NS_CERT_TYPE_CA
) ) {
1445 certType
|= NS_CERT_TYPE_CA
;
1450 EXIT_IF_NOT_LOGGING(log
);
1451 requiredKeyUsage
= 0;
1452 requiredCertType
= 0;
1454 if ( CERT_CheckKeyUsage(cert
, requiredKeyUsage
) != SECSuccess
) {
1455 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE
);
1456 LOG_ERROR_OR_EXIT(log
,cert
,0,requiredKeyUsage
);
1458 if ( !( certType
& requiredCertType
) ) {
1459 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE
);
1460 LOG_ERROR_OR_EXIT(log
,cert
,0,requiredCertType
);
1463 /* check trust flags to see if this cert is directly trusted */
1464 if ( cert
->trust
) { /* the cert is in the DB */
1465 switch ( certUsage
) {
1466 case certUsageSSLClient
:
1467 case certUsageSSLServer
:
1468 flags
= cert
->trust
->sslFlags
;
1470 /* is the cert directly trusted or not trusted ? */
1471 if ( flags
& CERTDB_VALID_PEER
) {/*the trust record is valid*/
1472 if ( flags
& CERTDB_TRUSTED
) { /* trust this cert */
1474 } else { /* don't trust this cert */
1475 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
1476 LOG_ERROR_OR_EXIT(log
,cert
,0,flags
);
1480 case certUsageSSLServerWithStepUp
:
1481 /* XXX - step up certs can't be directly trusted */
1483 case certUsageSSLCA
:
1485 case certUsageEmailSigner
:
1486 case certUsageEmailRecipient
:
1487 flags
= cert
->trust
->emailFlags
;
1489 /* is the cert directly trusted or not trusted ? */
1490 if ( ( flags
& ( CERTDB_VALID_PEER
| CERTDB_TRUSTED
) ) ==
1491 ( CERTDB_VALID_PEER
| CERTDB_TRUSTED
) ) {
1495 case certUsageObjectSigner
:
1496 flags
= cert
->trust
->objectSigningFlags
;
1498 /* is the cert directly trusted or not trusted ? */
1499 if ( flags
& CERTDB_VALID_PEER
) {/*the trust record is valid*/
1500 if ( flags
& CERTDB_TRUSTED
) { /* trust this cert */
1502 } else { /* don't trust this cert */
1503 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
1504 LOG_ERROR_OR_EXIT(log
,cert
,0,flags
);
1508 case certUsageVerifyCA
:
1509 case certUsageStatusResponder
:
1510 flags
= cert
->trust
->sslFlags
;
1511 /* is the cert directly trusted or not trusted ? */
1512 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1513 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1516 flags
= cert
->trust
->emailFlags
;
1517 /* is the cert directly trusted or not trusted ? */
1518 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1519 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1522 flags
= cert
->trust
->objectSigningFlags
;
1523 /* is the cert directly trusted or not trusted ? */
1524 if ( ( flags
& ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) ==
1525 ( CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
) ) {
1529 case certUsageAnyCA
:
1530 case certUsageProtectedObjectSigner
:
1531 case certUsageUserCertImport
:
1532 /* XXX to make the compiler happy. Should these be
1533 * explicitly handled?
1539 rv
= CERT_VerifyCertChain(handle
, cert
, checkSig
, certUsage
,
1541 if (rv
!= SECSuccess
) {
1542 EXIT_IF_NOT_LOGGING(log
);
1546 * Check revocation status, but only if the cert we are checking
1547 * is not a status reponder itself. We only do this in the case
1548 * where we checked the cert chain (above); explicit trust "wins"
1549 * (avoids status checking, just as it avoids CRL checking, which
1550 * is all done inside VerifyCertChain) by bypassing this code.
1552 statusConfig
= CERT_GetStatusConfig(handle
);
1553 if (certUsage
!= certUsageStatusResponder
&& statusConfig
!= NULL
) {
1554 if (statusConfig
->statusChecker
!= NULL
) {
1555 rv
= (* statusConfig
->statusChecker
)(handle
, cert
,
1557 if (rv
!= SECSuccess
) {
1558 LOG_ERROR_OR_EXIT(log
,cert
,0,0);
1573 * verify a certificate by checking if its valid and that we
1574 * trust the issuer. Verify time against now.
1577 CERT_VerifyCertificateNow(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
1578 PRBool checkSig
, SECCertificateUsage requiredUsages
,
1579 void *wincx
, SECCertificateUsage
* returnedUsages
)
1581 return(CERT_VerifyCertificate(handle
, cert
, checkSig
,
1582 requiredUsages
, PR_Now(), wincx
, NULL
, returnedUsages
));
1585 /* obsolete, do not use for new code */
1587 CERT_VerifyCertNow(CERTCertDBHandle
*handle
, CERTCertificate
*cert
,
1588 PRBool checkSig
, SECCertUsage certUsage
, void *wincx
)
1590 return(CERT_VerifyCert(handle
, cert
, checkSig
,
1591 certUsage
, PR_Now(), wincx
, NULL
));
1595 /* [ FROM pcertdb.c ] */
1597 * Supported usage values and types:
1598 * certUsageSSLClient
1599 * certUsageSSLServer
1600 * certUsageSSLServerWithStepUp
1601 * certUsageEmailSigner
1602 * certUsageEmailRecipient
1603 * certUsageObjectSigner
1607 CERT_FindMatchingCert(CERTCertDBHandle
*handle
, SECItem
*derName
,
1608 CERTCertOwner owner
, SECCertUsage usage
,
1609 PRBool preferTrusted
, int64 validTime
, PRBool validOnly
)
1611 CERTCertList
*certList
= NULL
;
1612 CERTCertificate
*cert
= NULL
;
1613 unsigned int requiredTrustFlags
;
1614 SECTrustType requiredTrustType
;
1617 PRBool lookingForCA
= PR_FALSE
;
1619 CERTCertListNode
*node
;
1620 CERTCertificate
*saveUntrustedCA
= NULL
;
1622 /* if preferTrusted is set, must be a CA cert */
1623 PORT_Assert( ! ( preferTrusted
&& ( owner
!= certOwnerCA
) ) );
1625 if ( owner
== certOwnerCA
) {
1626 lookingForCA
= PR_TRUE
;
1627 if ( preferTrusted
) {
1628 rv
= CERT_TrustFlagsForCACertUsage(usage
, &requiredTrustFlags
,
1629 &requiredTrustType
);
1630 if ( rv
!= SECSuccess
) {
1633 requiredTrustFlags
|= CERTDB_VALID_CA
;
1637 certList
= CERT_CreateSubjectCertList(NULL
, handle
, derName
, validTime
,
1639 if ( certList
!= NULL
) {
1640 rv
= CERT_FilterCertListByUsage(certList
, usage
, lookingForCA
);
1641 if ( rv
!= SECSuccess
) {
1645 node
= CERT_LIST_HEAD(certList
);
1647 while ( !CERT_LIST_END(node
, certList
) ) {
1650 /* looking for a trusted CA cert */
1651 if ( ( owner
== certOwnerCA
) && preferTrusted
&&
1652 ( requiredTrustType
!= trustTypeNone
) ) {
1654 if ( cert
->trust
== NULL
) {
1657 flags
= SEC_GET_TRUST_FLAGS(cert
->trust
, requiredTrustType
);
1660 if ( ( flags
& requiredTrustFlags
) != requiredTrustFlags
) {
1661 /* cert is not trusted */
1662 /* if this is the first cert to get this far, then save
1663 * it, so we can use it if we can't find a trusted one
1665 if ( saveUntrustedCA
== NULL
) {
1666 saveUntrustedCA
= cert
;
1671 /* if we got this far, then this cert meets all criteria */
1675 node
= CERT_LIST_NEXT(node
);
1679 /* use the saved one if we have it */
1680 if ( cert
== NULL
) {
1681 cert
= saveUntrustedCA
;
1684 /* if we found one then bump the ref count before freeing the list */
1685 if ( cert
!= NULL
) {
1686 /* bump the ref count */
1687 cert
= CERT_DupCertificate(cert
);
1690 CERT_DestroyCertList(certList
);
1696 if ( certList
!= NULL
) {
1697 CERT_DestroyCertList(certList
);
1704 /* [ From certdb.c ] */
1706 * Filter a list of certificates, removing those certs that do not have
1707 * one of the named CA certs somewhere in their cert chain.
1709 * "certList" - the list of certificates to filter
1710 * "nCANames" - number of CA names
1711 * "caNames" - array of CA names in string(rfc 1485) form
1712 * "usage" - what use the certs are for, this is used when
1713 * selecting CA certs
1716 CERT_FilterCertListByCANames(CERTCertList
*certList
, int nCANames
,
1717 char **caNames
, SECCertUsage usage
)
1719 CERTCertificate
*issuerCert
= NULL
;
1720 CERTCertificate
*subjectCert
;
1721 CERTCertListNode
*node
, *freenode
;
1722 CERTCertificate
*cert
;
1728 if ( nCANames
<= 0 ) {
1734 node
= CERT_LIST_HEAD(certList
);
1736 while ( ! CERT_LIST_END(node
, certList
) ) {
1739 subjectCert
= CERT_DupCertificate(cert
);
1741 /* traverse the CA certs for this cert */
1743 while ( subjectCert
!= NULL
) {
1747 if (subjectCert
->issuerName
!= NULL
) {
1749 if ( PORT_Strcmp(*names
, subjectCert
->issuerName
) == 0 ) {
1763 issuerCert
= CERT_FindCertIssuer(subjectCert
, time
, usage
);
1764 if ( issuerCert
== subjectCert
) {
1765 CERT_DestroyCertificate(issuerCert
);
1769 CERT_DestroyCertificate(subjectCert
);
1770 subjectCert
= issuerCert
;
1773 CERT_DestroyCertificate(subjectCert
);
1775 /* CA was not found, so remove this cert from the list */
1777 node
= CERT_LIST_NEXT(node
);
1778 CERT_RemoveCertListNode(freenode
);
1780 /* CA was found, so leave it in the list */
1781 node
= CERT_LIST_NEXT(node
);
1789 * Given a certificate, return a string containing the nickname, and possibly
1790 * one of the validity strings, based on the current validity state of the
1793 * "arena" - arena to allocate returned string from. If NULL, then heap
1795 * "cert" - the cert to get nickname from
1796 * "expiredString" - the string to append to the nickname if the cert is
1798 * "notYetGoodString" - the string to append to the nickname if the cert is
1802 CERT_GetCertNicknameWithValidity(PRArenaPool
*arena
, CERTCertificate
*cert
,
1803 char *expiredString
, char *notYetGoodString
)
1805 SECCertTimeValidity validity
;
1806 char *nickname
= NULL
, *tmpstr
= NULL
;
1808 validity
= CERT_CheckCertValidTimes(cert
, PR_Now(), PR_FALSE
);
1810 /* if the cert is good, then just use the nickname directly */
1811 if ( validity
== secCertTimeValid
) {
1812 if ( arena
== NULL
) {
1813 nickname
= PORT_Strdup(cert
->nickname
);
1815 nickname
= PORT_ArenaStrdup(arena
, cert
->nickname
);
1818 if ( nickname
== NULL
) {
1823 /* if the cert is not valid, then tack one of the strings on the
1826 if ( validity
== secCertTimeExpired
) {
1827 tmpstr
= PR_smprintf("%s%s", cert
->nickname
,
1829 } else if ( validity
== secCertTimeNotValidYet
) {
1831 tmpstr
= PR_smprintf("%s%s", cert
->nickname
,
1835 tmpstr
= PR_smprintf("%s",
1836 "(NULL) (Validity Unknown)");
1839 if ( tmpstr
== NULL
) {
1844 /* copy the string into the arena and free the malloc'd one */
1845 nickname
= PORT_ArenaStrdup(arena
, tmpstr
);
1850 if ( nickname
== NULL
) {
1861 * Collect the nicknames from all certs in a CertList. If the cert is not
1862 * valid, append a string to that nickname.
1864 * "certList" - the list of certificates
1865 * "expiredString" - the string to append to the nickname of any expired cert
1866 * "notYetGoodString" - the string to append to the nickname of any cert
1867 * that is not yet valid
1870 CERT_NicknameStringsFromCertList(CERTCertList
*certList
, char *expiredString
,
1871 char *notYetGoodString
)
1873 CERTCertNicknames
*names
;
1875 CERTCertListNode
*node
;
1878 /* allocate an arena */
1879 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1880 if ( arena
== NULL
) {
1884 /* allocate the structure */
1885 names
= PORT_ArenaAlloc(arena
, sizeof(CERTCertNicknames
));
1886 if ( names
== NULL
) {
1890 /* init the structure */
1891 names
->arena
= arena
;
1893 names
->numnicknames
= 0;
1894 names
->nicknames
= NULL
;
1895 names
->totallen
= 0;
1897 /* count the certs in the list */
1898 node
= CERT_LIST_HEAD(certList
);
1899 while ( ! CERT_LIST_END(node
, certList
) ) {
1900 names
->numnicknames
++;
1901 node
= CERT_LIST_NEXT(node
);
1904 /* allocate nicknames array */
1905 names
->nicknames
= PORT_ArenaAlloc(arena
,
1906 sizeof(char *) * names
->numnicknames
);
1907 if ( names
->nicknames
== NULL
) {
1911 /* just in case printf can't deal with null strings */
1912 if (expiredString
== NULL
) {
1916 if ( notYetGoodString
== NULL
) {
1917 notYetGoodString
= "";
1920 /* traverse the list of certs and collect the nicknames */
1921 nn
= names
->nicknames
;
1922 node
= CERT_LIST_HEAD(certList
);
1923 while ( ! CERT_LIST_END(node
, certList
) ) {
1924 *nn
= CERT_GetCertNicknameWithValidity(arena
, node
->cert
,
1927 if ( *nn
== NULL
) {
1931 names
->totallen
+= PORT_Strlen(*nn
);
1934 node
= CERT_LIST_NEXT(node
);
1940 PORT_FreeArena(arena
, PR_FALSE
);
1945 * Extract the nickname from a nickmake string that may have either
1946 * expiredString or notYetGoodString appended.
1949 * "namestring" - the string containing the nickname, and possibly
1950 * one of the validity label strings
1951 * "expiredString" - the expired validity label string
1952 * "notYetGoodString" - the not yet good validity label string
1954 * Returns the raw nickname
1957 CERT_ExtractNicknameString(char *namestring
, char *expiredString
,
1958 char *notYetGoodString
)
1960 int explen
, nyglen
, namelen
;
1964 namelen
= PORT_Strlen(namestring
);
1965 explen
= PORT_Strlen(expiredString
);
1966 nyglen
= PORT_Strlen(notYetGoodString
);
1968 if ( namelen
> explen
) {
1969 if ( PORT_Strcmp(expiredString
, &namestring
[namelen
-explen
]) == 0 ) {
1970 retlen
= namelen
- explen
;
1971 retstr
= (char *)PORT_Alloc(retlen
+1);
1972 if ( retstr
== NULL
) {
1976 PORT_Memcpy(retstr
, namestring
, retlen
);
1977 retstr
[retlen
] = '\0';
1982 if ( namelen
> nyglen
) {
1983 if ( PORT_Strcmp(notYetGoodString
, &namestring
[namelen
-nyglen
]) == 0) {
1984 retlen
= namelen
- nyglen
;
1985 retstr
= (char *)PORT_Alloc(retlen
+1);
1986 if ( retstr
== NULL
) {
1990 PORT_Memcpy(retstr
, namestring
, retlen
);
1991 retstr
[retlen
] = '\0';
1996 /* if name string is shorter than either invalid string, then it must
1999 retstr
= PORT_Strdup(namestring
);
2009 CERT_GetCertChainFromCert(CERTCertificate
*cert
, int64 time
, SECCertUsage usage
)
2011 CERTCertList
*chain
= NULL
;
2017 cert
= CERT_DupCertificate(cert
);
2019 PORT_SetError(SEC_ERROR_NO_MEMORY
);
2023 chain
= CERT_NewCertList();
2024 if (NULL
== chain
) {
2025 PORT_SetError(SEC_ERROR_NO_MEMORY
);
2029 while (cert
!= NULL
) {
2030 if (SECSuccess
!= CERT_AddCertToListTail(chain
, cert
)) {
2031 /* return partial chain */
2032 PORT_SetError(SEC_ERROR_NO_MEMORY
);
2036 if (SECITEM_CompareItem(&cert
->derIssuer
, &cert
->derSubject
)
2038 /* return complete chain */
2042 cert
= CERT_FindCertIssuer(cert
, time
, usage
);
2045 /* return partial chain */
2046 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER
);