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, ¬Before, ¬After);
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