Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Side by Side Diff: nss/lib/certhigh/certvfy.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/certhigh/certreq.c ('k') | nss/lib/certhigh/certvfypkix.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "genname.h"
10 #include "keyhi.h"
11 #include "cert.h"
12 #include "certdb.h"
13 #include "certi.h"
14 #include "cryptohi.h"
15 #ifndef NSS_DISABLE_LIBPKIX
16 #include "pkix.h"
17 /*#include "pkix_sample_modules.h" */
18 #include "pkix_pl_cert.h"
19 #endif /* NSS_DISABLE_LIBPKIX */
20
21 #include "nsspki.h"
22 #include "pkitm.h"
23 #include "pkim.h"
24 #include "pki3hack.h"
25 #include "base.h"
26 #include "keyhi.h"
27
28 #ifdef NSS_DISABLE_LIBPKIX
29 SECStatus
30 cert_VerifyCertChainPkix(
31 CERTCertificate *cert,
32 PRBool checkSig,
33 SECCertUsage requiredUsage,
34 PRTime time,
35 void *wincx,
36 CERTVerifyLog *log,
37 PRBool *pSigerror,
38 PRBool *pRevoked)
39 {
40 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
41 return SECFailure;
42 }
43
44 SECStatus
45 CERT_SetUsePKIXForValidation(PRBool enable)
46 {
47 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
48 return SECFailure;
49 }
50
51 PRBool
52 CERT_GetUsePKIXForValidation()
53 {
54 return PR_FALSE;
55 }
56
57 SECStatus CERT_PKIXVerifyCert(
58 CERTCertificate *cert,
59 SECCertificateUsage usages,
60 CERTValInParam *paramsIn,
61 CERTValOutParam *paramsOut,
62 void *wincx)
63 {
64 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
65 return SECFailure;
66 }
67 #endif /* NSS_DISABLE_LIBPKIX */
68
69 /*
70 * Check the validity times of a certificate
71 */
72 SECStatus
73 CERT_CertTimesValid(CERTCertificate *c)
74 {
75 SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE);
76 return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
77 }
78
79 SECStatus
80 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
81 {
82 SECStatus rv;
83 SECOidTag sigAlg;
84 SECOidTag curve;
85 PRUint32 policyFlags = 0;
86 PRInt32 minLen, len;
87
88 sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
89
90 switch (sigAlg) {
91 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
92 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
93 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
94 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
95 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
96 if (key->keyType != ecKey) {
97 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
98 return SECFailure;
99 }
100
101 curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams);
102 if (curve != 0) {
103 if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
104 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
105 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
106 return SECFailure;
107 } else {
108 return SECSuccess;
109 }
110 } else {
111 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
112 return SECFailure;
113 }
114 return SECSuccess;
115 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
116 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
117 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
118 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
119 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
120 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
121 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
122 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
123 if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
124 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
125 return SECFailure;
126 }
127
128 len = 8 * key->u.rsa.modulus.len;
129
130 rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
131 if (rv != SECSuccess) {
132 return SECFailure;
133 }
134
135 if (len < minLen) {
136 return SECFailure;
137 }
138
139 return SECSuccess;
140 case SEC_OID_ANSIX9_DSA_SIGNATURE:
141 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
142 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
143 case SEC_OID_SDN702_DSA_SIGNATURE:
144 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
145 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
146 if (key->keyType != dsaKey) {
147 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
148 return SECFailure;
149 }
150
151 len = 8 * key->u.dsa.params.prime.len;
152
153 rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen);
154 if (rv != SECSuccess) {
155 return SECFailure;
156 }
157
158 if (len < minLen) {
159 return SECFailure;
160 }
161
162 return SECSuccess;
163 default:
164 return SECSuccess;
165 }
166 }
167
168 /*
169 * verify the signature of a signed data object with the given DER publickey
170 */
171 SECStatus
172 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
173 SECKEYPublicKey *pubKey,
174 void *wincx)
175 {
176 SECStatus rv;
177 SECItem sig;
178 SECOidTag hashAlg = SEC_OID_UNKNOWN;
179
180 if (!pubKey || !sd) {
181 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
182 return SECFailure;
183 }
184 /* check the signature */
185 sig = sd->signature;
186 /* convert sig->len from bit counts to byte count. */
187 DER_ConvertBitString(&sig);
188
189 rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
190 &sig, &sd->signatureAlgorithm, &hashAlg, wincx);
191 if (rv == SECSuccess) {
192 /* Are we honoring signatures for this algorithm? */
193 PRUint32 policyFlags = 0;
194 rv = checkKeyParams(&sd->signatureAlgorithm, pubKey);
195 if (rv != SECSuccess) {
196 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
197 return SECFailure;
198 }
199
200 rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
201 if (rv == SECSuccess &&
202 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
203 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
204 return SECFailure;
205 }
206 }
207 return rv;
208 }
209
210 /*
211 * verify the signature of a signed data object with the given DER publickey
212 */
213 SECStatus
214 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd,
215 CERTSubjectPublicKeyInfo *pubKeyInfo,
216 void *wincx)
217 {
218 SECKEYPublicKey *pubKey;
219 SECStatus rv = SECFailure;
220
221 /* get cert's public key */
222 pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
223 if (pubKey) {
224 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
225 SECKEY_DestroyPublicKey(pubKey);
226 }
227 return rv;
228 }
229
230 /*
231 * verify the signature of a signed data object with the given certificate
232 */
233 SECStatus
234 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
235 PRTime t, void *wincx)
236 {
237 SECKEYPublicKey *pubKey = 0;
238 SECStatus rv = SECFailure;
239 SECCertTimeValidity validity;
240
241 /* check the certificate's validity */
242 validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
243 if (validity != secCertTimeValid) {
244 return rv;
245 }
246
247 /* get cert's public key */
248 pubKey = CERT_ExtractPublicKey(cert);
249 if (pubKey) {
250 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
251 SECKEY_DestroyPublicKey(pubKey);
252 }
253 return rv;
254 }
255
256 SECStatus
257 SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert,
258 CERTCertificate *caCert, PRTime t, void *wincx)
259 {
260 return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
261 }
262
263 /*
264 * Find the issuer of a cert. Use the authorityKeyID if it exists.
265 */
266 CERTCertificate *
267 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage)
268 {
269 NSSCertificate *me;
270 NSSTime *nssTime;
271 NSSTrustDomain *td;
272 NSSCryptoContext *cc;
273 NSSCertificate *chain[3];
274 NSSUsage nssUsage;
275 PRStatus status;
276
277 me = STAN_GetNSSCertificate(cert);
278 if (!me) {
279 PORT_SetError(SEC_ERROR_NO_MEMORY);
280 return NULL;
281 }
282 nssTime = NSSTime_SetPRTime(NULL, validTime);
283 nssUsage.anyUsage = PR_FALSE;
284 nssUsage.nss3usage = usage;
285 nssUsage.nss3lookingForCA = PR_TRUE;
286 memset(chain, 0, 3 * sizeof(NSSCertificate *));
287 td = STAN_GetDefaultTrustDomain();
288 cc = STAN_GetDefaultCryptoContext();
289 (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL,
290 chain, 2, NULL, &status, td, cc);
291 nss_ZFreeIf(nssTime);
292 if (status == PR_SUCCESS) {
293 PORT_Assert(me == chain[0]);
294 /* if it's a root, the chain will only have one cert */
295 if (!chain[1]) {
296 /* already has a reference from the call to BuildChain */
297 return cert;
298 }
299 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
300 return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
301 }
302 if (chain[0]) {
303 PORT_Assert(me == chain[0]);
304 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
305 }
306 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
307 return NULL;
308 }
309
310 /*
311 * return required trust flags for various cert usages for CAs
312 */
313 SECStatus
314 CERT_TrustFlagsForCACertUsage(SECCertUsage usage,
315 unsigned int *retFlags,
316 SECTrustType *retTrustType)
317 {
318 unsigned int requiredFlags;
319 SECTrustType trustType;
320
321 switch (usage) {
322 case certUsageSSLClient:
323 requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
324 trustType = trustSSL;
325 break;
326 case certUsageSSLServer:
327 case certUsageSSLCA:
328 requiredFlags = CERTDB_TRUSTED_CA;
329 trustType = trustSSL;
330 break;
331 case certUsageSSLServerWithStepUp:
332 requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
333 trustType = trustSSL;
334 break;
335 case certUsageEmailSigner:
336 case certUsageEmailRecipient:
337 requiredFlags = CERTDB_TRUSTED_CA;
338 trustType = trustEmail;
339 break;
340 case certUsageObjectSigner:
341 requiredFlags = CERTDB_TRUSTED_CA;
342 trustType = trustObjectSigning;
343 break;
344 case certUsageVerifyCA:
345 case certUsageAnyCA:
346 case certUsageStatusResponder:
347 requiredFlags = CERTDB_TRUSTED_CA;
348 trustType = trustTypeNone;
349 break;
350 default:
351 PORT_Assert(0);
352 goto loser;
353 }
354 if (retFlags != NULL) {
355 *retFlags = requiredFlags;
356 }
357 if (retTrustType != NULL) {
358 *retTrustType = trustType;
359 }
360
361 return (SECSuccess);
362 loser:
363 return (SECFailure);
364 }
365
366 void
367 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
368 unsigned int depth, void *arg)
369 {
370 CERTVerifyLogNode *node, *tnode;
371
372 PORT_Assert(log != NULL);
373
374 node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
375 sizeof(CERTVerifyLogNode));
376 if (node != NULL) {
377 node->cert = CERT_DupCertificate(cert);
378 node->error = error;
379 node->depth = depth;
380 node->arg = arg;
381
382 if (log->tail == NULL) {
383 /* empty list */
384 log->head = log->tail = node;
385 node->prev = NULL;
386 node->next = NULL;
387 } else if (depth >= log->tail->depth) {
388 /* add to tail */
389 node->prev = log->tail;
390 log->tail->next = node;
391 log->tail = node;
392 node->next = NULL;
393 } else if (depth < log->head->depth) {
394 /* add at head */
395 node->prev = NULL;
396 node->next = log->head;
397 log->head->prev = node;
398 log->head = node;
399 } else {
400 /* add in middle */
401 tnode = log->tail;
402 while (tnode != NULL) {
403 if (depth >= tnode->depth) {
404 /* insert after tnode */
405 node->prev = tnode;
406 node->next = tnode->next;
407 tnode->next->prev = node;
408 tnode->next = node;
409 break;
410 }
411
412 tnode = tnode->prev;
413 }
414 }
415
416 log->count++;
417 }
418 return;
419 }
420
421 #define EXIT_IF_NOT_LOGGING(log) \
422 if (log == NULL) { \
423 goto loser; \
424 }
425
426 #define LOG_ERROR_OR_EXIT(log, cert, depth, arg) \
427 if (log != NULL) { \
428 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
429 (void *)(PRWord)arg); \
430 } else { \
431 goto loser; \
432 }
433
434 #define LOG_ERROR(log, cert, depth, arg) \
435 if (log != NULL) { \
436 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
437 (void *)(PRWord)arg); \
438 }
439
440 static SECStatus
441 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
442 PRBool checkSig, PRBool *sigerror,
443 SECCertUsage certUsage, PRTime t, void *wincx,
444 CERTVerifyLog *log, PRBool *revoked)
445 {
446 SECTrustType trustType;
447 CERTBasicConstraints basicConstraint;
448 CERTCertificate *issuerCert = NULL;
449 CERTCertificate *subjectCert = NULL;
450 CERTCertificate *badCert = NULL;
451 PRBool isca;
452 SECStatus rv;
453 SECStatus rvFinal = SECSuccess;
454 int count;
455 int currentPathLen = 0;
456 int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
457 unsigned int caCertType;
458 unsigned int requiredCAKeyUsage;
459 unsigned int requiredFlags;
460 PLArenaPool *arena = NULL;
461 CERTGeneralName *namesList = NULL;
462 CERTCertificate **certsList = NULL;
463 int certsListLen = 16;
464 int namesCount = 0;
465 PRBool subjectCertIsSelfIssued;
466 CERTCertTrust issuerTrust;
467
468 if (revoked) {
469 *revoked = PR_FALSE;
470 }
471
472 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
473 &requiredCAKeyUsage,
474 &caCertType) !=
475 SECSuccess) {
476 PORT_Assert(0);
477 EXIT_IF_NOT_LOGGING(log);
478 requiredCAKeyUsage = 0;
479 caCertType = 0;
480 }
481
482 switch (certUsage) {
483 case certUsageSSLClient:
484 case certUsageSSLServer:
485 case certUsageSSLCA:
486 case certUsageSSLServerWithStepUp:
487 case certUsageEmailSigner:
488 case certUsageEmailRecipient:
489 case certUsageObjectSigner:
490 case certUsageVerifyCA:
491 case certUsageAnyCA:
492 case certUsageStatusResponder:
493 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
494 &trustType) != SECSuccess) {
495 PORT_Assert(0);
496 EXIT_IF_NOT_LOGGING(log);
497 /* XXX continuing with requiredFlags = 0 seems wrong. It'll
498 * cause the following test to be true incorrectly:
499 * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
500 * if (( flags & requiredFlags ) == requiredFlags) {
501 * rv = rvFinal;
502 * goto done;
503 * }
504 * There are three other instances of this problem.
505 */
506 requiredFlags = 0;
507 trustType = trustSSL;
508 }
509 break;
510 default:
511 PORT_Assert(0);
512 EXIT_IF_NOT_LOGGING(log);
513 requiredFlags = 0;
514 trustType = trustSSL; /* This used to be 0, but we need something
515 * that matches the enumeration type.
516 */
517 caCertType = 0;
518 }
519
520 subjectCert = CERT_DupCertificate(cert);
521 if (subjectCert == NULL) {
522 goto loser;
523 }
524
525 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
526 if (arena == NULL) {
527 goto loser;
528 }
529
530 certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
531 if (certsList == NULL)
532 goto loser;
533
534 /* RFC 3280 says that the name constraints will apply to the names
535 ** in the leaf (EE) cert, whether it is self issued or not, so
536 ** we pretend that it is not.
537 */
538 subjectCertIsSelfIssued = PR_FALSE;
539 for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) {
540 PRBool validCAOverride = PR_FALSE;
541
542 /* Construct a list of names for the current and all previous
543 * certifcates (except leaf (EE) certs, root CAs, and self-issued
544 * intermediate CAs) to be verified against the name constraints
545 * extension of the issuer certificate.
546 */
547 if (subjectCertIsSelfIssued == PR_FALSE) {
548 CERTGeneralName *subjectNameList;
549 int subjectNameListLen;
550 int i;
551 PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer);
552 subjectNameList =
553 CERT_GetConstrainedCertificateNames(subjectCert, arena,
554 getSubjectCN);
555 if (!subjectNameList)
556 goto loser;
557 subjectNameListLen = CERT_GetNamesLength(subjectNameList);
558 if (!subjectNameListLen)
559 goto loser;
560 if (certsListLen <= namesCount + subjectNameListLen) {
561 CERTCertificate **tmpCertsList;
562 certsListLen = (namesCount + subjectNameListLen) * 2;
563 tmpCertsList =
564 (CERTCertificate **)PORT_Realloc(certsList,
565 certsListLen *
566 sizeof(CERTCertificate *));
567 if (tmpCertsList == NULL) {
568 goto loser;
569 }
570 certsList = tmpCertsList;
571 }
572 for (i = 0; i < subjectNameListLen; i++) {
573 certsList[namesCount + i] = subjectCert;
574 }
575 namesCount += subjectNameListLen;
576 namesList = cert_CombineNamesLists(namesList, subjectNameList);
577 }
578
579 /* check if the cert has an unsupported critical extension */
580 if (subjectCert->options.bits.hasUnsupportedCriticalExt) {
581 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
582 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
583 }
584
585 /* find the certificate of the issuer */
586 issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
587 if (!issuerCert) {
588 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
589 LOG_ERROR(log, subjectCert, count, 0);
590 goto loser;
591 }
592
593 /* verify the signature on the cert */
594 if (checkSig) {
595 rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
596 issuerCert, t, wincx);
597
598 if (rv != SECSuccess) {
599 if (sigerror) {
600 *sigerror = PR_TRUE;
601 }
602 if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) {
603 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
604 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
605 } else {
606 if (PORT_GetError() !=
607 SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
608 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
609 }
610 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
611 }
612 }
613 }
614
615 /* If the basicConstraint extension is included in an immediate CA
616 * certificate, make sure that the isCA flag is on. If the
617 * pathLenConstraint component exists, it must be greater than the
618 * number of CA certificates we have seen so far. If the extension
619 * is omitted, we will assume that this is a CA certificate with
620 * an unlimited pathLenConstraint (since it already passes the
621 * netscape-cert-type extension checking).
622 */
623
624 rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
625 if (rv != SECSuccess) {
626 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
627 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
628 }
629 pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
630 /* no basic constraints found, we aren't (yet) a CA. */
631 isca = PR_FALSE;
632 } else {
633 if (basicConstraint.isCA == PR_FALSE) {
634 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
635 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
636 }
637 pathLengthLimit = basicConstraint.pathLenConstraint;
638 isca = PR_TRUE;
639 }
640 /* make sure that the path len constraint is properly set.*/
641 if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) {
642 PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
643 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit);
644 }
645
646 /* make sure that the entire chain is within the name space of the
647 * current issuer certificate.
648 */
649 rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
650 arena, &badCert);
651 if (rv != SECSuccess || badCert != NULL) {
652 PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
653 LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
654 goto loser;
655 }
656
657 /* XXX - the error logging may need to go down into CRL stuff at some
658 * point
659 */
660 /* check revoked list (issuer) */
661 rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
662 if (rv == SECFailure) {
663 if (revoked) {
664 *revoked = PR_TRUE;
665 }
666 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
667 } else if (rv == SECWouldBlock) {
668 /* We found something fishy, so we intend to issue an
669 * error to the user, but the user may wish to continue
670 * processing, in which case we better make sure nothing
671 * worse has happened... so keep cranking the loop */
672 rvFinal = SECFailure;
673 if (revoked) {
674 *revoked = PR_TRUE;
675 }
676 LOG_ERROR(log, subjectCert, count, 0);
677 }
678
679 if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) {
680 /* we have some trust info, but this does NOT imply that this
681 * cert is actually trusted for any purpose. The cert may be
682 * explicitly UNtrusted. We won't know until we examine the
683 * trust bits.
684 */
685 unsigned int flags;
686
687 if (certUsage != certUsageAnyCA &&
688 certUsage != certUsageStatusResponder) {
689
690 /*
691 * XXX This choice of trustType seems arbitrary.
692 */
693 if (certUsage == certUsageVerifyCA) {
694 if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
695 trustType = trustEmail;
696 } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
697 trustType = trustSSL;
698 } else {
699 trustType = trustObjectSigning;
700 }
701 }
702
703 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
704 if ((flags & requiredFlags) == requiredFlags) {
705 /* we found a trusted one, so return */
706 rv = rvFinal;
707 goto done;
708 }
709 if (flags & CERTDB_VALID_CA) {
710 validCAOverride = PR_TRUE;
711 }
712 /* is it explicitly distrusted? */
713 if ((flags & CERTDB_TERMINAL_RECORD) &&
714 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
715 /* untrusted -- the cert is explicitly untrusted, not
716 * just that it doesn't chain to a trusted cert */
717 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
718 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
719 }
720 } else {
721 /* Check if we have any valid trust when cheching for
722 * certUsageAnyCA or certUsageStatusResponder. */
723 for (trustType = trustSSL; trustType < trustTypeNone;
724 trustType++) {
725 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
726 if ((flags & requiredFlags) == requiredFlags) {
727 rv = rvFinal;
728 goto done;
729 }
730 if (flags & CERTDB_VALID_CA)
731 validCAOverride = PR_TRUE;
732 }
733 /* We have 2 separate loops because we want any single trust
734 * bit to allow this usage to return trusted. Only if none of
735 * the trust bits are on do we check to see if the cert is
736 * untrusted */
737 for (trustType = trustSSL; trustType < trustTypeNone;
738 trustType++) {
739 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
740 /* is it explicitly distrusted? */
741 if ((flags & CERTDB_TERMINAL_RECORD) &&
742 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
743 /* untrusted -- the cert is explicitly untrusted, not
744 * just that it doesn't chain to a trusted cert */
745 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
746 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
747 }
748 }
749 }
750 }
751
752 if (!validCAOverride) {
753 /*
754 * Make sure that if this is an intermediate CA in the chain that
755 * it was given permission by its signer to be a CA.
756 */
757 /*
758 * if basicConstraints says it is a ca, then we check the
759 * nsCertType. If the nsCertType has any CA bits set, then
760 * it must have the right one.
761 */
762 if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
763 isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALS E;
764 }
765
766 if (!isca) {
767 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
768 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
769 }
770
771 /* make sure key usage allows cert signing */
772 if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess ) {
773 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
774 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage );
775 }
776 }
777
778 /* make sure that the issuer is not self signed. If it is, then
779 * stop here to prevent looping.
780 */
781 if (issuerCert->isRoot) {
782 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
783 LOG_ERROR(log, issuerCert, count + 1, 0);
784 goto loser;
785 }
786 /* The issuer cert will be the subject cert in the next loop.
787 * A cert is self-issued if its subject and issuer are equal and
788 * both are of non-zero length.
789 */
790 subjectCertIsSelfIssued = (PRBool)
791 SECITEM_ItemsAreEqual(&issuerCert->derIssu er,
792 &issuerCert->derSubj ect) &&
793 issuerCert->derSubject.len >
794 0;
795 if (subjectCertIsSelfIssued == PR_FALSE) {
796 /* RFC 3280 says only non-self-issued intermediate CA certs
797 * count in path length.
798 */
799 ++currentPathLen;
800 }
801
802 CERT_DestroyCertificate(subjectCert);
803 subjectCert = issuerCert;
804 issuerCert = NULL;
805 }
806
807 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
808 LOG_ERROR(log, subjectCert, count, 0);
809 loser:
810 rv = SECFailure;
811 done:
812 if (certsList != NULL) {
813 PORT_Free(certsList);
814 }
815 if (issuerCert) {
816 CERT_DestroyCertificate(issuerCert);
817 }
818
819 if (subjectCert) {
820 CERT_DestroyCertificate(subjectCert);
821 }
822
823 if (arena != NULL) {
824 PORT_FreeArena(arena, PR_FALSE);
825 }
826 return rv;
827 }
828
829 SECStatus
830 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
831 PRBool checkSig, PRBool *sigerror,
832 SECCertUsage certUsage, PRTime t, void *wincx,
833 CERTVerifyLog *log, PRBool *revoked)
834 {
835 if (CERT_GetUsePKIXForValidation()) {
836 return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
837 wincx, log, sigerror, revoked);
838 }
839 return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
840 certUsage, t, wincx, log, revoked);
841 }
842
843 SECStatus
844 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
845 PRBool checkSig, SECCertUsage certUsage, PRTime t,
846 void *wincx, CERTVerifyLog *log)
847 {
848 return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
849 wincx, log, NULL);
850 }
851
852 /*
853 * verify that a CA can sign a certificate with the requested usage.
854 */
855 SECStatus
856 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
857 PRBool checkSig, SECCertUsage certUsage, PRTime t,
858 void *wincx, CERTVerifyLog *log)
859 {
860 SECTrustType trustType;
861 CERTBasicConstraints basicConstraint;
862 PRBool isca;
863 PRBool validCAOverride = PR_FALSE;
864 SECStatus rv;
865 SECStatus rvFinal = SECSuccess;
866 unsigned int flags;
867 unsigned int caCertType;
868 unsigned int requiredCAKeyUsage;
869 unsigned int requiredFlags;
870 CERTCertificate *issuerCert;
871 CERTCertTrust certTrust;
872
873 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
874 &requiredCAKeyUsage,
875 &caCertType) != SECSuccess) {
876 PORT_Assert(0);
877 EXIT_IF_NOT_LOGGING(log);
878 requiredCAKeyUsage = 0;
879 caCertType = 0;
880 }
881
882 switch (certUsage) {
883 case certUsageSSLClient:
884 case certUsageSSLServer:
885 case certUsageSSLCA:
886 case certUsageSSLServerWithStepUp:
887 case certUsageEmailSigner:
888 case certUsageEmailRecipient:
889 case certUsageObjectSigner:
890 case certUsageVerifyCA:
891 case certUsageStatusResponder:
892 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
893 &trustType) != SECSuccess) {
894 PORT_Assert(0);
895 EXIT_IF_NOT_LOGGING(log);
896 requiredFlags = 0;
897 trustType = trustSSL;
898 }
899 break;
900 default:
901 PORT_Assert(0);
902 EXIT_IF_NOT_LOGGING(log);
903 requiredFlags = 0;
904 trustType = trustSSL; /* This used to be 0, but we need something
905 * that matches the enumeration type.
906 */
907 caCertType = 0;
908 }
909
910 /* If the basicConstraint extension is included in an intermmediate CA
911 * certificate, make sure that the isCA flag is on. If the
912 * pathLenConstraint component exists, it must be greater than the
913 * number of CA certificates we have seen so far. If the extension
914 * is omitted, we will assume that this is a CA certificate with
915 * an unlimited pathLenConstraint (since it already passes the
916 * netscape-cert-type extension checking).
917 */
918
919 rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
920 if (rv != SECSuccess) {
921 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
922 LOG_ERROR_OR_EXIT(log, cert, 0, 0);
923 }
924 /* no basic constraints found, we aren't (yet) a CA. */
925 isca = PR_FALSE;
926 } else {
927 if (basicConstraint.isCA == PR_FALSE) {
928 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
929 LOG_ERROR_OR_EXIT(log, cert, 0, 0);
930 }
931
932 /* can't check path length if we don't know the previous path */
933 isca = PR_TRUE;
934 }
935
936 if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
937 /* we have some trust info, but this does NOT imply that this
938 * cert is actually trusted for any purpose. The cert may be
939 * explicitly UNtrusted. We won't know until we examine the
940 * trust bits.
941 */
942 if (certUsage == certUsageStatusResponder) {
943 /* Check the special case of certUsageStatusResponder */
944 issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
945 if (issuerCert) {
946 if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) !=
947 SECSuccess) {
948 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
949 CERT_DestroyCertificate(issuerCert);
950 goto loser;
951 }
952 CERT_DestroyCertificate(issuerCert);
953 }
954 /* XXX We have NOT determined that this cert is trusted.
955 * For years, NSS has treated this as trusted,
956 * but it seems incorrect.
957 */
958 rv = rvFinal;
959 goto done;
960 }
961
962 /*
963 * check the trust params of the issuer
964 */
965 flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
966 if ((flags & requiredFlags) == requiredFlags) {
967 /* we found a trusted one, so return */
968 rv = rvFinal;
969 goto done;
970 }
971 if (flags & CERTDB_VALID_CA) {
972 validCAOverride = PR_TRUE;
973 }
974 /* is it explicitly distrusted? */
975 if ((flags & CERTDB_TERMINAL_RECORD) &&
976 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
977 /* untrusted -- the cert is explicitly untrusted, not
978 * just that it doesn't chain to a trusted cert */
979 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
980 LOG_ERROR_OR_EXIT(log, cert, 0, flags);
981 }
982 }
983 if (!validCAOverride) {
984 /*
985 * Make sure that if this is an intermediate CA in the chain that
986 * it was given permission by its signer to be a CA.
987 */
988 /*
989 * if basicConstraints says it is a ca, then we check the
990 * nsCertType. If the nsCertType has any CA bits set, then
991 * it must have the right one.
992 */
993 if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
994 isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
995 }
996
997 if (!isca) {
998 PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
999 LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1000 }
1001
1002 /* make sure key usage allows cert signing */
1003 if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
1004 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1005 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage);
1006 }
1007 }
1008 /* make sure that the issuer is not self signed. If it is, then
1009 * stop here to prevent looping.
1010 */
1011 if (cert->isRoot) {
1012 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
1013 LOG_ERROR(log, cert, 0, 0);
1014 goto loser;
1015 }
1016
1017 return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
1018 wincx, log);
1019 loser:
1020 rv = SECFailure;
1021 done:
1022 return rv;
1023 }
1024
1025 #define NEXT_USAGE() \
1026 { \
1027 i *= 2; \
1028 certUsage++; \
1029 continue; \
1030 }
1031
1032 #define VALID_USAGE() \
1033 { \
1034 NEXT_USAGE(); \
1035 }
1036
1037 #define INVALID_USAGE() \
1038 { \
1039 if (returnedUsages) { \
1040 *returnedUsages &= (~i); \
1041 } \
1042 if (PR_TRUE == requiredUsage) { \
1043 valid = SECFailure; \
1044 } \
1045 NEXT_USAGE(); \
1046 }
1047
1048 /*
1049 * check the leaf cert against trust and usage.
1050 * returns success if the cert is not distrusted. If the cert is
1051 * trusted, then the trusted bool will be true.
1052 * returns failure if the cert is distrusted. If failure, flags
1053 * will return the flag bits that indicated distrust.
1054 */
1055 SECStatus
1056 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
1057 unsigned int *failedFlags, PRBool *trusted)
1058 {
1059 unsigned int flags;
1060 CERTCertTrust trust;
1061
1062 *failedFlags = 0;
1063 *trusted = PR_FALSE;
1064
1065 /* check trust flags to see if this cert is directly trusted */
1066 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
1067 switch (certUsage) {
1068 case certUsageSSLClient:
1069 case certUsageSSLServer:
1070 flags = trust.sslFlags;
1071
1072 /* is the cert directly trusted or not trusted ? */
1073 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1074 * authoritative */
1075 if (flags & CERTDB_TRUSTED) { /* trust this cert */
1076 *trusted = PR_TRUE;
1077 return SECSuccess;
1078 } else { /* don't trust this cert */
1079 *failedFlags = flags;
1080 return SECFailure;
1081 }
1082 }
1083 break;
1084 case certUsageSSLServerWithStepUp:
1085 /* XXX - step up certs can't be directly trusted, only distrust */
1086 flags = trust.sslFlags;
1087 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1088 * authoritative */
1089 if ((flags & CERTDB_TRUSTED) == 0) {
1090 /* don't trust this cert */
1091 *failedFlags = flags;
1092 return SECFailure;
1093 }
1094 }
1095 break;
1096 case certUsageSSLCA:
1097 flags = trust.sslFlags;
1098 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1099 * authoritative */
1100 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1101 /* don't trust this cert */
1102 *failedFlags = flags;
1103 return SECFailure;
1104 }
1105 }
1106 break;
1107 case certUsageEmailSigner:
1108 case certUsageEmailRecipient:
1109 flags = trust.emailFlags;
1110 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1111 * authoritative */
1112 if (flags & CERTDB_TRUSTED) { /* trust this cert */
1113 *trusted = PR_TRUE;
1114 return SECSuccess;
1115 } else { /* don't trust this cert */
1116 *failedFlags = flags;
1117 return SECFailure;
1118 }
1119 }
1120
1121 break;
1122 case certUsageObjectSigner:
1123 flags = trust.objectSigningFlags;
1124
1125 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1126 * authoritative */
1127 if (flags & CERTDB_TRUSTED) { /* trust this cert */
1128 *trusted = PR_TRUE;
1129 return SECSuccess;
1130 } else { /* don't trust this cert */
1131 *failedFlags = flags;
1132 return SECFailure;
1133 }
1134 }
1135 break;
1136 case certUsageVerifyCA:
1137 case certUsageStatusResponder:
1138 flags = trust.sslFlags;
1139 /* is the cert directly trusted or not trusted ? */
1140 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1141 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1142 *trusted = PR_TRUE;
1143 return SECSuccess;
1144 }
1145 flags = trust.emailFlags;
1146 /* is the cert directly trusted or not trusted ? */
1147 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1148 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1149 *trusted = PR_TRUE;
1150 return SECSuccess;
1151 }
1152 flags = trust.objectSigningFlags;
1153 /* is the cert directly trusted or not trusted ? */
1154 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1155 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1156 *trusted = PR_TRUE;
1157 return SECSuccess;
1158 }
1159 /* fall through to test distrust */
1160 case certUsageAnyCA:
1161 case certUsageUserCertImport:
1162 /* do we distrust these certs explicitly */
1163 flags = trust.sslFlags;
1164 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1165 * authoritative */
1166 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1167 *failedFlags = flags;
1168 return SECFailure;
1169 }
1170 }
1171 flags = trust.emailFlags;
1172 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1173 * authoritative */
1174 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1175 *failedFlags = flags;
1176 return SECFailure;
1177 }
1178 }
1179 /* fall through */
1180 case certUsageProtectedObjectSigner:
1181 flags = trust.objectSigningFlags;
1182 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1183 * authoritative */
1184 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1185 *failedFlags = flags;
1186 return SECFailure;
1187 }
1188 }
1189 break;
1190 }
1191 }
1192 return SECSuccess;
1193 }
1194
1195 /*
1196 * verify a certificate by checking if it's valid and that we
1197 * trust the issuer.
1198 *
1199 * certificateUsage contains a bitfield of all cert usages that are
1200 * required for verification to succeed
1201 *
1202 * a bitfield of cert usages is returned in *returnedUsages
1203 * if requiredUsages is non-zero, the returned bitmap is only
1204 * for those required usages, otherwise it is for all usages
1205 *
1206 */
1207 SECStatus
1208 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
1209 PRBool checkSig, SECCertificateUsage requiredUsages, PRTi me t,
1210 void *wincx, CERTVerifyLog *log, SECCertificateUsage *ret urnedUsages)
1211 {
1212 SECStatus rv;
1213 SECStatus valid;
1214 unsigned int requiredKeyUsage;
1215 unsigned int requiredCertType;
1216 unsigned int flags;
1217 unsigned int certType;
1218 PRBool allowOverride;
1219 SECCertTimeValidity validity;
1220 CERTStatusConfig *statusConfig;
1221 PRInt32 i;
1222 SECCertUsage certUsage = 0;
1223 PRBool checkedOCSP = PR_FALSE;
1224 PRBool checkAllUsages = PR_FALSE;
1225 PRBool revoked = PR_FALSE;
1226 PRBool sigerror = PR_FALSE;
1227 PRBool trusted = PR_FALSE;
1228
1229 if (!requiredUsages) {
1230 /* there are no required usages, so the user probably wants to
1231 get status for all usages */
1232 checkAllUsages = PR_TRUE;
1233 }
1234
1235 if (returnedUsages) {
1236 *returnedUsages = 0;
1237 } else {
1238 /* we don't have a place to return status for all usages,
1239 so we can skip checks for usages that aren't required */
1240 checkAllUsages = PR_FALSE;
1241 }
1242 valid = SECSuccess; /* start off assuming cert is valid */
1243
1244 /* make sure that the cert is valid at time t */
1245 allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
1246 (requiredUsages & certificateUsageSSLServerWithStep Up));
1247 validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1248 if (validity != secCertTimeValid) {
1249 valid = SECFailure;
1250 LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1251 }
1252
1253 /* check key usage and netscape cert type */
1254 cert_GetCertType(cert);
1255 certType = cert->nsCertType;
1256
1257 for (i = 1; i <= certificateUsageHighest &&
1258 (SECSuccess == valid || returnedUsages || log);) {
1259 PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
1260 if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
1261 NEXT_USAGE();
1262 }
1263 if (returnedUsages) {
1264 *returnedUsages |= i; /* start off assuming this usage is valid */
1265 }
1266 switch (certUsage) {
1267 case certUsageSSLClient:
1268 case certUsageSSLServer:
1269 case certUsageSSLServerWithStepUp:
1270 case certUsageSSLCA:
1271 case certUsageEmailSigner:
1272 case certUsageEmailRecipient:
1273 case certUsageObjectSigner:
1274 case certUsageStatusResponder:
1275 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1276 &requiredKeyUsage,
1277 &requiredCertType);
1278 if (rv != SECSuccess) {
1279 PORT_Assert(0);
1280 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
1281 requiredKeyUsage = 0;
1282 requiredCertType = 0;
1283 INVALID_USAGE();
1284 }
1285 break;
1286
1287 case certUsageAnyCA:
1288 case certUsageProtectedObjectSigner:
1289 case certUsageUserCertImport:
1290 case certUsageVerifyCA:
1291 /* these usages cannot be verified */
1292 NEXT_USAGE();
1293
1294 default:
1295 PORT_Assert(0);
1296 requiredKeyUsage = 0;
1297 requiredCertType = 0;
1298 INVALID_USAGE();
1299 }
1300 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1301 if (PR_TRUE == requiredUsage) {
1302 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1303 }
1304 LOG_ERROR(log, cert, 0, requiredKeyUsage);
1305 INVALID_USAGE();
1306 }
1307 if (!(certType & requiredCertType)) {
1308 if (PR_TRUE == requiredUsage) {
1309 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1310 }
1311 LOG_ERROR(log, cert, 0, requiredCertType);
1312 INVALID_USAGE();
1313 }
1314
1315 rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
1316 if (rv == SECFailure) {
1317 if (PR_TRUE == requiredUsage) {
1318 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1319 }
1320 LOG_ERROR(log, cert, 0, flags);
1321 INVALID_USAGE();
1322 } else if (trusted) {
1323 VALID_USAGE();
1324 }
1325
1326 if (PR_TRUE == revoked || PR_TRUE == sigerror) {
1327 INVALID_USAGE();
1328 }
1329
1330 rv = cert_VerifyCertChain(handle, cert,
1331 checkSig, &sigerror,
1332 certUsage, t, wincx, log,
1333 &revoked);
1334
1335 if (rv != SECSuccess) {
1336 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
1337 INVALID_USAGE();
1338 }
1339
1340 /*
1341 * Check OCSP revocation status, but only if the cert we are checking
1342 * is not a status responder itself. We only do this in the case
1343 * where we checked the cert chain (above); explicit trust "wins"
1344 * (avoids status checking, just as it avoids CRL checking) by
1345 * bypassing this code.
1346 */
1347
1348 if (PR_FALSE == checkedOCSP) {
1349 checkedOCSP = PR_TRUE; /* only check OCSP once */
1350 statusConfig = CERT_GetStatusConfig(handle);
1351 if (requiredUsages != certificateUsageStatusResponder &&
1352 statusConfig != NULL) {
1353 if (statusConfig->statusChecker != NULL) {
1354 rv = (*statusConfig->statusChecker)(handle, cert,
1355 t, wincx);
1356 if (rv != SECSuccess) {
1357 LOG_ERROR(log, cert, 0, 0);
1358 revoked = PR_TRUE;
1359 INVALID_USAGE();
1360 }
1361 }
1362 }
1363 }
1364
1365 NEXT_USAGE();
1366 }
1367
1368 loser:
1369 return (valid);
1370 }
1371
1372 SECStatus
1373 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
1374 PRBool checkSig, SECCertUsage certUsage, PRTime t,
1375 void *wincx, CERTVerifyLog *log)
1376 {
1377 return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
1378 CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
1379 }
1380
1381 SECStatus
1382 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
1383 PRBool checkSig, SECCertUsage certUsage, PRTime t,
1384 PRUint32 flags, void *wincx, CERTVerifyLog *log)
1385 {
1386 SECStatus rv;
1387 unsigned int requiredKeyUsage;
1388 unsigned int requiredCertType;
1389 unsigned int failedFlags;
1390 unsigned int certType;
1391 PRBool trusted;
1392 PRBool allowOverride;
1393 SECCertTimeValidity validity;
1394 CERTStatusConfig *statusConfig;
1395
1396 #ifdef notdef
1397 /* check if this cert is in the Evil list */
1398 rv = CERT_CheckForEvilCert(cert);
1399 if (rv != SECSuccess) {
1400 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
1401 LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1402 }
1403 #endif
1404
1405 /* make sure that the cert is valid at time t */
1406 allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
1407 (certUsage == certUsageSSLServerWithStepUp));
1408 validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1409 if (validity != secCertTimeValid) {
1410 LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1411 }
1412
1413 /* check key usage and netscape cert type */
1414 cert_GetCertType(cert);
1415 certType = cert->nsCertType;
1416 switch (certUsage) {
1417 case certUsageSSLClient:
1418 case certUsageSSLServer:
1419 case certUsageSSLServerWithStepUp:
1420 case certUsageSSLCA:
1421 case certUsageEmailSigner:
1422 case certUsageEmailRecipient:
1423 case certUsageObjectSigner:
1424 case certUsageStatusResponder:
1425 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1426 &requiredKeyUsage,
1427 &requiredCertType);
1428 if (rv != SECSuccess) {
1429 PORT_Assert(0);
1430 EXIT_IF_NOT_LOGGING(log);
1431 requiredKeyUsage = 0;
1432 requiredCertType = 0;
1433 }
1434 break;
1435 case certUsageVerifyCA:
1436 case certUsageAnyCA:
1437 requiredKeyUsage = KU_KEY_CERT_SIGN;
1438 requiredCertType = NS_CERT_TYPE_CA;
1439 if (!(certType & NS_CERT_TYPE_CA)) {
1440 certType |= NS_CERT_TYPE_CA;
1441 }
1442 break;
1443 default:
1444 PORT_Assert(0);
1445 EXIT_IF_NOT_LOGGING(log);
1446 requiredKeyUsage = 0;
1447 requiredCertType = 0;
1448 }
1449 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1450 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1451 LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage);
1452 }
1453 if (!(certType & requiredCertType)) {
1454 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1455 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType);
1456 }
1457
1458 rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
1459 if (rv == SECFailure) {
1460 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1461 LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
1462 } else if (trusted) {
1463 goto done;
1464 }
1465
1466 rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
1467 t, wincx, log);
1468 if (rv != SECSuccess) {
1469 EXIT_IF_NOT_LOGGING(log);
1470 }
1471
1472 /*
1473 * Check revocation status, but only if the cert we are checking is not a
1474 * status responder itself and the caller did not ask us to skip the check.
1475 * We only do this in the case where we checked the cert chain (above);
1476 * explicit trust "wins" (avoids status checking, just as it avoids CRL
1477 * checking, which is all done inside VerifyCertChain) by bypassing this
1478 * code.
1479 */
1480 if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
1481 certUsage != certUsageStatusResponder) {
1482 statusConfig = CERT_GetStatusConfig(handle);
1483 if (statusConfig && statusConfig->statusChecker) {
1484 rv = (*statusConfig->statusChecker)(handle, cert,
1485 t, wincx);
1486 if (rv != SECSuccess) {
1487 LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1488 }
1489 }
1490 }
1491
1492 done:
1493 if (log && log->head) {
1494 return SECFailure;
1495 }
1496 return (SECSuccess);
1497
1498 loser:
1499 rv = SECFailure;
1500
1501 return (rv);
1502 }
1503
1504 /*
1505 * verify a certificate by checking if its valid and that we
1506 * trust the issuer. Verify time against now.
1507 */
1508 SECStatus
1509 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1510 PRBool checkSig, SECCertificateUsage requiredUsages,
1511 void *wincx, SECCertificateUsage *returnedUsages)
1512 {
1513 return (CERT_VerifyCertificate(handle, cert, checkSig,
1514 requiredUsages, PR_Now(), wincx, NULL, return edUsages));
1515 }
1516
1517 /* obsolete, do not use for new code */
1518 SECStatus
1519 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1520 PRBool checkSig, SECCertUsage certUsage, void *wincx)
1521 {
1522 return (CERT_VerifyCert(handle, cert, checkSig,
1523 certUsage, PR_Now(), wincx, NULL));
1524 }
1525
1526 /* [ FROM pcertdb.c ] */
1527 /*
1528 * Supported usage values and types:
1529 * certUsageSSLClient
1530 * certUsageSSLServer
1531 * certUsageSSLServerWithStepUp
1532 * certUsageEmailSigner
1533 * certUsageEmailRecipient
1534 * certUsageObjectSigner
1535 */
1536
1537 CERTCertificate *
1538 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
1539 CERTCertOwner owner, SECCertUsage usage,
1540 PRBool preferTrusted, PRTime validTime, PRBool validOnly)
1541 {
1542 CERTCertList *certList = NULL;
1543 CERTCertificate *cert = NULL;
1544 CERTCertTrust certTrust;
1545 unsigned int requiredTrustFlags;
1546 SECTrustType requiredTrustType;
1547 unsigned int flags;
1548
1549 PRBool lookingForCA = PR_FALSE;
1550 SECStatus rv;
1551 CERTCertListNode *node;
1552 CERTCertificate *saveUntrustedCA = NULL;
1553
1554 /* if preferTrusted is set, must be a CA cert */
1555 PORT_Assert(!(preferTrusted && (owner != certOwnerCA)));
1556
1557 if (owner == certOwnerCA) {
1558 lookingForCA = PR_TRUE;
1559 if (preferTrusted) {
1560 rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
1561 &requiredTrustType);
1562 if (rv != SECSuccess) {
1563 goto loser;
1564 }
1565 requiredTrustFlags |= CERTDB_VALID_CA;
1566 }
1567 }
1568
1569 certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
1570 validOnly);
1571 if (certList != NULL) {
1572 rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
1573 if (rv != SECSuccess) {
1574 goto loser;
1575 }
1576
1577 node = CERT_LIST_HEAD(certList);
1578
1579 while (!CERT_LIST_END(node, certList)) {
1580 cert = node->cert;
1581
1582 /* looking for a trusted CA cert */
1583 if ((owner == certOwnerCA) && preferTrusted &&
1584 (requiredTrustType != trustTypeNone)) {
1585
1586 if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) {
1587 flags = 0;
1588 } else {
1589 flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
1590 }
1591
1592 if ((flags & requiredTrustFlags) != requiredTrustFlags) {
1593 /* cert is not trusted */
1594 /* if this is the first cert to get this far, then save
1595 * it, so we can use it if we can't find a trusted one
1596 */
1597 if (saveUntrustedCA == NULL) {
1598 saveUntrustedCA = cert;
1599 }
1600 goto endloop;
1601 }
1602 }
1603 /* if we got this far, then this cert meets all criteria */
1604 break;
1605
1606 endloop:
1607 node = CERT_LIST_NEXT(node);
1608 cert = NULL;
1609 }
1610
1611 /* use the saved one if we have it */
1612 if (cert == NULL) {
1613 cert = saveUntrustedCA;
1614 }
1615
1616 /* if we found one then bump the ref count before freeing the list */
1617 if (cert != NULL) {
1618 /* bump the ref count */
1619 cert = CERT_DupCertificate(cert);
1620 }
1621
1622 CERT_DestroyCertList(certList);
1623 }
1624
1625 return (cert);
1626
1627 loser:
1628 if (certList != NULL) {
1629 CERT_DestroyCertList(certList);
1630 }
1631
1632 return (NULL);
1633 }
1634
1635 /* [ From certdb.c ] */
1636 /*
1637 * Filter a list of certificates, removing those certs that do not have
1638 * one of the named CA certs somewhere in their cert chain.
1639 *
1640 * "certList" - the list of certificates to filter
1641 * "nCANames" - number of CA names
1642 * "caNames" - array of CA names in string(rfc 1485) form
1643 * "usage" - what use the certs are for, this is used when
1644 * selecting CA certs
1645 */
1646 SECStatus
1647 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
1648 char **caNames, SECCertUsage usage)
1649 {
1650 CERTCertificate *issuerCert = NULL;
1651 CERTCertificate *subjectCert;
1652 CERTCertListNode *node, *freenode;
1653 CERTCertificate *cert;
1654 int n;
1655 char **names;
1656 PRBool found;
1657 PRTime time;
1658
1659 if (nCANames <= 0) {
1660 return (SECSuccess);
1661 }
1662
1663 time = PR_Now();
1664
1665 node = CERT_LIST_HEAD(certList);
1666
1667 while (!CERT_LIST_END(node, certList)) {
1668 cert = node->cert;
1669
1670 subjectCert = CERT_DupCertificate(cert);
1671
1672 /* traverse the CA certs for this cert */
1673 found = PR_FALSE;
1674 while (subjectCert != NULL) {
1675 n = nCANames;
1676 names = caNames;
1677
1678 if (subjectCert->issuerName != NULL) {
1679 while (n > 0) {
1680 if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) {
1681 found = PR_TRUE;
1682 break;
1683 }
1684
1685 n--;
1686 names++;
1687 }
1688 }
1689
1690 if (found) {
1691 break;
1692 }
1693
1694 issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
1695 if (issuerCert == subjectCert) {
1696 CERT_DestroyCertificate(issuerCert);
1697 issuerCert = NULL;
1698 break;
1699 }
1700 CERT_DestroyCertificate(subjectCert);
1701 subjectCert = issuerCert;
1702 }
1703 CERT_DestroyCertificate(subjectCert);
1704 if (!found) {
1705 /* CA was not found, so remove this cert from the list */
1706 freenode = node;
1707 node = CERT_LIST_NEXT(node);
1708 CERT_RemoveCertListNode(freenode);
1709 } else {
1710 /* CA was found, so leave it in the list */
1711 node = CERT_LIST_NEXT(node);
1712 }
1713 }
1714
1715 return (SECSuccess);
1716 }
1717
1718 /*
1719 * Given a certificate, return a string containing the nickname, and possibly
1720 * one of the validity strings, based on the current validity state of the
1721 * certificate.
1722 *
1723 * "arena" - arena to allocate returned string from. If NULL, then heap
1724 * is used.
1725 * "cert" - the cert to get nickname from
1726 * "expiredString" - the string to append to the nickname if the cert is
1727 * expired.
1728 * "notYetGoodString" - the string to append to the nickname if the cert is
1729 * not yet good.
1730 */
1731 char *
1732 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
1733 char *expiredString, char *notYetGoodString)
1734 {
1735 SECCertTimeValidity validity;
1736 char *nickname = NULL, *tmpstr = NULL;
1737
1738 validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
1739
1740 /* if the cert is good, then just use the nickname directly */
1741 if (validity == secCertTimeValid) {
1742 if (arena == NULL) {
1743 nickname = PORT_Strdup(cert->nickname);
1744 } else {
1745 nickname = PORT_ArenaStrdup(arena, cert->nickname);
1746 }
1747
1748 if (nickname == NULL) {
1749 goto loser;
1750 }
1751 } else {
1752
1753 /* if the cert is not valid, then tack one of the strings on the
1754 * end
1755 */
1756 if (validity == secCertTimeExpired) {
1757 tmpstr = PR_smprintf("%s%s", cert->nickname,
1758 expiredString);
1759 } else if (validity == secCertTimeNotValidYet) {
1760 /* not yet valid */
1761 tmpstr = PR_smprintf("%s%s", cert->nickname,
1762 notYetGoodString);
1763 } else {
1764 /* undetermined */
1765 tmpstr = PR_smprintf("%s",
1766 "(NULL) (Validity Unknown)");
1767 }
1768
1769 if (tmpstr == NULL) {
1770 goto loser;
1771 }
1772
1773 if (arena) {
1774 /* copy the string into the arena and free the malloc'd one */
1775 nickname = PORT_ArenaStrdup(arena, tmpstr);
1776 PORT_Free(tmpstr);
1777 } else {
1778 nickname = tmpstr;
1779 }
1780 if (nickname == NULL) {
1781 goto loser;
1782 }
1783 }
1784 return (nickname);
1785
1786 loser:
1787 return (NULL);
1788 }
1789
1790 /*
1791 * Collect the nicknames from all certs in a CertList. If the cert is not
1792 * valid, append a string to that nickname.
1793 *
1794 * "certList" - the list of certificates
1795 * "expiredString" - the string to append to the nickname of any expired cert
1796 * "notYetGoodString" - the string to append to the nickname of any cert
1797 * that is not yet valid
1798 */
1799 CERTCertNicknames *
1800 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
1801 char *notYetGoodString)
1802 {
1803 CERTCertNicknames *names;
1804 PLArenaPool *arena;
1805 CERTCertListNode *node;
1806 char **nn;
1807
1808 /* allocate an arena */
1809 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1810 if (arena == NULL) {
1811 return (NULL);
1812 }
1813
1814 /* allocate the structure */
1815 names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
1816 if (names == NULL) {
1817 goto loser;
1818 }
1819
1820 /* init the structure */
1821 names->arena = arena;
1822 names->head = NULL;
1823 names->numnicknames = 0;
1824 names->nicknames = NULL;
1825 names->totallen = 0;
1826
1827 /* count the certs in the list */
1828 node = CERT_LIST_HEAD(certList);
1829 while (!CERT_LIST_END(node, certList)) {
1830 names->numnicknames++;
1831 node = CERT_LIST_NEXT(node);
1832 }
1833
1834 /* allocate nicknames array */
1835 names->nicknames = PORT_ArenaAlloc(arena,
1836 sizeof(char *) * names->numnicknames);
1837 if (names->nicknames == NULL) {
1838 goto loser;
1839 }
1840
1841 /* just in case printf can't deal with null strings */
1842 if (expiredString == NULL) {
1843 expiredString = "";
1844 }
1845
1846 if (notYetGoodString == NULL) {
1847 notYetGoodString = "";
1848 }
1849
1850 /* traverse the list of certs and collect the nicknames */
1851 nn = names->nicknames;
1852 node = CERT_LIST_HEAD(certList);
1853 while (!CERT_LIST_END(node, certList)) {
1854 *nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
1855 expiredString,
1856 notYetGoodString);
1857 if (*nn == NULL) {
1858 goto loser;
1859 }
1860
1861 names->totallen += PORT_Strlen(*nn);
1862
1863 nn++;
1864 node = CERT_LIST_NEXT(node);
1865 }
1866
1867 return (names);
1868
1869 loser:
1870 PORT_FreeArena(arena, PR_FALSE);
1871 return (NULL);
1872 }
1873
1874 /*
1875 * Extract the nickname from a nickmake string that may have either
1876 * expiredString or notYetGoodString appended.
1877 *
1878 * Args:
1879 * "namestring" - the string containing the nickname, and possibly
1880 * one of the validity label strings
1881 * "expiredString" - the expired validity label string
1882 * "notYetGoodString" - the not yet good validity label string
1883 *
1884 * Returns the raw nickname
1885 */
1886 char *
1887 CERT_ExtractNicknameString(char *namestring, char *expiredString,
1888 char *notYetGoodString)
1889 {
1890 int explen, nyglen, namelen;
1891 int retlen;
1892 char *retstr;
1893
1894 namelen = PORT_Strlen(namestring);
1895 explen = PORT_Strlen(expiredString);
1896 nyglen = PORT_Strlen(notYetGoodString);
1897
1898 if (namelen > explen) {
1899 if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) {
1900 retlen = namelen - explen;
1901 retstr = (char *)PORT_Alloc(retlen + 1);
1902 if (retstr == NULL) {
1903 goto loser;
1904 }
1905
1906 PORT_Memcpy(retstr, namestring, retlen);
1907 retstr[retlen] = '\0';
1908 goto done;
1909 }
1910 }
1911
1912 if (namelen > nyglen) {
1913 if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) {
1914 retlen = namelen - nyglen;
1915 retstr = (char *)PORT_Alloc(retlen + 1);
1916 if (retstr == NULL) {
1917 goto loser;
1918 }
1919
1920 PORT_Memcpy(retstr, namestring, retlen);
1921 retstr[retlen] = '\0';
1922 goto done;
1923 }
1924 }
1925
1926 /* if name string is shorter than either invalid string, then it must
1927 * be a raw nickname
1928 */
1929 retstr = PORT_Strdup(namestring);
1930
1931 done:
1932 return (retstr);
1933
1934 loser:
1935 return (NULL);
1936 }
1937
1938 CERTCertList *
1939 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage )
1940 {
1941 CERTCertList *chain = NULL;
1942 int count = 0;
1943
1944 if (NULL == cert) {
1945 return NULL;
1946 }
1947
1948 cert = CERT_DupCertificate(cert);
1949 if (NULL == cert) {
1950 PORT_SetError(SEC_ERROR_NO_MEMORY);
1951 return NULL;
1952 }
1953
1954 chain = CERT_NewCertList();
1955 if (NULL == chain) {
1956 PORT_SetError(SEC_ERROR_NO_MEMORY);
1957 return NULL;
1958 }
1959
1960 while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
1961 if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
1962 /* return partial chain */
1963 PORT_SetError(SEC_ERROR_NO_MEMORY);
1964 return chain;
1965 }
1966
1967 if (cert->isRoot) {
1968 /* return complete chain */
1969 return chain;
1970 }
1971
1972 cert = CERT_FindCertIssuer(cert, time, usage);
1973 }
1974
1975 /* return partial chain */
1976 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
1977 return chain;
1978 }
OLDNEW
« no previous file with comments | « nss/lib/certhigh/certreq.c ('k') | nss/lib/certhigh/certvfypkix.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698