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