security/nss/lib/certhigh/certvfy.c

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:bd61cff220b5
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"
19
20
21 #include "nsspki.h"
22 #include "pkitm.h"
23 #include "pkim.h"
24 #include "pki3hack.h"
25 #include "base.h"
26
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 }
36
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;
48
49 if ( !pubKey || !sd ) {
50 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
51 return SECFailure;
52 }
53
54 /* check the signature */
55 sig = sd->signature;
56 /* convert sig->len from bit counts to byte count. */
57 DER_ConvertBitString(&sig);
58
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 }
73
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;
84
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 }
93
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;
104
105 /* check the certificate's validity */
106 validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
107 if ( validity != secCertTimeValid ) {
108 return rv;
109 }
110
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 }
119
120
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 }
127
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;
141
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 }
174
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;
185
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 }
225
226 return(SECSuccess);
227 loser:
228 return(SECFailure);
229 }
230
231 void
232 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
233 unsigned int depth, void *arg)
234 {
235 CERTVerifyLogNode *node, *tnode;
236
237 PORT_Assert(log != NULL);
238
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;
246
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 }
276
277 tnode = tnode->prev;
278 }
279 }
280
281 log->count++;
282 }
283 return;
284 }
285
286 #define EXIT_IF_NOT_LOGGING(log) \
287 if ( log == NULL ) { \
288 goto loser; \
289 }
290
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 }
298
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 }
304
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;
332
333 if (revoked) {
334 *revoked = PR_FALSE;
335 }
336
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 }
346
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 }
384
385 subjectCert = CERT_DupCertificate(cert);
386 if ( subjectCert == NULL ) {
387 goto loser;
388 }
389
390 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
391 if (arena == NULL) {
392 goto loser;
393 }
394
395 certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
396 if (certsList == NULL)
397 goto loser;
398
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;
406
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 }
442
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 }
448
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 }
456
457 /* verify the signature on the cert */
458 if ( checkSig ) {
459 rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
460 issuerCert, t, wincx);
461
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 }
478
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 */
487
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 }
509
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 }
520
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 }
542
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;
550
551 if (certUsage != certUsageAnyCA &&
552 certUsage != certUsageStatusResponder) {
553
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 }
566
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 }
615
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 }
629
630 if ( !isca ) {
631 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
632 LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
633 }
634
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 }
641
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 }
664
665 CERT_DestroyCertificate(subjectCert);
666 subjectCert = issuerCert;
667 issuerCert = NULL;
668 }
669
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 }
681
682 if ( subjectCert ) {
683 CERT_DestroyCertificate(subjectCert);
684 }
685
686 if ( arena != NULL ) {
687 PORT_FreeArena(arena, PR_FALSE);
688 }
689 return rv;
690 }
691
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 }
705
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 }
714
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;
735
736
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 }
745
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 }
773
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 */
782
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 }
795
796 /* can't check path length if we don't know the previous path */
797 isca = PR_TRUE;
798 }
799
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 }
825
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 }
860
861 if (!isca) {
862 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
863 LOG_ERROR_OR_EXIT(log,cert,0,0);
864 }
865
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 }
880
881 return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
882 wincx, log);
883 loser:
884 rv = SECFailure;
885 done:
886 return rv;
887 }
888
889 #define NEXT_USAGE() { \
890 i*=2; \
891 certUsage++; \
892 continue; \
893 }
894
895 #define VALID_USAGE() { \
896 NEXT_USAGE(); \
897 }
898
899 #define INVALID_USAGE() { \
900 if (returnedUsages) { \
901 *returnedUsages &= (~i); \
902 } \
903 if (PR_TRUE == requiredUsage) { \
904 valid = SECFailure; \
905 } \
906 NEXT_USAGE(); \
907 }
908
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;
922
923 *failedFlags = 0;
924 *trusted = PR_FALSE;
925
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;
932
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 }
982
983 break;
984 case certUsageObjectSigner:
985 flags = trust.objectSigningFlags;
986
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;
1006 }
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;
1013 }
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;
1020 }
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;
1031 }
1032 }
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;
1039 }
1040 }
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;
1049 }
1050 }
1051 break;
1052 }
1053 }
1054 return SECSuccess;
1055 }
1056
1057 /*
1058 * verify a certificate by checking if it's valid and that we
1059 * trust the issuer.
1060 *
1061 * certificateUsage contains a bitfield of all cert usages that are
1062 * required for verification to succeed
1063 *
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
1067 *
1068 */
1069 SECStatus
1070 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
1071 PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
1072 void *wincx, CERTVerifyLog *log, SECCertificateUsage* returnedUsages)
1073 {
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;
1090
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;
1095 }
1096
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;
1103 }
1104 valid = SECSuccess ; /* start off assuming cert is valid */
1105
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);
1113 }
1114
1115 /* check key usage and netscape cert type */
1116 cert_GetCertType(cert);
1117 certType = cert->nsCertType;
1118
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();
1124 }
1125 if (returnedUsages) {
1126 *returnedUsages |= i; /* start off assuming this usage is valid */
1127 }
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();
1146 }
1147 break;
1148
1149 case certUsageAnyCA:
1150 case certUsageProtectedObjectSigner:
1151 case certUsageUserCertImport:
1152 case certUsageVerifyCA:
1153 /* these usages cannot be verified */
1154 NEXT_USAGE();
1155
1156 default:
1157 PORT_Assert(0);
1158 requiredKeyUsage = 0;
1159 requiredCertType = 0;
1160 INVALID_USAGE();
1161 }
1162 if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) {
1163 if (PR_TRUE == requiredUsage) {
1164 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1165 }
1166 LOG_ERROR(log,cert,0,requiredKeyUsage);
1167 INVALID_USAGE();
1168 }
1169 if ( !( certType & requiredCertType ) ) {
1170 if (PR_TRUE == requiredUsage) {
1171 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1172 }
1173 LOG_ERROR(log,cert,0,requiredCertType);
1174 INVALID_USAGE();
1175 }
1176
1177 rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
1178 if (rv == SECFailure) {
1179 if (PR_TRUE == requiredUsage) {
1180 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1181 }
1182 LOG_ERROR(log, cert, 0, flags);
1183 INVALID_USAGE();
1184 } else if (trusted) {
1185 VALID_USAGE();
1186 }
1187
1188 if (PR_TRUE == revoked || PR_TRUE == sigerror) {
1189 INVALID_USAGE();
1190 }
1191
1192 rv = cert_VerifyCertChain(handle, cert,
1193 checkSig, &sigerror,
1194 certUsage, t, wincx, log,
1195 &revoked);
1196
1197 if (rv != SECSuccess) {
1198 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
1199 INVALID_USAGE();
1200 }
1201
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 */
1209
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();
1222 }
1223 }
1224 }
1225 }
1226
1227 NEXT_USAGE();
1228 }
1229
1230 loser:
1231 return(valid);
1232 }
1233
1234 SECStatus
1235 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
1236 PRBool checkSig, SECCertUsage certUsage, PRTime t,
1237 void *wincx, CERTVerifyLog *log)
1238 {
1239 return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
1240 CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
1241 }
1242
1243 SECStatus
1244 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
1245 PRBool checkSig, SECCertUsage certUsage, PRTime t,
1246 PRUint32 flags, void *wincx, CERTVerifyLog *log)
1247 {
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;
1257
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);
1264 }
1265 #endif
1266
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);
1273 }
1274
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;
1295 }
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;
1303 }
1304 break;
1305 default:
1306 PORT_Assert(0);
1307 EXIT_IF_NOT_LOGGING(log);
1308 requiredKeyUsage = 0;
1309 requiredCertType = 0;
1310 }
1311 if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) {
1312 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1313 LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage);
1314 }
1315 if ( !( certType & requiredCertType ) ) {
1316 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1317 LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
1318 }
1319
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;
1326 }
1327
1328
1329 rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
1330 t, wincx, log);
1331 if (rv != SECSuccess) {
1332 EXIT_IF_NOT_LOGGING(log);
1333 }
1334
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);
1351 }
1352 }
1353 }
1354
1355 done:
1356 if (log && log->head) {
1357 return SECFailure;
1358 }
1359 return(SECSuccess);
1360
1361 loser:
1362 rv = SECFailure;
1363
1364 return(rv);
1365 }
1366
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)
1375 {
1376 return(CERT_VerifyCertificate(handle, cert, checkSig,
1377 requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
1378 }
1379
1380 /* obsolete, do not use for new code */
1381 SECStatus
1382 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1383 PRBool checkSig, SECCertUsage certUsage, void *wincx)
1384 {
1385 return(CERT_VerifyCert(handle, cert, checkSig,
1386 certUsage, PR_Now(), wincx, NULL));
1387 }
1388
1389
1390 /* [ FROM pcertdb.c ] */
1391 /*
1392 * Supported usage values and types:
1393 * certUsageSSLClient
1394 * certUsageSSLServer
1395 * certUsageSSLServerWithStepUp
1396 * certUsageEmailSigner
1397 * certUsageEmailRecipient
1398 * certUsageObjectSigner
1399 */
1400
1401 CERTCertificate *
1402 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
1403 CERTCertOwner owner, SECCertUsage usage,
1404 PRBool preferTrusted, PRTime validTime, PRBool validOnly)
1405 {
1406 CERTCertList *certList = NULL;
1407 CERTCertificate *cert = NULL;
1408 CERTCertTrust certTrust;
1409 unsigned int requiredTrustFlags;
1410 SECTrustType requiredTrustType;
1411 unsigned int flags;
1412
1413 PRBool lookingForCA = PR_FALSE;
1414 SECStatus rv;
1415 CERTCertListNode *node;
1416 CERTCertificate *saveUntrustedCA = NULL;
1417
1418 /* if preferTrusted is set, must be a CA cert */
1419 PORT_Assert( ! ( preferTrusted && ( owner != certOwnerCA ) ) );
1420
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;
1428 }
1429 requiredTrustFlags |= CERTDB_VALID_CA;
1430 }
1431 }
1432
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;
1439 }
1440
1441 node = CERT_LIST_HEAD(certList);
1442
1443 while ( !CERT_LIST_END(node, certList) ) {
1444 cert = node->cert;
1445
1446 /* looking for a trusted CA cert */
1447 if ( ( owner == certOwnerCA ) && preferTrusted &&
1448 ( requiredTrustType != trustTypeNone ) ) {
1449
1450 if ( CERT_GetCertTrust(cert, &certTrust) != SECSuccess ) {
1451 flags = 0;
1452 } else {
1453 flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
1454 }
1455
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;
1463 }
1464 goto endloop;
1465 }
1466 }
1467 /* if we got this far, then this cert meets all criteria */
1468 break;
1469
1470 endloop:
1471 node = CERT_LIST_NEXT(node);
1472 cert = NULL;
1473 }
1474
1475 /* use the saved one if we have it */
1476 if ( cert == NULL ) {
1477 cert = saveUntrustedCA;
1478 }
1479
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);
1484 }
1485
1486 CERT_DestroyCertList(certList);
1487 }
1488
1489 return(cert);
1490
1491 loser:
1492 if ( certList != NULL ) {
1493 CERT_DestroyCertList(certList);
1494 }
1495
1496 return(NULL);
1497 }
1498
1499
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.
1504 *
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)
1514 {
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;
1523
1524 if ( nCANames <= 0 ) {
1525 return(SECSuccess);
1526 }
1527
1528 time = PR_Now();
1529
1530 node = CERT_LIST_HEAD(certList);
1531
1532 while ( ! CERT_LIST_END(node, certList) ) {
1533 cert = node->cert;
1534
1535 subjectCert = CERT_DupCertificate(cert);
1536
1537 /* traverse the CA certs for this cert */
1538 found = PR_FALSE;
1539 while ( subjectCert != NULL ) {
1540 n = nCANames;
1541 names = caNames;
1542
1543 if (subjectCert->issuerName != NULL) {
1544 while ( n > 0 ) {
1545 if ( PORT_Strcmp(*names, subjectCert->issuerName) == 0 ) {
1546 found = PR_TRUE;
1547 break;
1548 }
1549
1550 n--;
1551 names++;
1552 }
1553 }
1554
1555 if ( found ) {
1556 break;
1557 }
1558
1559 issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
1560 if ( issuerCert == subjectCert ) {
1561 CERT_DestroyCertificate(issuerCert);
1562 issuerCert = NULL;
1563 break;
1564 }
1565 CERT_DestroyCertificate(subjectCert);
1566 subjectCert = issuerCert;
1567
1568 }
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);
1578 }
1579 }
1580
1581 return(SECSuccess);
1582 }
1583
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.
1588 *
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)
1600 {
1601 SECCertTimeValidity validity;
1602 char *nickname = NULL, *tmpstr = NULL;
1603
1604 validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
1605
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);
1612 }
1613
1614 if ( nickname == NULL ) {
1615 goto loser;
1616 }
1617 } else {
1618
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)");
1633 }
1634
1635 if ( tmpstr == NULL ) {
1636 goto loser;
1637 }
1638
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;
1645 }
1646 if ( nickname == NULL ) {
1647 goto loser;
1648 }
1649 }
1650 return(nickname);
1651
1652 loser:
1653 return(NULL);
1654 }
1655
1656 /*
1657 * Collect the nicknames from all certs in a CertList. If the cert is not
1658 * valid, append a string to that nickname.
1659 *
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)
1668 {
1669 CERTCertNicknames *names;
1670 PLArenaPool *arena;
1671 CERTCertListNode *node;
1672 char **nn;
1673
1674 /* allocate an arena */
1675 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1676 if ( arena == NULL ) {
1677 return(NULL);
1678 }
1679
1680 /* allocate the structure */
1681 names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
1682 if ( names == NULL ) {
1683 goto loser;
1684 }
1685
1686 /* init the structure */
1687 names->arena = arena;
1688 names->head = NULL;
1689 names->numnicknames = 0;
1690 names->nicknames = NULL;
1691 names->totallen = 0;
1692
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);
1698 }
1699
1700 /* allocate nicknames array */
1701 names->nicknames = PORT_ArenaAlloc(arena,
1702 sizeof(char *) * names->numnicknames);
1703 if ( names->nicknames == NULL ) {
1704 goto loser;
1705 }
1706
1707 /* just in case printf can't deal with null strings */
1708 if (expiredString == NULL ) {
1709 expiredString = "";
1710 }
1711
1712 if ( notYetGoodString == NULL ) {
1713 notYetGoodString = "";
1714 }
1715
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;
1725 }
1726
1727 names->totallen += PORT_Strlen(*nn);
1728
1729 nn++;
1730 node = CERT_LIST_NEXT(node);
1731 }
1732
1733 return(names);
1734
1735 loser:
1736 PORT_FreeArena(arena, PR_FALSE);
1737 return(NULL);
1738 }
1739
1740 /*
1741 * Extract the nickname from a nickmake string that may have either
1742 * expiredString or notYetGoodString appended.
1743 *
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
1749 *
1750 * Returns the raw nickname
1751 */
1752 char *
1753 CERT_ExtractNicknameString(char *namestring, char *expiredString,
1754 char *notYetGoodString)
1755 {
1756 int explen, nyglen, namelen;
1757 int retlen;
1758 char *retstr;
1759
1760 namelen = PORT_Strlen(namestring);
1761 explen = PORT_Strlen(expiredString);
1762 nyglen = PORT_Strlen(notYetGoodString);
1763
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;
1770 }
1771
1772 PORT_Memcpy(retstr, namestring, retlen);
1773 retstr[retlen] = '\0';
1774 goto done;
1775 }
1776 }
1777
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;
1784 }
1785
1786 PORT_Memcpy(retstr, namestring, retlen);
1787 retstr[retlen] = '\0';
1788 goto done;
1789 }
1790 }
1791
1792 /* if name string is shorter than either invalid string, then it must
1793 * be a raw nickname
1794 */
1795 retstr = PORT_Strdup(namestring);
1796
1797 done:
1798 return(retstr);
1799
1800 loser:
1801 return(NULL);
1802 }
1803
1804 CERTCertList *
1805 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
1806 {
1807 CERTCertList *chain = NULL;
1808 int count = 0;
1809
1810 if (NULL == cert) {
1811 return NULL;
1812 }
1813
1814 cert = CERT_DupCertificate(cert);
1815 if (NULL == cert) {
1816 PORT_SetError(SEC_ERROR_NO_MEMORY);
1817 return NULL;
1818 }
1819
1820 chain = CERT_NewCertList();
1821 if (NULL == chain) {
1822 PORT_SetError(SEC_ERROR_NO_MEMORY);
1823 return NULL;
1824 }
1825
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;
1831 }
1832
1833 if (cert->isRoot) {
1834 /* return complete chain */
1835 return chain;
1836 }
1837
1838 cert = CERT_FindCertIssuer(cert, time, usage);
1839 }
1840
1841 /* return partial chain */
1842 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
1843 return chain;
1844 }

mercurial