security/nss/lib/certhigh/certvfy.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include "nspr.h"
     5 #include "secerr.h"
     6 #include "secport.h"
     7 #include "seccomon.h"
     8 #include "secoid.h"
     9 #include "sslerr.h"
    10 #include "genname.h"
    11 #include "keyhi.h"
    12 #include "cert.h"
    13 #include "certdb.h"
    14 #include "certi.h"
    15 #include "cryptohi.h"
    16 #include "pkix.h"
    17 /*#include "pkix_sample_modules.h" */
    18 #include "pkix_pl_cert.h"
    21 #include "nsspki.h"
    22 #include "pkitm.h"
    23 #include "pkim.h"
    24 #include "pki3hack.h"
    25 #include "base.h"
    27 /*
    28  * Check the validity times of a certificate
    29  */
    30 SECStatus
    31 CERT_CertTimesValid(CERTCertificate *c)
    32 {
    33     SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE);
    34     return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
    35 }
    37 /*
    38  * verify the signature of a signed data object with the given DER publickey
    39  */
    40 SECStatus
    41 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
    42                                    SECKEYPublicKey *pubKey,
    43 		                   void *wincx)
    44 {
    45     SECStatus        rv;
    46     SECItem          sig;
    47     SECOidTag        hashAlg = SEC_OID_UNKNOWN;
    49     if ( !pubKey || !sd ) {
    50 	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    51 	return SECFailure;
    52     }
    54     /* check the signature */
    55     sig = sd->signature;
    56     /* convert sig->len from bit counts to byte count. */
    57     DER_ConvertBitString(&sig);
    59     rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, 
    60 			&sig, &sd->signatureAlgorithm, &hashAlg, wincx);
    61     if (rv == SECSuccess) {
    62         /* Are we honoring signatures for this algorithm?  */
    63 	PRUint32 policyFlags = 0;
    64 	rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
    65 	if (rv == SECSuccess && 
    66 	    !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
    67 	    PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
    68 	    rv = SECFailure;
    69 	}
    70     }
    71     return rv;
    72 }
    74 /*
    75  * verify the signature of a signed data object with the given DER publickey
    76  */
    77 SECStatus
    78 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, 
    79                                        CERTSubjectPublicKeyInfo *pubKeyInfo,
    80 		                       void *wincx)
    81 {
    82     SECKEYPublicKey *pubKey;
    83     SECStatus        rv		= SECFailure;
    85     /* get cert's public key */
    86     pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
    87     if (pubKey) {
    88 	rv =  CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
    89 	SECKEY_DestroyPublicKey(pubKey);
    90     }
    91     return rv;
    92 }
    94 /*
    95  * verify the signature of a signed data object with the given certificate
    96  */
    97 SECStatus
    98 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
    99 		      PRTime t, void *wincx)
   100 {
   101     SECKEYPublicKey *pubKey = 0;
   102     SECStatus        rv     = SECFailure;
   103     SECCertTimeValidity validity;
   105     /* check the certificate's validity */
   106     validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
   107     if ( validity != secCertTimeValid ) {
   108 	return rv;
   109     }
   111     /* get cert's public key */
   112     pubKey = CERT_ExtractPublicKey(cert);
   113     if (pubKey) {
   114 	rv =  CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
   115 	SECKEY_DestroyPublicKey(pubKey);
   116     }
   117     return rv;
   118 }
   121 SECStatus
   122 SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert,
   123 	     CERTCertificate *caCert, PRTime t, void * wincx)
   124 {
   125     return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
   126 }
   128 /*
   129  * Find the issuer of a cert.  Use the authorityKeyID if it exists.
   130  */
   131 CERTCertificate *
   132 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage)
   133 {
   134     NSSCertificate *me;
   135     NSSTime *nssTime;
   136     NSSTrustDomain *td;
   137     NSSCryptoContext *cc;
   138     NSSCertificate *chain[3];
   139     NSSUsage nssUsage;
   140     PRStatus status;
   142     me = STAN_GetNSSCertificate(cert);
   143     if (!me) {
   144         PORT_SetError(SEC_ERROR_NO_MEMORY);
   145 	return NULL;
   146     }
   147     nssTime = NSSTime_SetPRTime(NULL, validTime);
   148     nssUsage.anyUsage = PR_FALSE;
   149     nssUsage.nss3usage = usage;
   150     nssUsage.nss3lookingForCA = PR_TRUE;
   151     memset(chain, 0, 3*sizeof(NSSCertificate *));
   152     td   = STAN_GetDefaultTrustDomain();
   153     cc = STAN_GetDefaultCryptoContext();
   154     (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, 
   155                                     chain, 2, NULL, &status, td, cc);
   156     nss_ZFreeIf(nssTime);
   157     if (status == PR_SUCCESS) {
   158 	PORT_Assert(me == chain[0]);
   159 	/* if it's a root, the chain will only have one cert */
   160 	if (!chain[1]) {
   161 	    /* already has a reference from the call to BuildChain */
   162 	    return cert;
   163 	} 
   164 	NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
   165 	return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
   166     } 
   167     if (chain[0]) {
   168 	PORT_Assert(me == chain[0]);
   169 	NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
   170     }
   171     PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER);
   172     return NULL;
   173 }
   175 /*
   176  * return required trust flags for various cert usages for CAs
   177  */
   178 SECStatus
   179 CERT_TrustFlagsForCACertUsage(SECCertUsage usage,
   180 			      unsigned int *retFlags,
   181 			      SECTrustType *retTrustType)
   182 {
   183     unsigned int requiredFlags;
   184     SECTrustType trustType;
   186     switch ( usage ) {
   187       case certUsageSSLClient:
   188 	requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
   189 	trustType = trustSSL;
   190         break;
   191       case certUsageSSLServer:
   192       case certUsageSSLCA:
   193 	requiredFlags = CERTDB_TRUSTED_CA;
   194 	trustType = trustSSL;
   195         break;
   196       case certUsageSSLServerWithStepUp:
   197 	requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
   198 	trustType = trustSSL;
   199         break;
   200       case certUsageEmailSigner:
   201       case certUsageEmailRecipient:
   202 	requiredFlags = CERTDB_TRUSTED_CA;
   203 	trustType = trustEmail;
   204 	break;
   205       case certUsageObjectSigner:
   206 	requiredFlags = CERTDB_TRUSTED_CA;
   207 	trustType = trustObjectSigning;
   208 	break;
   209       case certUsageVerifyCA:
   210       case certUsageAnyCA:
   211       case certUsageStatusResponder:
   212 	requiredFlags = CERTDB_TRUSTED_CA;
   213 	trustType = trustTypeNone;
   214 	break;
   215       default:
   216 	PORT_Assert(0);
   217 	goto loser;
   218     }
   219     if ( retFlags != NULL ) {
   220 	*retFlags = requiredFlags;
   221     }
   222     if ( retTrustType != NULL ) {
   223 	*retTrustType = trustType;
   224     }
   226     return(SECSuccess);
   227 loser:
   228     return(SECFailure);
   229 }
   231 void
   232 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
   233 	       unsigned int depth, void *arg)
   234 {
   235     CERTVerifyLogNode *node, *tnode;
   237     PORT_Assert(log != NULL);
   239     node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
   240 						sizeof(CERTVerifyLogNode));
   241     if ( node != NULL ) {
   242 	node->cert = CERT_DupCertificate(cert);
   243 	node->error = error;
   244 	node->depth = depth;
   245 	node->arg = arg;
   247 	if ( log->tail == NULL ) {
   248 	    /* empty list */
   249 	    log->head = log->tail = node;
   250 	    node->prev = NULL;
   251 	    node->next = NULL;
   252 	} else if ( depth >= log->tail->depth ) {
   253 	    /* add to tail */
   254 	    node->prev = log->tail;
   255 	    log->tail->next = node;
   256 	    log->tail = node;
   257 	    node->next = NULL;
   258 	} else if ( depth < log->head->depth ) {
   259 	    /* add at head */
   260 	    node->prev = NULL;
   261 	    node->next = log->head;
   262 	    log->head->prev = node;
   263 	    log->head = node;
   264 	} else {
   265 	    /* add in middle */
   266 	    tnode = log->tail;
   267 	    while ( tnode != NULL ) {
   268 		if ( depth >= tnode->depth ) {
   269 		    /* insert after tnode */
   270 		    node->prev = tnode;
   271 		    node->next = tnode->next;
   272 		    tnode->next->prev = node;
   273 		    tnode->next = node;
   274 		    break;
   275 		}
   277 		tnode = tnode->prev;
   278 	    }
   279 	}
   281 	log->count++;
   282     }
   283     return;
   284 }
   286 #define EXIT_IF_NOT_LOGGING(log) \
   287     if ( log == NULL ) { \
   288 	goto loser; \
   289     }
   291 #define LOG_ERROR_OR_EXIT(log,cert,depth,arg) \
   292     if ( log != NULL ) { \
   293 	cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
   294 			    (void *)(PRWord)arg); \
   295     } else { \
   296 	goto loser; \
   297     }
   299 #define LOG_ERROR(log,cert,depth,arg) \
   300     if ( log != NULL ) { \
   301 	cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
   302 			    (void *)(PRWord)arg); \
   303     }
   305 static SECStatus
   306 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
   307 		     PRBool checkSig, PRBool* sigerror,
   308                      SECCertUsage certUsage, PRTime t, void *wincx,
   309                      CERTVerifyLog *log, PRBool* revoked)
   310 {
   311     SECTrustType trustType;
   312     CERTBasicConstraints basicConstraint;
   313     CERTCertificate *issuerCert = NULL;
   314     CERTCertificate *subjectCert = NULL;
   315     CERTCertificate *badCert = NULL;
   316     PRBool isca;
   317     SECStatus rv;
   318     SECStatus rvFinal = SECSuccess;
   319     int count;
   320     int currentPathLen = 0;
   321     int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
   322     unsigned int caCertType;
   323     unsigned int requiredCAKeyUsage;
   324     unsigned int requiredFlags;
   325     PLArenaPool *arena = NULL;
   326     CERTGeneralName *namesList = NULL;
   327     CERTCertificate **certsList      = NULL;
   328     int certsListLen = 16;
   329     int namesCount = 0;
   330     PRBool subjectCertIsSelfIssued;
   331     CERTCertTrust issuerTrust;
   333     if (revoked) {
   334         *revoked = PR_FALSE;
   335     }
   337     if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
   338 					 &requiredCAKeyUsage,
   339 					 &caCertType)
   340 	!= SECSuccess ) {
   341 	PORT_Assert(0);
   342 	EXIT_IF_NOT_LOGGING(log);
   343 	requiredCAKeyUsage = 0;
   344 	caCertType = 0;
   345     }
   347     switch ( certUsage ) {
   348       case certUsageSSLClient:
   349       case certUsageSSLServer:
   350       case certUsageSSLCA:
   351       case certUsageSSLServerWithStepUp:
   352       case certUsageEmailSigner:
   353       case certUsageEmailRecipient:
   354       case certUsageObjectSigner:
   355       case certUsageVerifyCA:
   356       case certUsageAnyCA:
   357       case certUsageStatusResponder:
   358 	if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
   359 					   &trustType) != SECSuccess ) {
   360 	    PORT_Assert(0);
   361 	    EXIT_IF_NOT_LOGGING(log);
   362 	    /* XXX continuing with requiredFlags = 0 seems wrong.  It'll
   363 	     * cause the following test to be true incorrectly:
   364 	     *   flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
   365 	     *   if (( flags & requiredFlags ) == requiredFlags) {
   366 	     *       rv = rvFinal;
   367 	     *       goto done;
   368 	     *   }
   369 	     * There are three other instances of this problem.
   370 	     */
   371 	    requiredFlags = 0;
   372 	    trustType = trustSSL;
   373 	}
   374 	break;
   375       default:
   376 	PORT_Assert(0);
   377 	EXIT_IF_NOT_LOGGING(log);
   378 	requiredFlags = 0;
   379 	trustType = trustSSL;/* This used to be 0, but we need something
   380 			      * that matches the enumeration type.
   381 			      */
   382 	caCertType = 0;
   383     }
   385     subjectCert = CERT_DupCertificate(cert);
   386     if ( subjectCert == NULL ) {
   387 	goto loser;
   388     }
   390     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   391     if (arena == NULL) {
   392 	goto loser;
   393     }
   395     certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
   396     if (certsList == NULL)
   397 	goto loser;
   399     /* RFC 3280 says that the name constraints will apply to the names
   400     ** in the leaf (EE) cert, whether it is self issued or not, so
   401     ** we pretend that it is not.
   402     */
   403     subjectCertIsSelfIssued = PR_FALSE;
   404     for ( count = 0; count < CERT_MAX_CERT_CHAIN; count++ ) {
   405 	PRBool validCAOverride = PR_FALSE;
   407 	/* Construct a list of names for the current and all previous 
   408 	 * certifcates (except leaf (EE) certs, root CAs, and self-issued
   409 	 * intermediate CAs) to be verified against the name constraints 
   410 	 * extension of the issuer certificate. 
   411 	 */
   412 	if (subjectCertIsSelfIssued == PR_FALSE) {
   413 	    CERTGeneralName *subjectNameList;
   414 	    int subjectNameListLen;
   415 	    int i;
   416 	    PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer);
   417 	    subjectNameList = 
   418 	    	CERT_GetConstrainedCertificateNames(subjectCert, arena,
   419 		                                    getSubjectCN);
   420 	    if (!subjectNameList)
   421 		goto loser;
   422 	    subjectNameListLen = CERT_GetNamesLength(subjectNameList);
   423 	    if (!subjectNameListLen)
   424 		goto loser;
   425 	    if (certsListLen <= namesCount + subjectNameListLen) {
   426 		CERTCertificate **tmpCertsList;
   427 		certsListLen = (namesCount + subjectNameListLen) * 2;
   428 		tmpCertsList = 
   429 		    (CERTCertificate **)PORT_Realloc(certsList, 
   430 	                            certsListLen * sizeof(CERTCertificate *));
   431 		if (tmpCertsList == NULL) {
   432 		    goto loser;
   433 		}
   434 		certsList = tmpCertsList;
   435 	    }
   436 	    for (i = 0; i < subjectNameListLen; i++) {
   437 		certsList[namesCount + i] = subjectCert;
   438 	    }
   439 	    namesCount += subjectNameListLen;
   440 	    namesList = cert_CombineNamesLists(namesList, subjectNameList);
   441 	}
   443         /* check if the cert has an unsupported critical extension */
   444 	if ( subjectCert->options.bits.hasUnsupportedCriticalExt ) {
   445 	    PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
   446 	    LOG_ERROR_OR_EXIT(log,subjectCert,count,0);
   447 	}
   449 	/* find the certificate of the issuer */
   450 	issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
   451 	if ( ! issuerCert ) {
   452 	    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
   453 	    LOG_ERROR(log,subjectCert,count,0);
   454 	    goto loser;
   455 	}
   457 	/* verify the signature on the cert */
   458 	if ( checkSig ) {
   459 	    rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
   460 				       issuerCert, t, wincx);
   462 	    if ( rv != SECSuccess ) {
   463                 if (sigerror) {
   464                     *sigerror = PR_TRUE;
   465                 }
   466 		if ( PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ) {
   467 		    PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
   468 		    LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
   469 		} else {
   470 		    if (PORT_GetError() !=
   471 			SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
   472 			PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   473 		    }
   474 		    LOG_ERROR_OR_EXIT(log,subjectCert,count,0);
   475 		}
   476 	    }
   477 	}
   479 	/* If the basicConstraint extension is included in an immediate CA
   480 	 * certificate, make sure that the isCA flag is on.  If the
   481 	 * pathLenConstraint component exists, it must be greater than the
   482 	 * number of CA certificates we have seen so far.  If the extension
   483 	 * is omitted, we will assume that this is a CA certificate with
   484 	 * an unlimited pathLenConstraint (since it already passes the
   485 	 * netscape-cert-type extension checking).
   486 	 */
   488 	rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
   489 	if ( rv != SECSuccess ) {
   490 	    if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
   491 		LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
   492 	    } 
   493 	    pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
   494 	    /* no basic constraints found, we aren't (yet) a CA. */
   495 	    isca = PR_FALSE;
   496 	} else  {
   497 	    if ( basicConstraint.isCA == PR_FALSE ) {
   498 		PORT_SetError (SEC_ERROR_CA_CERT_INVALID);
   499 		LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
   500 	    }
   501 	    pathLengthLimit = basicConstraint.pathLenConstraint;
   502 	    isca = PR_TRUE;
   503 	}    
   504 	/* make sure that the path len constraint is properly set.*/
   505 	if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) {
   506 	    PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
   507 	    LOG_ERROR_OR_EXIT(log, issuerCert, count+1, pathLengthLimit);
   508 	}
   510         /* make sure that the entire chain is within the name space of the
   511          * current issuer certificate.
   512          */
   513         rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
   514                                    arena, &badCert);
   515         if (rv != SECSuccess || badCert != NULL) {
   516             PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
   517             LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
   518             goto loser;
   519         }
   521 	/* XXX - the error logging may need to go down into CRL stuff at some
   522 	 * point
   523 	 */
   524 	/* check revoked list (issuer) */
   525         rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
   526         if (rv == SECFailure) {
   527             if (revoked) {
   528                 *revoked = PR_TRUE;
   529             }
   530             LOG_ERROR_OR_EXIT(log,subjectCert,count,0);
   531         } else if (rv == SECWouldBlock) {
   532             /* We found something fishy, so we intend to issue an
   533              * error to the user, but the user may wish to continue
   534              * processing, in which case we better make sure nothing
   535              * worse has happened... so keep cranking the loop */
   536             rvFinal = SECFailure;
   537             if (revoked) {
   538                 *revoked = PR_TRUE;
   539             }
   540             LOG_ERROR(log,subjectCert,count,0);
   541         }
   543 	if ( CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) {
   544 	    /* we have some trust info, but this does NOT imply that this
   545 	     * cert is actually trusted for any purpose.  The cert may be
   546 	     * explicitly UNtrusted.  We won't know until we examine the
   547 	     * trust bits.
   548 	     */
   549 	    unsigned int flags;
   551 	    if (certUsage != certUsageAnyCA &&
   552 	        certUsage != certUsageStatusResponder) {
   554 	        /*
   555 	         * XXX This choice of trustType seems arbitrary.
   556 	         */
   557 	        if ( certUsage == certUsageVerifyCA ) {
   558 	            if ( subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA ) {
   559 	                trustType = trustEmail;
   560 	            } else if ( subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA ) {
   561 	                trustType = trustSSL;
   562 	            } else {
   563 	                trustType = trustObjectSigning;
   564 	            }
   565 	        }
   567 	        flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
   568 	        if (( flags & requiredFlags ) == requiredFlags) {
   569 	            /* we found a trusted one, so return */
   570 	            rv = rvFinal; 
   571 	            goto done;
   572 	        }
   573 	        if (flags & CERTDB_VALID_CA) {
   574 	            validCAOverride = PR_TRUE;
   575 	        }
   576 		/* is it explicitly distrusted? */
   577 		if ((flags & CERTDB_TERMINAL_RECORD) && 
   578 			((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) {
   579 		    /* untrusted -- the cert is explicitly untrusted, not
   580 		     * just that it doesn't chain to a trusted cert */
   581 		    PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
   582 		    LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags);
   583 		}
   584 	    } else {
   585                 /* Check if we have any valid trust when cheching for
   586                  * certUsageAnyCA or certUsageStatusResponder. */
   587                 for (trustType = trustSSL; trustType < trustTypeNone;
   588                      trustType++) {
   589                     flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
   590                     if ((flags & requiredFlags) == requiredFlags) {
   591 	                rv = rvFinal; 
   592 	                goto done;
   593                     }
   594                     if (flags & CERTDB_VALID_CA)
   595                         validCAOverride = PR_TRUE;
   596                 }
   597 		/* We have 2 separate loops because we want any single trust
   598 		 * bit to allow this usage to return trusted. Only if none of
   599 		 * the trust bits are on do we check to see if the cert is 
   600 		 * untrusted */
   601                 for (trustType = trustSSL; trustType < trustTypeNone;
   602                      trustType++) {
   603                     flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
   604 		    /* is it explicitly distrusted? */
   605 		    if ((flags & CERTDB_TERMINAL_RECORD) && 
   606 			((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) {
   607 			/* untrusted -- the cert is explicitly untrusted, not
   608 			 * just that it doesn't chain to a trusted cert */
   609 			PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
   610 			LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags);
   611 		    }
   612                 }
   613             }
   614         }
   616 	if (!validCAOverride) {
   617 	    /*
   618 	     * Make sure that if this is an intermediate CA in the chain that
   619 	     * it was given permission by its signer to be a CA.
   620 	     */
   621 	    /*
   622 	     * if basicConstraints says it is a ca, then we check the
   623 	     * nsCertType.  If the nsCertType has any CA bits set, then
   624 	     * it must have the right one.
   625 	     */
   626 	    if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
   627 		isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
   628 	    }
   630 	    if (  !isca  ) {
   631 		PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
   632 		LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
   633 	    }
   635 	    /* make sure key usage allows cert signing */
   636 	    if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) {
   637 		PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
   638 		LOG_ERROR_OR_EXIT(log,issuerCert,count+1,requiredCAKeyUsage);
   639 	    }
   640 	}
   642 	/* make sure that the issuer is not self signed.  If it is, then
   643 	 * stop here to prevent looping.
   644 	 */
   645 	if (issuerCert->isRoot) {
   646 	    PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
   647 	    LOG_ERROR(log, issuerCert, count+1, 0);
   648 	    goto loser;
   649 	} 
   650 	/* The issuer cert will be the subject cert in the next loop.
   651 	 * A cert is self-issued if its subject and issuer are equal and
   652 	 * both are of non-zero length. 
   653 	 */
   654 	subjectCertIsSelfIssued = (PRBool)
   655 	    SECITEM_ItemsAreEqual(&issuerCert->derIssuer, 
   656 				  &issuerCert->derSubject) &&
   657 	    issuerCert->derSubject.len > 0;
   658 	if (subjectCertIsSelfIssued == PR_FALSE) {
   659 	    /* RFC 3280 says only non-self-issued intermediate CA certs 
   660 	     * count in path length.
   661 	     */
   662 	    ++currentPathLen;
   663 	}
   665 	CERT_DestroyCertificate(subjectCert);
   666 	subjectCert = issuerCert;
   667 	issuerCert = NULL;
   668     }
   670     PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
   671     LOG_ERROR(log,subjectCert,count,0);
   672 loser:
   673     rv = SECFailure;
   674 done:
   675     if (certsList != NULL) {
   676 	PORT_Free(certsList);
   677     }
   678     if ( issuerCert ) {
   679 	CERT_DestroyCertificate(issuerCert);
   680     }
   682     if ( subjectCert ) {
   683 	CERT_DestroyCertificate(subjectCert);
   684     }
   686     if ( arena != NULL ) {
   687 	PORT_FreeArena(arena, PR_FALSE);
   688     }
   689     return rv;
   690 }
   692 SECStatus
   693 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
   694                      PRBool checkSig, PRBool* sigerror,
   695                      SECCertUsage certUsage, PRTime t, void *wincx,
   696                      CERTVerifyLog *log, PRBool* revoked)
   697 {
   698     if (CERT_GetUsePKIXForValidation()) {
   699         return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
   700                                         wincx, log, sigerror, revoked);
   701     }
   702     return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
   703                                    certUsage, t, wincx, log, revoked);
   704 }
   706 SECStatus
   707 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
   708 		     PRBool checkSig, SECCertUsage certUsage, PRTime t,
   709 		     void *wincx, CERTVerifyLog *log)
   710 {
   711     return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
   712 			 wincx, log, NULL);
   713 }
   715 /*
   716  * verify that a CA can sign a certificate with the requested usage.
   717  */
   718 SECStatus
   719 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
   720 		PRBool checkSig, SECCertUsage certUsage, PRTime t,
   721 		void *wincx, CERTVerifyLog *log)
   722 {
   723     SECTrustType trustType;
   724     CERTBasicConstraints basicConstraint;
   725     PRBool isca;
   726     PRBool validCAOverride = PR_FALSE;
   727     SECStatus rv;
   728     SECStatus rvFinal = SECSuccess;
   729     unsigned int flags;
   730     unsigned int caCertType;
   731     unsigned int requiredCAKeyUsage;
   732     unsigned int requiredFlags;
   733     CERTCertificate *issuerCert;
   734     CERTCertTrust certTrust;
   737     if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
   738 					 &requiredCAKeyUsage,
   739 					 &caCertType) != SECSuccess ) {
   740 	PORT_Assert(0);
   741 	EXIT_IF_NOT_LOGGING(log);
   742 	requiredCAKeyUsage = 0;
   743 	caCertType = 0;
   744     }
   746     switch ( certUsage ) {
   747       case certUsageSSLClient:
   748       case certUsageSSLServer:
   749       case certUsageSSLCA:
   750       case certUsageSSLServerWithStepUp:
   751       case certUsageEmailSigner:
   752       case certUsageEmailRecipient:
   753       case certUsageObjectSigner:
   754       case certUsageVerifyCA:
   755       case certUsageStatusResponder:
   756 	if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
   757 					   &trustType) != SECSuccess ) {
   758 	    PORT_Assert(0);
   759 	    EXIT_IF_NOT_LOGGING(log);
   760 	    requiredFlags = 0;
   761 	    trustType = trustSSL;
   762 	}
   763 	break;
   764       default:
   765 	PORT_Assert(0);
   766 	EXIT_IF_NOT_LOGGING(log);
   767 	requiredFlags = 0;
   768 	trustType = trustSSL;/* This used to be 0, but we need something
   769 			      * that matches the enumeration type.
   770 			      */
   771 	caCertType = 0;
   772     }
   774     /* If the basicConstraint extension is included in an intermmediate CA
   775      * certificate, make sure that the isCA flag is on.  If the
   776      * pathLenConstraint component exists, it must be greater than the
   777      * number of CA certificates we have seen so far.  If the extension
   778      * is omitted, we will assume that this is a CA certificate with
   779      * an unlimited pathLenConstraint (since it already passes the
   780      * netscape-cert-type extension checking).
   781      */
   783     rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
   784     if ( rv != SECSuccess ) {
   785 	if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
   786 	    LOG_ERROR_OR_EXIT(log,cert,0,0);
   787 	} 
   788 	/* no basic constraints found, we aren't (yet) a CA. */
   789 	isca = PR_FALSE;
   790     } else  {
   791 	if ( basicConstraint.isCA == PR_FALSE ) {
   792 	    PORT_SetError (SEC_ERROR_CA_CERT_INVALID);
   793 	    LOG_ERROR_OR_EXIT(log,cert,0,0);
   794 	}
   796 	/* can't check path length if we don't know the previous path */
   797 	isca = PR_TRUE;
   798     }
   800     if ( CERT_GetCertTrust(cert, &certTrust) == SECSuccess ) {
   801 	/* we have some trust info, but this does NOT imply that this
   802 	 * cert is actually trusted for any purpose.  The cert may be
   803 	 * explicitly UNtrusted.  We won't know until we examine the
   804 	 * trust bits.
   805 	 */
   806         if (certUsage == certUsageStatusResponder) {
   807 	    /* Check the special case of certUsageStatusResponder */
   808             issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
   809             if (issuerCert) {
   810                 if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) 
   811 		    != SECSuccess) {
   812                     PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
   813                     CERT_DestroyCertificate(issuerCert);
   814                     goto loser;
   815                 }
   816                 CERT_DestroyCertificate(issuerCert);
   817             }
   818 	    /* XXX We have NOT determined that this cert is trusted.
   819 	     * For years, NSS has treated this as trusted, 
   820 	     * but it seems incorrect.
   821 	     */
   822 	    rv = rvFinal; 
   823 	    goto done;
   824         }
   826 	/*
   827 	 * check the trust params of the issuer
   828 	 */
   829 	flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
   830 	if ( ( flags & requiredFlags ) == requiredFlags) {
   831 	    /* we found a trusted one, so return */
   832 	    rv = rvFinal; 
   833 	    goto done;
   834 	}
   835 	if (flags & CERTDB_VALID_CA) {
   836 	    validCAOverride = PR_TRUE;
   837 	}
   838 	/* is it explicitly distrusted? */
   839 	if ((flags & CERTDB_TERMINAL_RECORD) && 
   840 		((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) {
   841 	    /* untrusted -- the cert is explicitly untrusted, not
   842 	     * just that it doesn't chain to a trusted cert */
   843 	    PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
   844 	    LOG_ERROR_OR_EXIT(log,cert,0,flags);
   845 	}
   846     }
   847     if (!validCAOverride) {
   848 	/*
   849 	 * Make sure that if this is an intermediate CA in the chain that
   850 	 * it was given permission by its signer to be a CA.
   851 	 */
   852 	/*
   853 	 * if basicConstraints says it is a ca, then we check the
   854 	 * nsCertType.  If the nsCertType has any CA bits set, then
   855 	 * it must have the right one.
   856 	 */
   857 	if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
   858 	    isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
   859 	}
   861 	if (!isca) {
   862 	    PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
   863 	    LOG_ERROR_OR_EXIT(log,cert,0,0);
   864 	}
   866 	/* make sure key usage allows cert signing */
   867 	if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
   868 	    PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
   869 	    LOG_ERROR_OR_EXIT(log,cert,0,requiredCAKeyUsage);
   870 	}
   871     }
   872     /* make sure that the issuer is not self signed.  If it is, then
   873      * stop here to prevent looping.
   874      */
   875     if (cert->isRoot) {
   876 	    PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
   877 	    LOG_ERROR(log, cert, 0, 0);
   878 	    goto loser;
   879     }
   881     return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, 
   882 		     					wincx, log);
   883 loser:
   884     rv = SECFailure;
   885 done:
   886     return rv;
   887 }
   889 #define NEXT_USAGE() { \
   890     i*=2; \
   891     certUsage++; \
   892     continue; \
   893 }
   895 #define VALID_USAGE() { \
   896     NEXT_USAGE(); \
   897 }
   899 #define INVALID_USAGE() { \
   900     if (returnedUsages) { \
   901         *returnedUsages &= (~i); \
   902     } \
   903     if (PR_TRUE == requiredUsage) { \
   904         valid = SECFailure; \
   905     } \
   906     NEXT_USAGE(); \
   907 }
   909 /*
   910  * check the leaf cert against trust and usage. 
   911  *   returns success if the cert is not distrusted. If the cert is
   912  *       trusted, then the trusted bool will be true.
   913  *   returns failure if the cert is distrusted. If failure, flags
   914  *       will return the flag bits that indicated distrust.
   915  */
   916 SECStatus
   917 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
   918 	            unsigned int *failedFlags, PRBool *trusted)
   919 {
   920     unsigned int flags;
   921     CERTCertTrust trust;
   923     *failedFlags = 0;
   924     *trusted = PR_FALSE;
   926     /* check trust flags to see if this cert is directly trusted */
   927     if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) { 
   928 	switch ( certUsage ) {
   929 	  case certUsageSSLClient:
   930 	  case certUsageSSLServer:
   931 	    flags = trust.sslFlags;
   933 	    /* is the cert directly trusted or not trusted ? */
   934 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
   935 						    * authoritative */
   936 		if ( flags & CERTDB_TRUSTED ) {	/* trust this cert */
   937 		    *trusted = PR_TRUE;
   938 		    return SECSuccess;
   939 		} else { /* don't trust this cert */
   940 		    *failedFlags = flags;
   941 		    return SECFailure;
   942 		}
   943 	    }
   944 	    break;
   945 	  case certUsageSSLServerWithStepUp:
   946 	    /* XXX - step up certs can't be directly trusted, only distrust */
   947 	    flags = trust.sslFlags;
   948 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
   949 						    * authoritative */
   950 		if (( flags & CERTDB_TRUSTED ) == 0) {	
   951 		    /* don't trust this cert */
   952 		    *failedFlags = flags;
   953 		    return SECFailure;
   954 		}
   955 	    }
   956 	    break;
   957 	  case certUsageSSLCA:
   958 	    flags = trust.sslFlags;
   959 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
   960 						    * authoritative */
   961 		if (( flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA) ) == 0) {	
   962 		    /* don't trust this cert */
   963 		    *failedFlags = flags;
   964 		    return SECFailure;
   965 		}
   966 	    }
   967 	    break;
   968 	  case certUsageEmailSigner:
   969 	  case certUsageEmailRecipient:
   970 	    flags = trust.emailFlags;
   971 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
   972 						    * authoritative */
   973 		if ( flags & CERTDB_TRUSTED ) {	/* trust this cert */
   974 		    *trusted = PR_TRUE;
   975 		    return SECSuccess;
   976 		} 
   977 		else { /* don't trust this cert */
   978 		    *failedFlags = flags;
   979 		    return SECFailure;
   980 		}
   981 	    }
   983 	    break;
   984 	  case certUsageObjectSigner:
   985 	    flags = trust.objectSigningFlags;
   987 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
   988 						    * authoritative */
   989 		if ( flags & CERTDB_TRUSTED ) {	/* trust this cert */
   990 		    *trusted = PR_TRUE;
   991 		    return SECSuccess;
   992 		} else { /* don't trust this cert */
   993 		    *failedFlags = flags;
   994 		    return SECFailure;
   995 		}
   996 	    }
   997 	    break;
   998 	  case certUsageVerifyCA:
   999 	  case certUsageStatusResponder:
  1000 	    flags = trust.sslFlags;
  1001 	    /* is the cert directly trusted or not trusted ? */
  1002 	    if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
  1003 		( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
  1004 		*trusted = PR_TRUE;
  1005 		return SECSuccess;
  1007 	    flags = trust.emailFlags;
  1008 	    /* is the cert directly trusted or not trusted ? */
  1009 	    if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
  1010 		( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
  1011 		*trusted = PR_TRUE;
  1012 		return SECSuccess;
  1014 	    flags = trust.objectSigningFlags;
  1015 	    /* is the cert directly trusted or not trusted ? */
  1016 	    if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
  1017 		( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
  1018 		*trusted = PR_TRUE;
  1019 		return SECSuccess;
  1021 	    /* fall through to test distrust */
  1022 	  case certUsageAnyCA:
  1023 	  case certUsageUserCertImport:
  1024 	    /* do we distrust these certs explicitly */
  1025 	    flags = trust.sslFlags;
  1026 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
  1027 						    * authoritative */
  1028 		if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) {
  1029 		    *failedFlags = flags;
  1030 		    return SECFailure;
  1033 	    flags = trust.emailFlags;
  1034 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
  1035 						    * authoritative */
  1036 		if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) {
  1037 		    *failedFlags = flags;
  1038 		    return SECFailure;
  1041 	    /* fall through */
  1042 	  case certUsageProtectedObjectSigner:
  1043 	    flags = trust.objectSigningFlags;
  1044 	    if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 
  1045 						    * authoritative */
  1046 		if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) {
  1047 		    *failedFlags = flags;
  1048 		    return SECFailure;
  1051 	    break;
  1054     return SECSuccess;
  1057 /*
  1058  * verify a certificate by checking if it's valid and that we
  1059  * trust the issuer.
  1061  * certificateUsage contains a bitfield of all cert usages that are
  1062  * required for verification to succeed
  1064  * a bitfield of cert usages is returned in *returnedUsages
  1065  * if requiredUsages is non-zero, the returned bitmap is only
  1066  * for those required usages, otherwise it is for all usages
  1068  */
  1069 SECStatus
  1070 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
  1071 		PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
  1072 		void *wincx, CERTVerifyLog *log, SECCertificateUsage* returnedUsages)
  1074     SECStatus rv;
  1075     SECStatus valid;
  1076     unsigned int requiredKeyUsage;
  1077     unsigned int requiredCertType;
  1078     unsigned int flags;
  1079     unsigned int certType;
  1080     PRBool       allowOverride;
  1081     SECCertTimeValidity validity;
  1082     CERTStatusConfig *statusConfig;
  1083     PRInt32 i;
  1084     SECCertUsage certUsage = 0;
  1085     PRBool checkedOCSP = PR_FALSE;
  1086     PRBool checkAllUsages = PR_FALSE;
  1087     PRBool revoked = PR_FALSE;
  1088     PRBool sigerror = PR_FALSE;
  1089     PRBool trusted = PR_FALSE;
  1091     if (!requiredUsages) {
  1092         /* there are no required usages, so the user probably wants to
  1093            get status for all usages */
  1094         checkAllUsages = PR_TRUE;
  1097     if (returnedUsages) {
  1098         *returnedUsages = 0;
  1099     } else {
  1100         /* we don't have a place to return status for all usages,
  1101            so we can skip checks for usages that aren't required */
  1102         checkAllUsages = PR_FALSE;
  1104     valid = SECSuccess ; /* start off assuming cert is valid */
  1106     /* make sure that the cert is valid at time t */
  1107     allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
  1108                              (requiredUsages & certificateUsageSSLServerWithStepUp));
  1109     validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
  1110     if ( validity != secCertTimeValid ) {
  1111         valid = SECFailure;
  1112         LOG_ERROR_OR_EXIT(log,cert,0,validity);
  1115     /* check key usage and netscape cert type */
  1116     cert_GetCertType(cert);
  1117     certType = cert->nsCertType;
  1119     for (i=1; i<=certificateUsageHighest && 
  1120               (SECSuccess == valid || returnedUsages || log) ; ) {
  1121         PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
  1122         if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
  1123             NEXT_USAGE();
  1125         if (returnedUsages) {
  1126             *returnedUsages |= i; /* start off assuming this usage is valid */
  1128         switch ( certUsage ) {
  1129           case certUsageSSLClient:
  1130           case certUsageSSLServer:
  1131           case certUsageSSLServerWithStepUp:
  1132           case certUsageSSLCA:
  1133           case certUsageEmailSigner:
  1134           case certUsageEmailRecipient:
  1135           case certUsageObjectSigner:
  1136           case certUsageStatusResponder:
  1137             rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
  1138                                                   &requiredKeyUsage,
  1139                                                   &requiredCertType);
  1140             if ( rv != SECSuccess ) {
  1141                 PORT_Assert(0);
  1142                 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
  1143                 requiredKeyUsage = 0;
  1144                 requiredCertType = 0;
  1145                 INVALID_USAGE();
  1147             break;
  1149           case certUsageAnyCA:
  1150           case certUsageProtectedObjectSigner:
  1151           case certUsageUserCertImport:
  1152           case certUsageVerifyCA:
  1153               /* these usages cannot be verified */
  1154               NEXT_USAGE();
  1156           default:
  1157             PORT_Assert(0);
  1158             requiredKeyUsage = 0;
  1159             requiredCertType = 0;
  1160             INVALID_USAGE();
  1162         if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) {
  1163             if (PR_TRUE == requiredUsage) {
  1164                 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
  1166             LOG_ERROR(log,cert,0,requiredKeyUsage);
  1167             INVALID_USAGE();
  1169         if ( !( certType & requiredCertType ) ) {
  1170             if (PR_TRUE == requiredUsage) {
  1171                 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
  1173             LOG_ERROR(log,cert,0,requiredCertType);
  1174             INVALID_USAGE();
  1177 	rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
  1178 	if (rv == SECFailure) {
  1179 	    if (PR_TRUE == requiredUsage) {
  1180 		PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
  1182 	    LOG_ERROR(log, cert, 0, flags);
  1183 	    INVALID_USAGE();
  1184 	} else if (trusted) {
  1185 	    VALID_USAGE();
  1188 	if (PR_TRUE == revoked || PR_TRUE == sigerror) {
  1189 	    INVALID_USAGE();
  1192         rv = cert_VerifyCertChain(handle, cert,
  1193             checkSig, &sigerror,
  1194             certUsage, t, wincx, log,
  1195             &revoked);
  1197         if (rv != SECSuccess) {
  1198             /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
  1199             INVALID_USAGE();
  1202         /*
  1203          * Check OCSP revocation status, but only if the cert we are checking
  1204          * is not a status responder itself. We only do this in the case
  1205          * where we checked the cert chain (above); explicit trust "wins"
  1206          * (avoids status checking, just as it avoids CRL checking) by
  1207          * bypassing this code.
  1208          */
  1210         if (PR_FALSE == checkedOCSP) {
  1211             checkedOCSP = PR_TRUE; /* only check OCSP once */
  1212             statusConfig = CERT_GetStatusConfig(handle);
  1213             if (requiredUsages != certificateUsageStatusResponder &&
  1214                 statusConfig != NULL) {
  1215                 if (statusConfig->statusChecker != NULL) {
  1216                     rv = (* statusConfig->statusChecker)(handle, cert,
  1217                                                                  t, wincx);
  1218                     if (rv != SECSuccess) {
  1219                         LOG_ERROR(log,cert,0,0);
  1220                         revoked = PR_TRUE;
  1221                         INVALID_USAGE();
  1227         NEXT_USAGE();
  1230 loser:
  1231     return(valid);
  1234 SECStatus
  1235 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
  1236 		PRBool checkSig, SECCertUsage certUsage, PRTime t,
  1237 		void *wincx, CERTVerifyLog *log)
  1239     return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
  1240                                     CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
  1243 SECStatus
  1244 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
  1245                          PRBool checkSig, SECCertUsage certUsage, PRTime t,
  1246                          PRUint32 flags, void *wincx, CERTVerifyLog *log)
  1248     SECStatus rv;
  1249     unsigned int requiredKeyUsage;
  1250     unsigned int requiredCertType;
  1251     unsigned int failedFlags;
  1252     unsigned int certType;
  1253     PRBool       trusted;
  1254     PRBool       allowOverride;
  1255     SECCertTimeValidity validity;
  1256     CERTStatusConfig *statusConfig;
  1258 #ifdef notdef 
  1259     /* check if this cert is in the Evil list */
  1260     rv = CERT_CheckForEvilCert(cert);
  1261     if ( rv != SECSuccess ) {
  1262 	PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
  1263 	LOG_ERROR_OR_EXIT(log,cert,0,0);
  1265 #endif
  1267     /* make sure that the cert is valid at time t */
  1268     allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
  1269                              (certUsage == certUsageSSLServerWithStepUp));
  1270     validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
  1271     if ( validity != secCertTimeValid ) {
  1272 	LOG_ERROR_OR_EXIT(log,cert,0,validity);
  1275     /* check key usage and netscape cert type */
  1276     cert_GetCertType(cert);
  1277     certType = cert->nsCertType;
  1278     switch ( certUsage ) {
  1279       case certUsageSSLClient:
  1280       case certUsageSSLServer:
  1281       case certUsageSSLServerWithStepUp:
  1282       case certUsageSSLCA:
  1283       case certUsageEmailSigner:
  1284       case certUsageEmailRecipient:
  1285       case certUsageObjectSigner:
  1286       case certUsageStatusResponder:
  1287 	rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
  1288 					      &requiredKeyUsage,
  1289 					      &requiredCertType);
  1290 	if ( rv != SECSuccess ) {
  1291 	    PORT_Assert(0);
  1292 	    EXIT_IF_NOT_LOGGING(log);
  1293 	    requiredKeyUsage = 0;
  1294 	    requiredCertType = 0;
  1296 	break;
  1297       case certUsageVerifyCA:
  1298       case certUsageAnyCA:
  1299 	requiredKeyUsage = KU_KEY_CERT_SIGN;
  1300 	requiredCertType = NS_CERT_TYPE_CA;
  1301 	if ( ! ( certType & NS_CERT_TYPE_CA ) ) {
  1302 	    certType |= NS_CERT_TYPE_CA;
  1304 	break;
  1305       default:
  1306 	PORT_Assert(0);
  1307 	EXIT_IF_NOT_LOGGING(log);
  1308 	requiredKeyUsage = 0;
  1309 	requiredCertType = 0;
  1311     if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) {
  1312 	PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
  1313 	LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage);
  1315     if ( !( certType & requiredCertType ) ) {
  1316 	PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
  1317 	LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
  1320     rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
  1321     if (rv  == SECFailure) {
  1322 	PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
  1323 	LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
  1324     } else if (trusted) {
  1325 	goto done;
  1329     rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
  1330 			      t, wincx, log);
  1331     if (rv != SECSuccess) {
  1332 	EXIT_IF_NOT_LOGGING(log);
  1335     /*
  1336      * Check revocation status, but only if the cert we are checking is not a
  1337      * status responder itself and the caller did not ask us to skip the check.
  1338      * We only do this in the case where we checked the cert chain (above);
  1339      * explicit trust "wins" (avoids status checking, just as it avoids CRL
  1340      * checking, which is all done inside VerifyCertChain) by bypassing this
  1341      * code.
  1342      */
  1343     if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
  1344 	certUsage != certUsageStatusResponder) {
  1345 	statusConfig = CERT_GetStatusConfig(handle);
  1346 	if (statusConfig && statusConfig->statusChecker) {
  1347 	    rv = (* statusConfig->statusChecker)(handle, cert,
  1348 							 t, wincx);
  1349 	    if (rv != SECSuccess) {
  1350 		LOG_ERROR_OR_EXIT(log,cert,0,0);
  1355 done:
  1356     if (log && log->head) {
  1357       return SECFailure;
  1359     return(SECSuccess);
  1361 loser:
  1362     rv = SECFailure;
  1364     return(rv);
  1367 /*
  1368  * verify a certificate by checking if its valid and that we
  1369  * trust the issuer.  Verify time against now.
  1370  */
  1371 SECStatus
  1372 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
  1373 		   PRBool checkSig, SECCertificateUsage requiredUsages,
  1374                    void *wincx, SECCertificateUsage* returnedUsages)
  1376     return(CERT_VerifyCertificate(handle, cert, checkSig, 
  1377 		   requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
  1380 /* obsolete, do not use for new code */
  1381 SECStatus
  1382 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
  1383 		   PRBool checkSig, SECCertUsage certUsage, void *wincx)
  1385     return(CERT_VerifyCert(handle, cert, checkSig, 
  1386 		   certUsage, PR_Now(), wincx, NULL));
  1390 /* [ FROM pcertdb.c ] */
  1391 /*
  1392  * Supported usage values and types:
  1393  *	certUsageSSLClient
  1394  *	certUsageSSLServer
  1395  *	certUsageSSLServerWithStepUp
  1396  *	certUsageEmailSigner
  1397  *	certUsageEmailRecipient
  1398  *	certUsageObjectSigner
  1399  */
  1401 CERTCertificate *
  1402 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
  1403 		      CERTCertOwner owner, SECCertUsage usage,
  1404 		      PRBool preferTrusted, PRTime validTime, PRBool validOnly)
  1406     CERTCertList *certList = NULL;
  1407     CERTCertificate *cert = NULL;
  1408     CERTCertTrust certTrust;
  1409     unsigned int requiredTrustFlags;
  1410     SECTrustType requiredTrustType;
  1411     unsigned int flags;
  1413     PRBool lookingForCA = PR_FALSE;
  1414     SECStatus rv;
  1415     CERTCertListNode *node;
  1416     CERTCertificate *saveUntrustedCA = NULL;
  1418     /* if preferTrusted is set, must be a CA cert */
  1419     PORT_Assert( ! ( preferTrusted && ( owner != certOwnerCA ) ) );
  1421     if ( owner == certOwnerCA ) {
  1422 	lookingForCA = PR_TRUE;
  1423 	if ( preferTrusted ) {
  1424 	    rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
  1425 					       &requiredTrustType);
  1426 	    if ( rv != SECSuccess ) {
  1427 		goto loser;
  1429 	    requiredTrustFlags |= CERTDB_VALID_CA;
  1433     certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
  1434 					  validOnly);
  1435     if ( certList != NULL ) {
  1436 	rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
  1437 	if ( rv != SECSuccess ) {
  1438 	    goto loser;
  1441 	node = CERT_LIST_HEAD(certList);
  1443 	while ( !CERT_LIST_END(node, certList) ) {
  1444 	    cert = node->cert;
  1446 	    /* looking for a trusted CA cert */
  1447 	    if ( ( owner == certOwnerCA ) && preferTrusted &&
  1448 		( requiredTrustType != trustTypeNone ) ) {
  1450 		if ( CERT_GetCertTrust(cert, &certTrust) != SECSuccess ) {
  1451 		    flags = 0;
  1452 		} else {
  1453 		    flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
  1456 		if ( ( flags & requiredTrustFlags ) != requiredTrustFlags ) {
  1457 		    /* cert is not trusted */
  1458 		    /* if this is the first cert to get this far, then save
  1459 		     * it, so we can use it if we can't find a trusted one
  1460 		     */
  1461 		    if ( saveUntrustedCA == NULL ) {
  1462 			saveUntrustedCA = cert;
  1464 		    goto endloop;
  1467 	    /* if we got this far, then this cert meets all criteria */
  1468 	    break;
  1470 endloop:
  1471 	    node = CERT_LIST_NEXT(node);
  1472 	    cert = NULL;
  1475 	/* use the saved one if we have it */
  1476 	if ( cert == NULL ) {
  1477 	    cert = saveUntrustedCA;
  1480 	/* if we found one then bump the ref count before freeing the list */
  1481 	if ( cert != NULL ) {
  1482 	    /* bump the ref count */
  1483 	    cert = CERT_DupCertificate(cert);
  1486 	CERT_DestroyCertList(certList);
  1489     return(cert);
  1491 loser:
  1492     if ( certList != NULL ) {
  1493 	CERT_DestroyCertList(certList);
  1496     return(NULL);
  1500 /* [ From certdb.c ] */
  1501 /*
  1502  * Filter a list of certificates, removing those certs that do not have
  1503  * one of the named CA certs somewhere in their cert chain.
  1505  *	"certList" - the list of certificates to filter
  1506  *	"nCANames" - number of CA names
  1507  *	"caNames" - array of CA names in string(rfc 1485) form
  1508  *	"usage" - what use the certs are for, this is used when
  1509  *		selecting CA certs
  1510  */
  1511 SECStatus
  1512 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
  1513 			     char **caNames, SECCertUsage usage)
  1515     CERTCertificate *issuerCert = NULL;
  1516     CERTCertificate *subjectCert;
  1517     CERTCertListNode *node, *freenode;
  1518     CERTCertificate *cert;
  1519     int n;
  1520     char **names;
  1521     PRBool found;
  1522     PRTime time;
  1524     if ( nCANames <= 0 ) {
  1525 	return(SECSuccess);
  1528     time = PR_Now();
  1530     node = CERT_LIST_HEAD(certList);
  1532     while ( ! CERT_LIST_END(node, certList) ) {
  1533 	cert = node->cert;
  1535 	subjectCert = CERT_DupCertificate(cert);
  1537 	/* traverse the CA certs for this cert */
  1538 	found = PR_FALSE;
  1539 	while ( subjectCert != NULL ) {
  1540 	    n = nCANames;
  1541 	    names = caNames;
  1543             if (subjectCert->issuerName != NULL) { 
  1544 	        while ( n > 0 ) {
  1545 		    if ( PORT_Strcmp(*names, subjectCert->issuerName) == 0 ) {
  1546 		        found = PR_TRUE;
  1547 		        break;
  1550 		    n--;
  1551 		    names++;
  1555 	    if ( found ) {
  1556 		break;
  1559 	    issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
  1560 	    if ( issuerCert == subjectCert ) {
  1561 		CERT_DestroyCertificate(issuerCert);
  1562 		issuerCert = NULL;
  1563 		break;
  1565 	    CERT_DestroyCertificate(subjectCert);
  1566 	    subjectCert = issuerCert;
  1569 	CERT_DestroyCertificate(subjectCert);
  1570 	if ( !found ) {
  1571 	    /* CA was not found, so remove this cert from the list */
  1572 	    freenode = node;
  1573 	    node = CERT_LIST_NEXT(node);
  1574 	    CERT_RemoveCertListNode(freenode);
  1575 	} else {
  1576 	    /* CA was found, so leave it in the list */
  1577 	    node = CERT_LIST_NEXT(node);
  1581     return(SECSuccess);
  1584 /*
  1585  * Given a certificate, return a string containing the nickname, and possibly
  1586  * one of the validity strings, based on the current validity state of the
  1587  * certificate.
  1589  * "arena" - arena to allocate returned string from.  If NULL, then heap
  1590  *	is used.
  1591  * "cert" - the cert to get nickname from
  1592  * "expiredString" - the string to append to the nickname if the cert is
  1593  *		expired.
  1594  * "notYetGoodString" - the string to append to the nickname if the cert is
  1595  *		not yet good.
  1596  */
  1597 char *
  1598 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
  1599 				 char *expiredString, char *notYetGoodString)
  1601     SECCertTimeValidity validity;
  1602     char *nickname = NULL, *tmpstr = NULL;
  1604     validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
  1606     /* if the cert is good, then just use the nickname directly */
  1607     if ( validity == secCertTimeValid ) {
  1608 	if ( arena == NULL ) {
  1609 	    nickname = PORT_Strdup(cert->nickname);
  1610 	} else {
  1611 	    nickname = PORT_ArenaStrdup(arena, cert->nickname);
  1614 	if ( nickname == NULL ) {
  1615 	    goto loser;
  1617     } else {
  1619 	/* if the cert is not valid, then tack one of the strings on the
  1620 	 * end
  1621 	 */
  1622 	if ( validity == secCertTimeExpired ) {
  1623 	    tmpstr = PR_smprintf("%s%s", cert->nickname,
  1624 				 expiredString);
  1625 	} else if ( validity == secCertTimeNotValidYet ) {
  1626 	    /* not yet valid */
  1627 	    tmpstr = PR_smprintf("%s%s", cert->nickname,
  1628 				 notYetGoodString);
  1629         } else {
  1630             /* undetermined */
  1631 	    tmpstr = PR_smprintf("%s",
  1632                         "(NULL) (Validity Unknown)");
  1635 	if ( tmpstr == NULL ) {
  1636 	    goto loser;
  1639 	if ( arena ) {
  1640 	    /* copy the string into the arena and free the malloc'd one */
  1641 	    nickname = PORT_ArenaStrdup(arena, tmpstr);
  1642 	    PORT_Free(tmpstr);
  1643 	} else {
  1644 	    nickname = tmpstr;
  1646 	if ( nickname == NULL ) {
  1647 	    goto loser;
  1650     return(nickname);
  1652 loser:
  1653     return(NULL);
  1656 /*
  1657  * Collect the nicknames from all certs in a CertList.  If the cert is not
  1658  * valid, append a string to that nickname.
  1660  * "certList" - the list of certificates
  1661  * "expiredString" - the string to append to the nickname of any expired cert
  1662  * "notYetGoodString" - the string to append to the nickname of any cert
  1663  *		that is not yet valid
  1664  */
  1665 CERTCertNicknames *
  1666 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
  1667 				 char *notYetGoodString)
  1669     CERTCertNicknames *names;
  1670     PLArenaPool *arena;
  1671     CERTCertListNode *node;
  1672     char **nn;
  1674     /* allocate an arena */
  1675     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1676     if ( arena == NULL ) {
  1677 	return(NULL);
  1680     /* allocate the structure */
  1681     names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
  1682     if ( names == NULL ) {
  1683 	goto loser;
  1686     /* init the structure */
  1687     names->arena = arena;
  1688     names->head = NULL;
  1689     names->numnicknames = 0;
  1690     names->nicknames = NULL;
  1691     names->totallen = 0;
  1693     /* count the certs in the list */
  1694     node = CERT_LIST_HEAD(certList);
  1695     while ( ! CERT_LIST_END(node, certList) ) {
  1696 	names->numnicknames++;
  1697 	node = CERT_LIST_NEXT(node);
  1700     /* allocate nicknames array */
  1701     names->nicknames = PORT_ArenaAlloc(arena,
  1702 				       sizeof(char *) * names->numnicknames);
  1703     if ( names->nicknames == NULL ) {
  1704 	goto loser;
  1707     /* just in case printf can't deal with null strings */
  1708     if (expiredString == NULL ) {
  1709 	expiredString = "";
  1712     if ( notYetGoodString == NULL ) {
  1713 	notYetGoodString = "";
  1716     /* traverse the list of certs and collect the nicknames */
  1717     nn = names->nicknames;
  1718     node = CERT_LIST_HEAD(certList);
  1719     while ( ! CERT_LIST_END(node, certList) ) {
  1720 	*nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
  1721 					       expiredString,
  1722 					       notYetGoodString);
  1723 	if ( *nn == NULL ) {
  1724 	    goto loser;
  1727 	names->totallen += PORT_Strlen(*nn);
  1729 	nn++;
  1730 	node = CERT_LIST_NEXT(node);
  1733     return(names);
  1735 loser:
  1736     PORT_FreeArena(arena, PR_FALSE);
  1737     return(NULL);
  1740 /*
  1741  * Extract the nickname from a nickmake string that may have either
  1742  * expiredString or notYetGoodString appended.
  1744  * Args:
  1745  *	"namestring" - the string containing the nickname, and possibly
  1746  *		one of the validity label strings
  1747  *	"expiredString" - the expired validity label string
  1748  *	"notYetGoodString" - the not yet good validity label string
  1750  * Returns the raw nickname
  1751  */
  1752 char *
  1753 CERT_ExtractNicknameString(char *namestring, char *expiredString,
  1754 			   char *notYetGoodString)
  1756     int explen, nyglen, namelen;
  1757     int retlen;
  1758     char *retstr;
  1760     namelen = PORT_Strlen(namestring);
  1761     explen = PORT_Strlen(expiredString);
  1762     nyglen = PORT_Strlen(notYetGoodString);
  1764     if ( namelen > explen ) {
  1765 	if ( PORT_Strcmp(expiredString, &namestring[namelen-explen]) == 0 ) {
  1766 	    retlen = namelen - explen;
  1767 	    retstr = (char *)PORT_Alloc(retlen+1);
  1768 	    if ( retstr == NULL ) {
  1769 		goto loser;
  1772 	    PORT_Memcpy(retstr, namestring, retlen);
  1773 	    retstr[retlen] = '\0';
  1774 	    goto done;
  1778     if ( namelen > nyglen ) {
  1779 	if ( PORT_Strcmp(notYetGoodString, &namestring[namelen-nyglen]) == 0) {
  1780 	    retlen = namelen - nyglen;
  1781 	    retstr = (char *)PORT_Alloc(retlen+1);
  1782 	    if ( retstr == NULL ) {
  1783 		goto loser;
  1786 	    PORT_Memcpy(retstr, namestring, retlen);
  1787 	    retstr[retlen] = '\0';
  1788 	    goto done;
  1792     /* if name string is shorter than either invalid string, then it must
  1793      * be a raw nickname
  1794      */
  1795     retstr = PORT_Strdup(namestring);
  1797 done:
  1798     return(retstr);
  1800 loser:
  1801     return(NULL);
  1804 CERTCertList *
  1805 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
  1807     CERTCertList *chain = NULL;
  1808     int count = 0;
  1810     if (NULL == cert) {
  1811         return NULL;
  1814     cert = CERT_DupCertificate(cert);
  1815     if (NULL == cert) {
  1816         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1817         return NULL;
  1820     chain = CERT_NewCertList();
  1821     if (NULL == chain) {
  1822         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1823         return NULL;
  1826     while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
  1827 	if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
  1828             /* return partial chain */
  1829             PORT_SetError(SEC_ERROR_NO_MEMORY);
  1830             return chain;
  1833 	if (cert->isRoot) {
  1834             /* return complete chain */
  1835 	    return chain;
  1838 	cert = CERT_FindCertIssuer(cert, time, usage);
  1841     /* return partial chain */
  1842     PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
  1843     return chain;

mercurial