1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
22
* Aaron Spangler <aaron@spangler.ods.org>
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
* Certificate handling code
41
* $Id: certdb.c,v 1.76.2.1 2006/02/16 00:14:18 julien.pierre.bugs%sun.com Exp $
66
#include "xconst.h" /* for CERT_DecodeAltNameExtension */
70
#endif /* NSS_3_4_CODE */
75
* Certificate database handling code
79
const SEC_ASN1Template CERT_CertExtensionTemplate[] = {
81
0, NULL, sizeof(CERTCertExtension) },
83
offsetof(CERTCertExtension,id) },
84
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
85
offsetof(CERTCertExtension,critical) },
86
{ SEC_ASN1_OCTET_STRING,
87
offsetof(CERTCertExtension,value) },
91
const SEC_ASN1Template CERT_SequenceOfCertExtensionTemplate[] = {
92
{ SEC_ASN1_SEQUENCE_OF, 0, CERT_CertExtensionTemplate }
95
const SEC_ASN1Template CERT_CertificateTemplate[] = {
97
0, NULL, sizeof(CERTCertificate) },
98
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
99
SEC_ASN1_CONTEXT_SPECIFIC | 0, /* XXX DER_DEFAULT */
100
offsetof(CERTCertificate,version),
101
SEC_IntegerTemplate },
103
offsetof(CERTCertificate,serialNumber) },
105
offsetof(CERTCertificate,signature),
106
SECOID_AlgorithmIDTemplate },
108
offsetof(CERTCertificate,derIssuer) },
110
offsetof(CERTCertificate,issuer),
113
offsetof(CERTCertificate,validity),
114
CERT_ValidityTemplate },
116
offsetof(CERTCertificate,derSubject) },
118
offsetof(CERTCertificate,subject),
121
offsetof(CERTCertificate,derPublicKey) },
123
offsetof(CERTCertificate,subjectPublicKeyInfo),
124
CERT_SubjectPublicKeyInfoTemplate },
125
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1,
126
offsetof(CERTCertificate,issuerID),
127
SEC_BitStringTemplate },
128
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 2,
129
offsetof(CERTCertificate,subjectID),
130
SEC_BitStringTemplate },
131
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
132
SEC_ASN1_CONTEXT_SPECIFIC | 3,
133
offsetof(CERTCertificate,extensions),
134
CERT_SequenceOfCertExtensionTemplate },
138
const SEC_ASN1Template SEC_SignedCertificateTemplate[] =
141
0, NULL, sizeof(CERTCertificate) },
143
offsetof(CERTCertificate,signatureWrap.data) },
145
0, CERT_CertificateTemplate },
147
offsetof(CERTCertificate,signatureWrap.signatureAlgorithm),
148
SECOID_AlgorithmIDTemplate },
149
{ SEC_ASN1_BIT_STRING,
150
offsetof(CERTCertificate,signatureWrap.signature) },
155
* Find the subjectName in a DER encoded certificate
157
const SEC_ASN1Template SEC_CertSubjectTemplate[] = {
159
0, NULL, sizeof(SECItem) },
160
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
161
SEC_ASN1_CONTEXT_SPECIFIC | 0,
162
0, SEC_SkipTemplate }, /* version */
163
{ SEC_ASN1_SKIP }, /* serial number */
164
{ SEC_ASN1_SKIP }, /* signature algorithm */
165
{ SEC_ASN1_SKIP }, /* issuer */
166
{ SEC_ASN1_SKIP }, /* validity */
167
{ SEC_ASN1_ANY, 0, NULL }, /* subject */
168
{ SEC_ASN1_SKIP_REST },
173
* Find the issuerName in a DER encoded certificate
175
const SEC_ASN1Template SEC_CertIssuerTemplate[] = {
177
0, NULL, sizeof(SECItem) },
178
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
179
SEC_ASN1_CONTEXT_SPECIFIC | 0,
180
0, SEC_SkipTemplate }, /* version */
181
{ SEC_ASN1_SKIP }, /* serial number */
182
{ SEC_ASN1_SKIP }, /* signature algorithm */
183
{ SEC_ASN1_ANY, 0, NULL }, /* issuer */
184
{ SEC_ASN1_SKIP_REST },
188
* Find the subjectName in a DER encoded certificate
190
const SEC_ASN1Template SEC_CertSerialNumberTemplate[] = {
192
0, NULL, sizeof(SECItem) },
193
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
194
SEC_ASN1_CONTEXT_SPECIFIC | 0,
195
0, SEC_SkipTemplate }, /* version */
196
{ SEC_ASN1_ANY, 0, NULL }, /* serial number */
197
{ SEC_ASN1_SKIP_REST },
202
* Find the issuer and serialNumber in a DER encoded certificate.
203
* This data is used as the database lookup key since its the unique
204
* identifier of a certificate.
206
const SEC_ASN1Template CERT_CertKeyTemplate[] = {
208
0, NULL, sizeof(CERTCertKey) },
209
{ SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
210
SEC_ASN1_CONTEXT_SPECIFIC | 0,
211
0, SEC_SkipTemplate }, /* version */
213
offsetof(CERTCertKey,serialNumber) },
214
{ SEC_ASN1_SKIP }, /* signature algorithm */
216
offsetof(CERTCertKey,derIssuer) },
217
{ SEC_ASN1_SKIP_REST },
221
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateTemplate)
222
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SignedCertificateTemplate)
223
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SequenceOfCertExtensionTemplate)
226
CERT_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
229
key->len = sn->len + issuer->len;
231
if ((sn->data == NULL) || (issuer->data == NULL)) {
235
key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
240
/* copy the serialNumber */
241
PORT_Memcpy(key->data, sn->data, sn->len);
243
/* copy the issuer */
244
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
254
* Extract the subject name from a DER certificate
257
CERT_NameFromDERCert(SECItem *derCert, SECItem *derName)
264
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
270
PORT_Memset(&sd, 0, sizeof(CERTSignedData));
271
rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
277
PORT_Memset(derName, 0, sizeof(SECItem));
278
rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSubjectTemplate, &sd.data);
284
tmpptr = derName->data;
285
derName->data = (unsigned char*)PORT_Alloc(derName->len);
286
if ( derName->data == NULL ) {
290
PORT_Memcpy(derName->data, tmpptr, derName->len);
292
PORT_FreeArena(arena, PR_FALSE);
296
PORT_FreeArena(arena, PR_FALSE);
301
CERT_IssuerNameFromDERCert(SECItem *derCert, SECItem *derName)
308
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
314
PORT_Memset(&sd, 0, sizeof(CERTSignedData));
315
rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
321
PORT_Memset(derName, 0, sizeof(SECItem));
322
rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertIssuerTemplate, &sd.data);
328
tmpptr = derName->data;
329
derName->data = (unsigned char*)PORT_Alloc(derName->len);
330
if ( derName->data == NULL ) {
334
PORT_Memcpy(derName->data, tmpptr, derName->len);
336
PORT_FreeArena(arena, PR_FALSE);
340
PORT_FreeArena(arena, PR_FALSE);
345
CERT_SerialNumberFromDERCert(SECItem *derCert, SECItem *derName)
352
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
358
PORT_Memset(&sd, 0, sizeof(CERTSignedData));
359
rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
365
PORT_Memset(derName, 0, sizeof(SECItem));
366
rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSerialNumberTemplate, &sd.data);
372
tmpptr = derName->data;
373
derName->data = (unsigned char*)PORT_Alloc(derName->len);
374
if ( derName->data == NULL ) {
378
PORT_Memcpy(derName->data, tmpptr, derName->len);
380
PORT_FreeArena(arena, PR_FALSE);
384
PORT_FreeArena(arena, PR_FALSE);
389
* Generate a database key, based on serial number and issuer, from a
393
CERT_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
399
PORT_Memset(&sd, 0, sizeof(CERTSignedData));
400
rv = SEC_ASN1DecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
406
PORT_Memset(&certkey, 0, sizeof(CERTCertKey));
407
rv = SEC_ASN1DecodeItem(arena, &certkey, CERT_CertKeyTemplate, &sd.data);
413
return(CERT_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
414
&certkey.serialNumber, key));
420
* fill in keyUsage field of the cert based on the cert extension
421
* if the extension is not critical, then we allow all uses
424
GetKeyUsage(CERTCertificate *cert)
429
rv = CERT_FindKeyUsageExtension(cert, &tmpitem);
430
if ( rv == SECSuccess ) {
431
/* remember the actual value of the extension */
432
cert->rawKeyUsage = tmpitem.data[0];
433
cert->keyUsagePresent = PR_TRUE;
434
cert->keyUsage = tmpitem.data[0];
436
PORT_Free(tmpitem.data);
440
/* if the extension is not present, then we allow all uses */
441
cert->keyUsage = KU_ALL;
442
cert->rawKeyUsage = KU_ALL;
443
cert->keyUsagePresent = PR_FALSE;
446
if ( CERT_GovtApprovedBitSet(cert) ) {
447
cert->keyUsage |= KU_NS_GOVT_APPROVED;
448
cert->rawKeyUsage |= KU_NS_GOVT_APPROVED;
456
* determine if a fortezza V1 Cert is a CA or not.
459
fortezzaIsCA( CERTCertificate *cert) {
460
PRBool isCA = PR_FALSE;
461
CERTSubjectPublicKeyInfo *spki = &cert->subjectPublicKeyInfo;
464
tag = SECOID_GetAlgorithmTag(&spki->algorithm);
465
if ((tag == SEC_OID_MISSI_KEA_DSS_OLD) ||
466
(tag == SEC_OID_MISSI_KEA_DSS) ||
467
(tag == SEC_OID_MISSI_DSS_OLD) ||
468
(tag == SEC_OID_MISSI_DSS) ) {
470
unsigned char *rawptr;
474
rawkey = spki->subjectPublicKey;
475
DER_ConvertBitString(&rawkey);
476
rawptr = rawkey.data;
477
end = rawkey.data + rawkey.len;
480
rawptr += sizeof(((SECKEYPublicKey*)0)->u.fortezza.KMID)+2;
482
/* clearance (the string up to the first byte with the hi-bit on */
483
while ((rawptr < end) && (*rawptr++ & 0x80));
484
if (rawptr >= end) { return PR_FALSE; }
486
/* KEAPrivilege (the string up to the first byte with the hi-bit on */
487
while ((rawptr < end) && (*rawptr++ & 0x80));
488
if (rawptr >= end) { return PR_FALSE; }
491
len = (*rawptr << 8) | rawptr[1];
495
if (rawptr >= end) { return PR_FALSE; }
496
/* DSS Version is next */
499
/* DSSPrivilege (the string up to the first byte with the hi-bit on */
500
if (*rawptr & 0x30) isCA = PR_TRUE;
507
findOIDinOIDSeqByTagNum(CERTOidSequence *seq, SECOidTag tagnum)
511
SECStatus rv = SECFailure;
515
while (oids != NULL && *oids != NULL) {
517
if (SECOID_FindOIDTag(oid) == tagnum) {
528
* fill in nsCertType field of the cert based on the cert extension
531
cert_GetCertType(CERTCertificate *cert)
535
SECItem encodedExtKeyUsage;
536
CERTOidSequence *extKeyUsage = NULL;
537
PRBool basicConstraintPresent = PR_FALSE;
538
CERTBasicConstraints basicConstraint;
539
unsigned int nsCertType = 0;
541
if (cert->nsCertType) {
542
/* once set, no need to recalculate */
547
CERT_FindNSCertTypeExtension(cert, &tmpitem);
548
encodedExtKeyUsage.data = NULL;
549
rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE,
550
&encodedExtKeyUsage);
551
if (rv == SECSuccess) {
552
extKeyUsage = CERT_DecodeOidSequence(&encodedExtKeyUsage);
554
rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
555
if (rv == SECSuccess) {
556
basicConstraintPresent = PR_TRUE;
558
if (tmpitem.data != NULL || extKeyUsage != NULL) {
559
if (tmpitem.data == NULL) {
562
nsCertType = tmpitem.data[0];
565
/* free tmpitem data pointer to avoid memory leak */
566
PORT_Free(tmpitem.data);
570
* for this release, we will allow SSL certs with an email address
571
* to be used for email
573
if ( ( nsCertType & NS_CERT_TYPE_SSL_CLIENT ) &&
574
cert->emailAddr && cert->emailAddr[0]) {
575
nsCertType |= NS_CERT_TYPE_EMAIL;
578
* for this release, we will allow SSL intermediate CAs to be
579
* email intermediate CAs too.
581
if ( nsCertType & NS_CERT_TYPE_SSL_CA ) {
582
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
585
* allow a cert with the extended key usage of EMail Protect
586
* to be used for email or as an email CA, if basic constraints
587
* indicates that it is a CA.
589
if (findOIDinOIDSeqByTagNum(extKeyUsage,
590
SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) ==
592
if (basicConstraintPresent == PR_TRUE &&
593
(basicConstraint.isCA)) {
594
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
596
nsCertType |= NS_CERT_TYPE_EMAIL;
599
if (findOIDinOIDSeqByTagNum(extKeyUsage,
600
SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) ==
602
if (basicConstraintPresent == PR_TRUE &&
603
(basicConstraint.isCA)) {
604
nsCertType |= NS_CERT_TYPE_SSL_CA;
606
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
609
/* Treat certs with step-up OID as also having SSL server type. */
610
if (findOIDinOIDSeqByTagNum(extKeyUsage,
611
SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) ==
613
if (basicConstraintPresent == PR_TRUE &&
614
(basicConstraint.isCA)) {
615
nsCertType |= NS_CERT_TYPE_SSL_CA;
617
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
620
if (findOIDinOIDSeqByTagNum(extKeyUsage,
621
SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) ==
623
if (basicConstraintPresent == PR_TRUE &&
624
(basicConstraint.isCA)) {
625
nsCertType |= NS_CERT_TYPE_SSL_CA;
627
nsCertType |= NS_CERT_TYPE_SSL_CLIENT;
630
if (findOIDinOIDSeqByTagNum(extKeyUsage,
631
SEC_OID_EXT_KEY_USAGE_CODE_SIGN) ==
633
if (basicConstraintPresent == PR_TRUE &&
634
(basicConstraint.isCA)) {
635
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
637
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING;
640
if (findOIDinOIDSeqByTagNum(extKeyUsage,
641
SEC_OID_EXT_KEY_USAGE_TIME_STAMP) ==
643
nsCertType |= EXT_KEY_USAGE_TIME_STAMP;
645
if (findOIDinOIDSeqByTagNum(extKeyUsage,
646
SEC_OID_OCSP_RESPONDER) ==
648
nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
651
/* if no extension, then allow any ssl or email (no ca or object
654
nsCertType = NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER |
657
/* if the basic constraint extension says the cert is a CA, then
658
allow SSL CA and EMAIL CA and Status Responder */
659
if ((basicConstraintPresent == PR_TRUE)
660
&& (basicConstraint.isCA)) {
661
nsCertType |= NS_CERT_TYPE_SSL_CA;
662
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
663
nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
664
} else if (CERT_IsCACert(cert, NULL) == PR_TRUE) {
665
nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
668
/* if the cert is a fortezza CA cert, then allow SSL CA and EMAIL CA */
669
if (fortezzaIsCA(cert)) {
670
nsCertType |= NS_CERT_TYPE_SSL_CA;
671
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
675
if (encodedExtKeyUsage.data != NULL) {
676
PORT_Free(encodedExtKeyUsage.data);
678
if (extKeyUsage != NULL) {
679
CERT_DestroyOidSequence(extKeyUsage);
681
/* Assert that it is safe to cast &cert->nsCertType to "PRInt32 *" */
682
PORT_Assert(sizeof(cert->nsCertType) == sizeof(PRInt32));
683
PR_AtomicSet((PRInt32 *)&cert->nsCertType, nsCertType);
688
* cert_GetKeyID() - extract or generate the subjectKeyID from a certificate
691
cert_GetKeyID(CERTCertificate *cert)
695
SECKEYPublicKey *key;
697
cert->subjectKeyID.len = 0;
699
/* see of the cert has a key identifier extension */
700
rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
701
if ( rv == SECSuccess ) {
702
cert->subjectKeyID.data = (unsigned char*) PORT_ArenaAlloc(cert->arena, tmpitem.len);
703
if ( cert->subjectKeyID.data != NULL ) {
704
PORT_Memcpy(cert->subjectKeyID.data, tmpitem.data, tmpitem.len);
705
cert->subjectKeyID.len = tmpitem.len;
706
cert->keyIDGenerated = PR_FALSE;
709
PORT_Free(tmpitem.data);
712
/* if the cert doesn't have a key identifier extension and the cert is
713
* a V1 fortezza certificate, use the cert's 8 byte KMID as the
715
key = CERT_KMIDPublicKey(cert);
719
if (key->keyType == fortezzaKey) {
721
cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, 8);
722
if ( cert->subjectKeyID.data != NULL ) {
723
PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8);
724
cert->subjectKeyID.len = 8;
725
cert->keyIDGenerated = PR_FALSE;
729
SECKEY_DestroyPublicKey(key);
732
/* if the cert doesn't have a key identifier extension, then generate one*/
733
if ( cert->subjectKeyID.len == 0 ) {
735
* pkix says that if the subjectKeyID is not present, then we should
736
* use the SHA-1 hash of the DER-encoded publicKeyInfo from the cert
738
cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH);
739
if ( cert->subjectKeyID.data != NULL ) {
740
rv = PK11_HashBuf(SEC_OID_SHA1,cert->subjectKeyID.data,
741
cert->derPublicKey.data,
742
cert->derPublicKey.len);
743
if ( rv == SECSuccess ) {
744
cert->subjectKeyID.len = SHA1_LENGTH;
749
if ( cert->subjectKeyID.len == 0 ) {
757
cert_IsRootCert(CERTCertificate *cert)
762
/* cache the authKeyID extension, if present */
763
cert->authKeyID = CERT_FindAuthKeyIDExten(cert->arena, cert);
765
/* it MUST be self-issued to be a root */
766
if (cert->derIssuer.len == 0 ||
767
!SECITEM_ItemsAreEqual(&cert->derIssuer, &cert->derSubject))
772
/* check the authKeyID extension */
773
if (cert->authKeyID) {
774
/* authority key identifier is present */
775
if (cert->authKeyID->keyID.len > 0) {
776
/* the keyIdentifier field is set, look for subjectKeyID */
777
rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
778
if (rv == SECSuccess) {
780
/* also present, they MUST match for it to be a root */
781
match = SECITEM_ItemsAreEqual(&cert->authKeyID->keyID,
783
PORT_Free(tmpitem.data);
784
if (!match) return PR_FALSE; /* else fall through */
786
/* the subject key ID is required when AKI is present */
790
if (cert->authKeyID->authCertIssuer) {
792
caName = (SECItem *)CERT_GetGeneralNameByType(
793
cert->authKeyID->authCertIssuer,
794
certDirectoryName, PR_TRUE);
796
if (!SECITEM_ItemsAreEqual(&cert->derIssuer, caName)) {
798
} /* else fall through */
799
} /* else ??? could not get general name as directory name? */
801
if (cert->authKeyID->authCertSerialNumber.len > 0) {
802
if (!SECITEM_ItemsAreEqual(&cert->serialNumber,
803
&cert->authKeyID->authCertSerialNumber)) {
805
} /* else fall through */
807
/* all of the AKI fields that were present passed the test */
810
/* else the AKI was not present, so this is a root */
815
* take a DER certificate and decode it into a certificate structure
818
CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
821
CERTCertificate *cert;
828
/* make a new arena */
829
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
835
/* allocate the certificate structure */
836
cert = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
845
/* copy the DER data for the cert into this arena */
846
data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len);
850
cert->derCert.data = (unsigned char *)data;
851
cert->derCert.len = derSignedCert->len;
852
PORT_Memcpy(data, derSignedCert->data, derSignedCert->len);
854
/* point to passed in DER data */
855
cert->derCert = *derSignedCert;
858
/* decode the certificate info */
859
rv = SEC_QuickDERDecodeItem(arena, cert, SEC_SignedCertificateTemplate,
866
if (cert_HasUnknownCriticalExten (cert->extensions) == PR_TRUE) {
867
cert->options.bits.hasUnsupportedCriticalExt = PR_TRUE;
870
/* generate and save the database key for the cert */
871
rv = CERT_KeyFromIssuerAndSN(arena, &cert->derIssuer, &cert->serialNumber,
877
/* set the nickname */
878
if ( nickname == NULL ) {
879
cert->nickname = NULL;
881
/* copy and install the nickname */
882
len = PORT_Strlen(nickname) + 1;
883
cert->nickname = (char*)PORT_ArenaAlloc(arena, len);
884
if ( cert->nickname == NULL ) {
888
PORT_Memcpy(cert->nickname, nickname, len);
891
/* set the email address */
892
cert->emailAddr = cert_GetCertificateEmailAddresses(cert);
894
/* initialize the subjectKeyID */
895
rv = cert_GetKeyID(cert);
896
if ( rv != SECSuccess ) {
900
/* initialize keyUsage */
901
rv = GetKeyUsage(cert);
902
if ( rv != SECSuccess ) {
906
/* initialize the certType */
907
rv = cert_GetCertType(cert);
908
if ( rv != SECSuccess ) {
912
/* determine if this is a root cert */
913
cert->isRoot = cert_IsRootCert(cert);
915
tmpname = CERT_NameToAscii(&cert->subject);
916
if ( tmpname != NULL ) {
917
cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname);
921
tmpname = CERT_NameToAscii(&cert->issuer);
922
if ( tmpname != NULL ) {
923
cert->issuerName = PORT_ArenaStrdup(cert->arena, tmpname);
927
cert->referenceCount = 1;
929
cert->pkcs11ID = CK_INVALID_HANDLE;
930
cert->dbnickname = NULL;
937
PORT_FreeArena(arena, PR_FALSE);
944
__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
947
return CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname);
952
** Amount of time that a certifiate is allowed good before it is actually
953
** good. This is used for pending certificates, ones that are about to be
954
** valid. The slop is designed to allow for some variance in the clocks
955
** of the machine checking the certificate.
957
#define PENDING_SLOP (24L*60L*60L) /* seconds per day */
958
static PRInt32 pendingSlop = PENDING_SLOP; /* seconds */
961
CERT_GetSlopTime(void)
963
return pendingSlop; /* seconds */
967
CERT_SetSlopTime(PRInt32 slop) /* seconds */
976
CERT_GetCertTimes(CERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
980
if (!c || !notBefore || !notAfter) {
981
PORT_SetError(SEC_ERROR_INVALID_ARGS);
985
/* convert DER not-before time */
986
rv = DER_DecodeTimeChoice(notBefore, &c->validity.notBefore);
991
/* convert DER not-after time */
992
rv = DER_DecodeTimeChoice(notAfter, &c->validity.notAfter);
1001
* Check the validity times of a certificate
1004
CERT_CheckCertValidTimes(CERTCertificate *c, PRTime t, PRBool allowOverride)
1006
PRTime notBefore, notAfter, llPendingSlop, tmp1;
1010
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1011
return(secCertTimeUndetermined);
1013
/* if cert is already marked OK, then don't bother to check */
1014
if ( allowOverride && c->timeOK ) {
1015
return(secCertTimeValid);
1018
rv = CERT_GetCertTimes(c, ¬Before, ¬After);
1021
return(secCertTimeExpired); /*XXX is this the right thing to do here?*/
1024
LL_I2L(llPendingSlop, pendingSlop);
1025
/* convert to micro seconds */
1026
LL_UI2L(tmp1, PR_USEC_PER_SEC);
1027
LL_MUL(llPendingSlop, llPendingSlop, tmp1);
1028
LL_SUB(notBefore, notBefore, llPendingSlop);
1029
if ( LL_CMP( t, <, notBefore ) ) {
1030
PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE);
1031
return(secCertTimeNotValidYet);
1033
if ( LL_CMP( t, >, notAfter) ) {
1034
PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE);
1035
return(secCertTimeExpired);
1038
return(secCertTimeValid);
1042
SEC_GetCrlTimes(CERTCrl *date, PRTime *notBefore, PRTime *notAfter)
1046
/* convert DER not-before time */
1047
rv = DER_DecodeTimeChoice(notBefore, &date->lastUpdate);
1052
/* convert DER not-after time */
1053
if (date->nextUpdate.data) {
1054
rv = DER_DecodeTimeChoice(notAfter, &date->nextUpdate);
1060
LL_I2L(*notAfter, 0L);
1065
/* These routines should probably be combined with the cert
1066
* routines using an common extraction routine.
1069
SEC_CheckCrlTimes(CERTCrl *crl, PRTime t) {
1070
PRTime notBefore, notAfter, llPendingSlop, tmp1;
1073
rv = SEC_GetCrlTimes(crl, ¬Before, ¬After);
1076
return(secCertTimeExpired);
1079
LL_I2L(llPendingSlop, pendingSlop);
1080
/* convert to micro seconds */
1081
LL_I2L(tmp1, PR_USEC_PER_SEC);
1082
LL_MUL(llPendingSlop, llPendingSlop, tmp1);
1083
LL_SUB(notBefore, notBefore, llPendingSlop);
1084
if ( LL_CMP( t, <, notBefore ) ) {
1085
return(secCertTimeNotValidYet);
1088
/* If next update is omitted and the test for notBefore passes, then
1089
we assume that the crl is up to date.
1091
if ( LL_IS_ZERO(notAfter) ) {
1092
return(secCertTimeValid);
1095
if ( LL_CMP( t, >, notAfter) ) {
1096
return(secCertTimeExpired);
1099
return(secCertTimeValid);
1103
SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old) {
1104
PRTime newNotBefore, newNotAfter;
1105
PRTime oldNotBefore, oldNotAfter;
1108
/* problems with the new CRL? reject it */
1109
rv = SEC_GetCrlTimes(inNew, &newNotBefore, &newNotAfter);
1110
if (rv) return PR_FALSE;
1112
/* problems with the old CRL? replace it */
1113
rv = SEC_GetCrlTimes(old, &oldNotBefore, &oldNotAfter);
1114
if (rv) return PR_TRUE;
1116
/* Question: what about the notAfter's? */
1117
return ((PRBool)LL_CMP(oldNotBefore, <, newNotBefore));
1121
* return required key usage and cert type based on cert usage
1124
CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage,
1126
unsigned int *retKeyUsage,
1127
unsigned int *retCertType)
1129
unsigned int requiredKeyUsage = 0;
1130
unsigned int requiredCertType = 0;
1134
case certUsageSSLServerWithStepUp:
1135
requiredKeyUsage = KU_NS_GOVT_APPROVED | KU_KEY_CERT_SIGN;
1136
requiredCertType = NS_CERT_TYPE_SSL_CA;
1138
case certUsageSSLClient:
1139
requiredKeyUsage = KU_KEY_CERT_SIGN;
1140
requiredCertType = NS_CERT_TYPE_SSL_CA;
1142
case certUsageSSLServer:
1143
requiredKeyUsage = KU_KEY_CERT_SIGN;
1144
requiredCertType = NS_CERT_TYPE_SSL_CA;
1146
case certUsageSSLCA:
1147
requiredKeyUsage = KU_KEY_CERT_SIGN;
1148
requiredCertType = NS_CERT_TYPE_SSL_CA;
1150
case certUsageEmailSigner:
1151
requiredKeyUsage = KU_KEY_CERT_SIGN;
1152
requiredCertType = NS_CERT_TYPE_EMAIL_CA;
1154
case certUsageEmailRecipient:
1155
requiredKeyUsage = KU_KEY_CERT_SIGN;
1156
requiredCertType = NS_CERT_TYPE_EMAIL_CA;
1158
case certUsageObjectSigner:
1159
requiredKeyUsage = KU_KEY_CERT_SIGN;
1160
requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA;
1162
case certUsageAnyCA:
1163
case certUsageVerifyCA:
1164
case certUsageStatusResponder:
1165
requiredKeyUsage = KU_KEY_CERT_SIGN;
1166
requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA |
1167
NS_CERT_TYPE_EMAIL_CA |
1168
NS_CERT_TYPE_SSL_CA;
1176
case certUsageSSLClient:
1177
requiredKeyUsage = KU_DIGITAL_SIGNATURE;
1178
requiredCertType = NS_CERT_TYPE_SSL_CLIENT;
1180
case certUsageSSLServer:
1181
requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT;
1182
requiredCertType = NS_CERT_TYPE_SSL_SERVER;
1184
case certUsageSSLServerWithStepUp:
1185
requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT |
1186
KU_NS_GOVT_APPROVED;
1187
requiredCertType = NS_CERT_TYPE_SSL_SERVER;
1189
case certUsageSSLCA:
1190
requiredKeyUsage = KU_KEY_CERT_SIGN;
1191
requiredCertType = NS_CERT_TYPE_SSL_CA;
1193
case certUsageEmailSigner:
1194
requiredKeyUsage = KU_DIGITAL_SIGNATURE;
1195
requiredCertType = NS_CERT_TYPE_EMAIL;
1197
case certUsageEmailRecipient:
1198
requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT;
1199
requiredCertType = NS_CERT_TYPE_EMAIL;
1201
case certUsageObjectSigner:
1202
requiredKeyUsage = KU_DIGITAL_SIGNATURE;
1203
requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING;
1205
case certUsageStatusResponder:
1206
requiredKeyUsage = KU_DIGITAL_SIGNATURE;
1207
requiredCertType = EXT_KEY_USAGE_STATUS_RESPONDER;
1215
if ( retKeyUsage != NULL ) {
1216
*retKeyUsage = requiredKeyUsage;
1218
if ( retCertType != NULL ) {
1219
*retCertType = requiredCertType;
1228
* check the key usage of a cert against a set of required values
1231
CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage)
1233
unsigned int certKeyUsage;
1236
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1239
/* choose between key agreement or key encipherment based on key
1242
if ( requiredUsage & KU_KEY_AGREEMENT_OR_ENCIPHERMENT ) {
1243
KeyType keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
1244
/* turn off the special bit */
1245
requiredUsage &= (~KU_KEY_AGREEMENT_OR_ENCIPHERMENT);
1249
requiredUsage |= KU_KEY_ENCIPHERMENT;
1252
requiredUsage |= KU_DIGITAL_SIGNATURE;
1257
requiredUsage |= KU_KEY_AGREEMENT;
1260
/* Accept either signature or agreement. */
1261
if (!(cert->keyUsage & (KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)))
1269
certKeyUsage = cert->keyUsage;
1270
if (certKeyUsage & KU_NON_REPUDIATION)
1271
certKeyUsage |= KU_DIGITAL_SIGNATURE;
1272
if ( (certKeyUsage & requiredUsage) == requiredUsage )
1276
PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1282
CERT_DupCertificate(CERTCertificate *c)
1286
CERT_LockCertRefCount(c);
1287
++c->referenceCount;
1288
CERT_UnlockCertRefCount(c);
1290
NSSCertificate *tmp = STAN_GetNSSCertificate(c);
1291
nssCertificate_AddRef(tmp);
1298
* Allow use of default cert database, so that apps(such as mozilla) don't
1299
* have to pass the handle all over the place.
1301
static CERTCertDBHandle *default_cert_db_handle = 0;
1304
CERT_SetDefaultCertDB(CERTCertDBHandle *handle)
1306
default_cert_db_handle = handle;
1312
CERT_GetDefaultCertDB(void)
1314
return(default_cert_db_handle);
1317
/* XXX this would probably be okay/better as an xp routine? */
1319
sec_lower_string(char *s)
1326
*s = PORT_Tolower(*s);
1334
** Add a domain name to the list of names that the user has explicitly
1335
** allowed (despite cert name mismatches) for use with a server cert.
1338
CERT_AddOKDomainName(CERTCertificate *cert, const char *hn)
1340
CERTOKDomainName *domainOK;
1343
if (!hn || !(newNameLen = strlen(hn))) {
1344
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1347
domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena,
1348
(sizeof *domainOK) + newNameLen);
1350
return SECFailure; /* error code is already set. */
1352
PORT_Strcpy(domainOK->name, hn);
1353
sec_lower_string(domainOK->name);
1355
/* put at head of list. */
1356
domainOK->next = cert->domainOK;
1357
cert->domainOK = domainOK;
1361
/* returns SECSuccess if hn matches pattern cn,
1362
** returns SECFailure with SSL_ERROR_BAD_CERT_DOMAIN if no match,
1363
** returns SECFailure with some other error code if another error occurs.
1365
** may modify cn, so caller must pass a modifiable copy.
1368
cert_TestHostName(char * cn, const char * hn)
1370
int regvalid = PORT_RegExpValid(cn);
1371
if (regvalid != NON_SXP) {
1373
/* cn is a regular expression, try to match the shexp */
1374
int match = PORT_RegExpCaseSearch(hn, cn);
1379
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
1384
/* cn is not a regular expression */
1386
/* compare entire hn with cert name */
1387
if (PORT_Strcasecmp(hn, cn) == 0) {
1391
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
1397
cert_VerifySubjectAltName(CERTCertificate *cert, const char *hn)
1399
PRArenaPool * arena = NULL;
1400
CERTGeneralName * nameList = NULL;
1401
CERTGeneralName * current;
1405
int DNSextCount = 0;
1408
SECStatus rv = SECFailure;
1413
subAltName.data = NULL;
1416
cnBufLen = sizeof cnbuf;
1418
rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
1420
if (rv != SECSuccess) {
1423
isIPaddr = (PR_SUCCESS == PR_StringToNetAddr(hn, &netAddr));
1425
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1429
nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName);
1434
switch (current->type) {
1437
/* DNS name current->name.other.data is not null terminated.
1440
int cnLen = current->name.other.len;
1441
if (cnLen + 1 > cnBufLen) {
1442
cnBufLen = cnLen + 1;
1443
cn = (char *)PORT_ArenaAlloc(arena, cnBufLen);
1447
PORT_Memcpy(cn, current->name.other.data, cnLen);
1449
rv = cert_TestHostName(cn ,hn);
1450
if (rv == SECSuccess)
1459
if (current->name.other.len == 4 && /* IP v4 address */
1460
netAddr.inet.family == PR_AF_INET) {
1461
match = !memcmp(&netAddr.inet.ip,
1462
current->name.other.data, 4);
1463
} else if (current->name.other.len == 16 && /* IP v6 address */
1464
netAddr.ipv6.family == PR_AF_INET6) {
1465
match = !memcmp(&netAddr.ipv6.ip,
1466
current->name.other.data, 16);
1467
} else if (current->name.other.len == 16 && /* IP v6 address */
1468
netAddr.inet.family == PR_AF_INET) {
1469
/* convert netAddr to ipv6, then compare. */
1470
/* ipv4 must be in Network Byte Order on input. */
1471
PR_ConvertIPv4AddrToIPv6(netAddr.inet.ip, &v6Addr);
1472
match = !memcmp(&v6Addr, current->name.other.data, 16);
1473
} else if (current->name.other.len == 4 && /* IP v4 address */
1474
netAddr.inet.family == PR_AF_INET6) {
1475
/* convert netAddr to ipv6, then compare. */
1476
PRUint32 ipv4 = (current->name.other.data[0] << 24) |
1477
(current->name.other.data[1] << 16) |
1478
(current->name.other.data[2] << 8) |
1479
current->name.other.data[3];
1480
/* ipv4 must be in Network Byte Order on input. */
1481
PR_ConvertIPv4AddrToIPv6(PR_htonl(ipv4), &v6Addr);
1482
match = !memcmp(&netAddr.ipv6.ip, &v6Addr, 16);
1494
current = CERT_GetNextGeneralName(current);
1495
} while (current != nameList);
1497
if ((!isIPaddr && !DNSextCount) || (isIPaddr && !IPextCount)) {
1498
/* no relevant value in the extension was found. */
1499
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
1501
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
1507
/* Don't free nameList, it's part of the arena. */
1509
PORT_FreeArena(arena, PR_FALSE);
1512
if (subAltName.data) {
1513
SECITEM_FreeItem(&subAltName, PR_FALSE);
1520
/* Make sure that the name of the host we are connecting to matches the
1521
* name that is incoded in the common-name component of the certificate
1522
* that they are using.
1525
CERT_VerifyCertName(CERTCertificate *cert, const char *hn)
1529
CERTOKDomainName *domainOK;
1531
if (!hn || !strlen(hn)) {
1532
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1536
/* if the name is one that the user has already approved, it's OK. */
1537
for (domainOK = cert->domainOK; domainOK; domainOK = domainOK->next) {
1538
if (0 == PORT_Strcasecmp(hn, domainOK->name)) {
1543
/* Per RFC 2818, if the SubjectAltName extension is present, it must
1544
** be used as the cert's identity.
1546
rv = cert_VerifySubjectAltName(cert, hn);
1547
if (rv == SECSuccess || PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
1550
/* try the cert extension first, then the common name */
1551
cn = CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
1553
cn = CERT_GetCommonName(&cert->subject);
1556
rv = cert_TestHostName(cn, hn);
1559
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
1564
CERT_CompareCerts(CERTCertificate *c1, CERTCertificate *c2)
1568
comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert);
1569
if ( comp == SECEqual ) { /* certs are the same */
1577
StringsEqual(char *s1, char *s2) {
1578
if ( ( s1 == NULL ) || ( s2 == NULL ) ) {
1579
if ( s1 != s2 ) { /* only one is null */
1582
return(SECSuccess); /* both are null */
1585
if ( PORT_Strcmp( s1, s2 ) != 0 ) {
1586
return(SECFailure); /* not equal */
1589
return(SECSuccess); /* strings are equal */
1594
CERT_CompareCertsForRedirection(CERTCertificate *c1, CERTCertificate *c2)
1597
char *c1str, *c2str;
1600
comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert);
1601
if ( comp == SECEqual ) { /* certs are the same */
1605
/* check if they are issued by the same CA */
1606
comp = SECITEM_CompareItem(&c1->derIssuer, &c2->derIssuer);
1607
if ( comp != SECEqual ) { /* different issuer */
1611
/* check country name */
1612
c1str = CERT_GetCountryName(&c1->subject);
1613
c2str = CERT_GetCountryName(&c2->subject);
1614
eq = StringsEqual(c1str, c2str);
1617
if ( eq != SECSuccess ) {
1621
/* check locality name */
1622
c1str = CERT_GetLocalityName(&c1->subject);
1623
c2str = CERT_GetLocalityName(&c2->subject);
1624
eq = StringsEqual(c1str, c2str);
1627
if ( eq != SECSuccess ) {
1631
/* check state name */
1632
c1str = CERT_GetStateName(&c1->subject);
1633
c2str = CERT_GetStateName(&c2->subject);
1634
eq = StringsEqual(c1str, c2str);
1637
if ( eq != SECSuccess ) {
1641
/* check org name */
1642
c1str = CERT_GetOrgName(&c1->subject);
1643
c2str = CERT_GetOrgName(&c2->subject);
1644
eq = StringsEqual(c1str, c2str);
1647
if ( eq != SECSuccess ) {
1652
/* check orgUnit name */
1654
* We need to revisit this and decide which fields should be allowed to be
1657
c1str = CERT_GetOrgUnitName(&c1->subject);
1658
c2str = CERT_GetOrgUnitName(&c2->subject);
1659
eq = StringsEqual(c1str, c2str);
1662
if ( eq != SECSuccess ) {
1667
return(PR_TRUE); /* all fields but common name are the same */
1671
/* CERT_CertChainFromCert and CERT_DestroyCertificateList moved
1676
CERT_GetCertIssuerAndSN(PRArenaPool *arena, CERTCertificate *cert)
1678
CERTIssuerAndSN *result;
1681
if ( arena == NULL ) {
1682
arena = cert->arena;
1685
result = (CERTIssuerAndSN*)PORT_ArenaZAlloc(arena, sizeof(*result));
1686
if (result == NULL) {
1687
PORT_SetError (SEC_ERROR_NO_MEMORY);
1691
rv = SECITEM_CopyItem(arena, &result->derIssuer, &cert->derIssuer);
1692
if (rv != SECSuccess)
1695
rv = CERT_CopyName(arena, &result->issuer, &cert->issuer);
1696
if (rv != SECSuccess)
1699
rv = SECITEM_CopyItem(arena, &result->serialNumber, &cert->serialNumber);
1700
if (rv != SECSuccess)
1707
CERT_MakeCANickname(CERTCertificate *cert)
1709
char *firstname = NULL;
1711
char *nickname = NULL;
1713
CERTCertificate *dummycert;
1714
CERTCertDBHandle *handle;
1716
handle = cert->dbhandle;
1718
nickname = CERT_GetNickName(cert, handle, cert->arena);
1719
if (nickname == NULL) {
1720
firstname = CERT_GetCommonName(&cert->subject);
1721
if ( firstname == NULL ) {
1722
firstname = CERT_GetOrgUnitName(&cert->subject);
1725
org = CERT_GetOrgName(&cert->issuer);
1727
org = CERT_GetDomainComponentName(&cert->issuer);
1733
org = PORT_Strdup("Unknown CA");
1738
/* can only fail if PORT_Strdup fails, in which case
1739
* we're having memory problems. */
1750
nickname = PR_smprintf("%s - %s", firstname, org);
1752
nickname = PR_smprintf("%s - %s #%d", firstname, org, count);
1756
nickname = PR_smprintf("%s", org);
1758
nickname = PR_smprintf("%s #%d", org, count);
1761
if ( nickname == NULL ) {
1765
/* look up the nickname to make sure it isn't in use already */
1766
dummycert = CERT_FindCertByNickname(handle, nickname);
1768
if ( dummycert == NULL ) {
1772
/* found a cert, destroy it and loop */
1773
CERT_DestroyCertificate(dummycert);
1775
/* free the nickname */
1776
PORT_Free(nickname);
1783
PORT_Free(nickname);
1790
PORT_Free(firstname);
1799
/* CERT_Import_CAChain moved to certhigh.c */
1802
CERT_DestroyCrl (CERTSignedCrl *crl)
1804
SEC_DestroyCrl (crl);
1810
* Does a cert belong to a CA? We decide based on perm database trust
1811
* flags, Netscape Cert Type Extension, and KeyUsage Extension.
1814
CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype)
1816
CERTCertTrust *trust;
1824
if ( cert->trust && (cert->trust->sslFlags|cert->trust->emailFlags|
1825
cert->trust->objectSigningFlags)) {
1826
trust = cert->trust;
1827
if ( ( ( trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||
1828
( ( trust->sslFlags & CERTDB_TRUSTED_CA ) == CERTDB_TRUSTED_CA ) ) {
1830
type |= NS_CERT_TYPE_SSL_CA;
1833
if ( ( ( trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||
1834
( ( trust->emailFlags & CERTDB_TRUSTED_CA ) == CERTDB_TRUSTED_CA ) ) {
1836
type |= NS_CERT_TYPE_EMAIL_CA;
1839
if ( ( ( trust->objectSigningFlags & CERTDB_VALID_CA )
1840
== CERTDB_VALID_CA ) ||
1841
( ( trust->objectSigningFlags & CERTDB_TRUSTED_CA )
1842
== CERTDB_TRUSTED_CA ) ) {
1844
type |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
1847
if ( cert->nsCertType &
1848
( NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA |
1849
NS_CERT_TYPE_OBJECT_SIGNING_CA ) ) {
1851
type = (cert->nsCertType & NS_CERT_TYPE_CA);
1853
CERTBasicConstraints constraints;
1854
rv = CERT_FindBasicConstraintExten(cert, &constraints);
1855
if ( rv == SECSuccess ) {
1856
if ( constraints.isCA ) {
1858
type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
1863
/* finally check if it's a FORTEZZA V1 CA */
1864
if (ret == PR_FALSE) {
1865
if (fortezzaIsCA(cert)) {
1867
type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
1872
/* the isRoot flag trumps all */
1875
/* set only these by default, same as above */
1876
type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
1879
if ( rettype != NULL ) {
1887
CERT_IsCADERCert(SECItem *derCert, unsigned int *type) {
1888
CERTCertificate *cert;
1891
/* This is okay -- only looks at extensions */
1892
cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
1893
if (cert == NULL) return PR_FALSE;
1895
isCA = CERT_IsCACert(cert,type);
1896
CERT_DestroyCertificate (cert);
1901
CERT_IsRootDERCert(SECItem *derCert)
1903
CERTCertificate *cert;
1906
/* This is okay -- only looks at extensions */
1907
cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
1908
if (cert == NULL) return PR_FALSE;
1910
isRoot = cert->isRoot;
1911
CERT_DestroyCertificate (cert);
1915
CERTCompareValidityStatus
1916
CERT_CompareValidityTimes(CERTValidity* val_a, CERTValidity* val_b)
1918
PRTime notBeforeA, notBeforeB, notAfterA, notAfterB;
1920
if (!val_a || !val_b)
1922
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1923
return certValidityUndetermined;
1926
if ( SECSuccess != DER_DecodeTimeChoice(¬BeforeA, &val_a->notBefore) ||
1927
SECSuccess != DER_DecodeTimeChoice(¬BeforeB, &val_b->notBefore) ||
1928
SECSuccess != DER_DecodeTimeChoice(¬AfterA, &val_a->notAfter) ||
1929
SECSuccess != DER_DecodeTimeChoice(¬AfterB, &val_b->notAfter) ) {
1930
return certValidityUndetermined;
1934
if (LL_CMP(notBeforeA,>,notAfterA) || LL_CMP(notBeforeB,>,notAfterB)) {
1935
PORT_SetError(SEC_ERROR_INVALID_TIME);
1936
return certValidityUndetermined;
1939
if (LL_CMP(notAfterA,!=,notAfterB)) {
1940
/* one cert validity goes farther into the future, select it */
1941
return LL_CMP(notAfterA,<,notAfterB) ?
1942
certValidityChooseB : certValidityChooseA;
1944
/* the two certs have the same expiration date */
1945
PORT_Assert(LL_CMP(notAfterA, == , notAfterB));
1946
/* do they also have the same start date ? */
1947
if (LL_CMP(notBeforeA,==,notBeforeB)) {
1948
return certValidityEqual;
1950
/* choose cert with the later start date */
1951
return LL_CMP(notBeforeA,<,notBeforeB) ?
1952
certValidityChooseB : certValidityChooseA;
1956
* is certa newer than certb? If one is expired, pick the other one.
1959
CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb)
1961
PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
1963
PRBool newerbefore, newerafter;
1965
rv = CERT_GetCertTimes(certa, ¬BeforeA, ¬AfterA);
1966
if ( rv != SECSuccess ) {
1970
rv = CERT_GetCertTimes(certb, ¬BeforeB, ¬AfterB);
1971
if ( rv != SECSuccess ) {
1975
newerbefore = PR_FALSE;
1976
if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
1977
newerbefore = PR_TRUE;
1980
newerafter = PR_FALSE;
1981
if ( LL_CMP(notAfterA, >, notAfterB) ) {
1982
newerafter = PR_TRUE;
1985
if ( newerbefore && newerafter ) {
1989
if ( ( !newerbefore ) && ( !newerafter ) ) {
1993
/* get current time */
1996
if ( newerbefore ) {
1997
/* cert A was issued after cert B, but expires sooner */
1998
/* if A is expired, then pick B */
1999
if ( LL_CMP(notAfterA, <, now ) ) {
2004
/* cert B was issued after cert A, but expires sooner */
2005
/* if B is expired, then pick A */
2006
if ( LL_CMP(notAfterB, <, now ) ) {
2014
CERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts)
2019
for ( i = 0; i < ncerts; i++ ) {
2021
CERT_DestroyCertificate(certs[i]);
2032
CERT_FixupEmailAddr(char *emailAddr)
2037
if ( emailAddr == NULL ) {
2041
/* copy the string */
2042
str = retaddr = PORT_Strdup(emailAddr);
2043
if ( str == NULL ) {
2047
/* make it lower case */
2049
*str = tolower( *str );
2057
* NOTE - don't allow encode of govt-approved or invisible bits
2060
CERT_DecodeTrustString(CERTCertTrust *trust, char *trusts)
2063
unsigned int *pflags;
2066
PORT_SetError(SEC_ERROR_INVALID_ARGS);
2069
trust->sslFlags = 0;
2070
trust->emailFlags = 0;
2071
trust->objectSigningFlags = 0;
2073
PORT_SetError(SEC_ERROR_INVALID_ARGS);
2077
pflags = &trust->sslFlags;
2079
for (i=0; i < PORT_Strlen(trusts); i++) {
2080
switch (trusts[i]) {
2082
*pflags = *pflags | CERTDB_VALID_PEER;
2086
*pflags = *pflags | CERTDB_TRUSTED | CERTDB_VALID_PEER;
2090
*pflags = *pflags | CERTDB_SEND_WARN;
2094
*pflags = *pflags | CERTDB_VALID_CA;
2098
*pflags = *pflags | CERTDB_TRUSTED_CLIENT_CA | CERTDB_VALID_CA;
2102
*pflags = *pflags | CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
2106
*pflags = *pflags | CERTDB_USER;
2110
*pflags = *pflags | CERTDB_INVISIBLE_CA;
2113
*pflags = *pflags | CERTDB_GOVT_APPROVED_CA;
2117
if ( pflags == &trust->sslFlags ) {
2118
pflags = &trust->emailFlags;
2120
pflags = &trust->objectSigningFlags;
2132
EncodeFlags(char *trusts, unsigned int flags)
2134
if (flags & CERTDB_VALID_CA)
2135
if (!(flags & CERTDB_TRUSTED_CA) &&
2136
!(flags & CERTDB_TRUSTED_CLIENT_CA))
2137
PORT_Strcat(trusts, "c");
2138
if (flags & CERTDB_VALID_PEER)
2139
if (!(flags & CERTDB_TRUSTED))
2140
PORT_Strcat(trusts, "p");
2141
if (flags & CERTDB_TRUSTED_CA)
2142
PORT_Strcat(trusts, "C");
2143
if (flags & CERTDB_TRUSTED_CLIENT_CA)
2144
PORT_Strcat(trusts, "T");
2145
if (flags & CERTDB_TRUSTED)
2146
PORT_Strcat(trusts, "P");
2147
if (flags & CERTDB_USER)
2148
PORT_Strcat(trusts, "u");
2149
if (flags & CERTDB_SEND_WARN)
2150
PORT_Strcat(trusts, "w");
2151
if (flags & CERTDB_INVISIBLE_CA)
2152
PORT_Strcat(trusts, "I");
2153
if (flags & CERTDB_GOVT_APPROVED_CA)
2154
PORT_Strcat(trusts, "G");
2159
CERT_EncodeTrustString(CERTCertTrust *trust)
2161
char tmpTrustSSL[32];
2162
char tmpTrustEmail[32];
2163
char tmpTrustSigning[32];
2164
char *retstr = NULL;
2167
tmpTrustSSL[0] = '\0';
2168
tmpTrustEmail[0] = '\0';
2169
tmpTrustSigning[0] = '\0';
2171
EncodeFlags(tmpTrustSSL, trust->sslFlags);
2172
EncodeFlags(tmpTrustEmail, trust->emailFlags);
2173
EncodeFlags(tmpTrustSigning, trust->objectSigningFlags);
2175
retstr = PR_smprintf("%s,%s,%s", tmpTrustSSL, tmpTrustEmail,
2182
/* in 3.4, this will only set trust */
2184
CERT_SaveImportedCert(CERTCertificate *cert, SECCertUsage usage,
2185
PRBool caOnly, char *nickname)
2189
CERTCertTrust trust;
2191
unsigned int certtype;
2193
isCA = CERT_IsCACert(cert, NULL);
2194
if ( caOnly && ( !isCA ) ) {
2197
/* In NSS 3.4, certs are given zero trust upon import. However, this
2198
* function needs to set up default CA trust (CERTDB_VALID_CA), or
2199
* PKCS#12 imported certs will not show up correctly. In the case of a
2200
* CA cert with zero trust, continue with this function. But if the cert
2201
* does already have some trust bits, exit and do not change them.
2203
if (isCA && cert->trust &&
2204
(cert->trust->sslFlags |
2205
cert->trust->emailFlags |
2206
cert->trust->objectSigningFlags)) {
2212
PORT_Memset((void *)&trust, 0, sizeof(trust));
2214
certtype = cert->nsCertType;
2216
/* if no CA bits in cert type, then set all CA bits */
2217
if ( isCA && ( ! ( certtype & NS_CERT_TYPE_CA ) ) ) {
2218
certtype |= NS_CERT_TYPE_CA;
2221
/* if no app bits in cert type, then set all app bits */
2222
if ( ( !isCA ) && ( ! ( certtype & NS_CERT_TYPE_APP ) ) ) {
2223
certtype |= NS_CERT_TYPE_APP;
2227
case certUsageEmailSigner:
2228
case certUsageEmailRecipient:
2230
if ( certtype & NS_CERT_TYPE_EMAIL_CA ) {
2231
trust.emailFlags = CERTDB_VALID_CA;
2234
if ( !cert->emailAddr || !cert->emailAddr[0] ) {
2238
if ( certtype & NS_CERT_TYPE_EMAIL ) {
2239
trust.emailFlags = CERTDB_VALID_PEER;
2240
if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) {
2241
/* don't save it if KeyEncipherment is not allowed */
2247
case certUsageUserCertImport:
2249
if ( certtype & NS_CERT_TYPE_SSL_CA ) {
2250
trust.sslFlags = CERTDB_VALID_CA;
2253
if ( certtype & NS_CERT_TYPE_EMAIL_CA ) {
2254
trust.emailFlags = CERTDB_VALID_CA;
2257
if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
2258
trust.objectSigningFlags = CERTDB_VALID_CA;
2262
if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) {
2263
trust.sslFlags = CERTDB_VALID_PEER;
2266
if ( certtype & NS_CERT_TYPE_EMAIL ) {
2267
trust.emailFlags = CERTDB_VALID_PEER;
2270
if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) {
2271
trust.objectSigningFlags = CERTDB_VALID_PEER;
2275
case certUsageAnyCA:
2276
trust.sslFlags = CERTDB_VALID_CA;
2278
case certUsageSSLCA:
2279
trust.sslFlags = CERTDB_VALID_CA |
2280
CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
2282
default: /* XXX added to quiet warnings; no other cases needed? */
2287
rv = CERT_ChangeCertTrust(cert->dbhandle, cert, &trust);
2288
if ( rv != SECSuccess ) {
2304
CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage,
2305
unsigned int ncerts, SECItem **derCerts,
2306
CERTCertificate ***retCerts, PRBool keepCerts,
2307
PRBool caOnly, char *nickname)
2310
CERTCertificate **certs = NULL;
2312
unsigned int fcerts = 0;
2315
certs = PORT_ZNewArray(CERTCertificate*, ncerts);
2316
if ( certs == NULL ) {
2320
/* decode all of the certs into the temporary DB */
2321
for ( i = 0, fcerts= 0; i < ncerts; i++) {
2322
certs[fcerts] = CERT_NewTempCertificate(certdb,
2327
if (certs[fcerts]) fcerts++;
2331
for ( i = 0; i < fcerts; i++ ) {
2332
char* canickname = NULL;
2333
PRBool freeNickname = PR_FALSE;
2335
SECKEY_UpdateCertPQG(certs[i]);
2337
if ( CERT_IsCACert(certs[i], NULL) ) {
2338
canickname = CERT_MakeCANickname(certs[i]);
2339
if ( canickname != NULL ) {
2340
freeNickname = PR_TRUE;
2344
if(CERT_IsCACert(certs[i], NULL) && (fcerts > 1)) {
2345
/* if we are importing only a single cert and specifying
2346
* a nickname, we want to use that nickname if it a CA,
2347
* otherwise if there are more than one cert, we don't
2348
* know which cert it belongs to. But we still may try
2349
* the individual canickname from the cert itself.
2351
rv = CERT_AddTempCertToPerm(certs[i], canickname, NULL);
2353
rv = CERT_AddTempCertToPerm(certs[i],
2354
nickname?nickname:canickname, NULL);
2356
if (rv == SECSuccess) {
2357
CERT_SaveImportedCert(certs[i], usage, caOnly, NULL);
2360
if (PR_TRUE == freeNickname) {
2361
PORT_Free(canickname);
2363
/* don't care if it fails - keep going */
2372
CERT_DestroyCertArray(certs, fcerts);
2376
return ((fcerts || !ncerts) ? SECSuccess : SECFailure);
2380
* a real list of certificates - need to convert CERTCertificateList
2381
* stuff and ASN 1 encoder/decoder over to using this...
2384
CERT_NewCertList(void)
2386
PRArenaPool *arena = NULL;
2387
CERTCertList *ret = NULL;
2389
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2390
if ( arena == NULL ) {
2394
ret = (CERTCertList *)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
2395
if ( ret == NULL ) {
2401
PR_INIT_CLIST(&ret->list);
2406
if ( arena != NULL ) {
2407
PORT_FreeArena(arena, PR_FALSE);
2414
CERT_DestroyCertList(CERTCertList *certs)
2418
while( !PR_CLIST_IS_EMPTY(&certs->list) ) {
2419
node = PR_LIST_HEAD(&certs->list);
2420
CERT_DestroyCertificate(((CERTCertListNode *)node)->cert);
2421
PR_REMOVE_LINK(node);
2424
PORT_FreeArena(certs->arena, PR_FALSE);
2430
CERT_RemoveCertListNode(CERTCertListNode *node)
2432
CERT_DestroyCertificate(node->cert);
2433
PR_REMOVE_LINK(&node->links);
2439
CERT_AddCertToListTailWithData(CERTCertList *certs,
2440
CERTCertificate *cert, void *appData)
2442
CERTCertListNode *node;
2444
node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
2445
sizeof(CERTCertListNode));
2446
if ( node == NULL ) {
2450
PR_INSERT_BEFORE(&node->links, &certs->list);
2451
/* certs->count++; */
2453
node->appData = appData;
2461
CERT_AddCertToListTail(CERTCertList *certs, CERTCertificate *cert)
2463
return CERT_AddCertToListTailWithData(certs, cert, NULL);
2467
CERT_AddCertToListHeadWithData(CERTCertList *certs,
2468
CERTCertificate *cert, void *appData)
2470
CERTCertListNode *node;
2471
CERTCertListNode *head;
2473
head = CERT_LIST_HEAD(certs);
2475
if (head == NULL) return CERT_AddCertToListTail(certs,cert);
2477
node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
2478
sizeof(CERTCertListNode));
2479
if ( node == NULL ) {
2483
PR_INSERT_BEFORE(&node->links, &head->links);
2484
/* certs->count++; */
2486
node->appData = appData;
2494
CERT_AddCertToListHead(CERTCertList *certs, CERTCertificate *cert)
2496
return CERT_AddCertToListHeadWithData(certs, cert, NULL);
2500
* Sort callback function to determine if cert a is newer than cert b.
2501
* Not valid certs are considered older than valid certs.
2504
CERT_SortCBValidity(CERTCertificate *certa,
2505
CERTCertificate *certb,
2509
PRTime notBeforeA, notAfterA, notBeforeB, notAfterB;
2511
PRBool newerbefore, newerafter;
2512
PRBool aNotValid = PR_FALSE, bNotValid = PR_FALSE;
2514
sorttime = *(PRTime *)arg;
2516
rv = CERT_GetCertTimes(certa, ¬BeforeA, ¬AfterA);
2517
if ( rv != SECSuccess ) {
2521
rv = CERT_GetCertTimes(certb, ¬BeforeB, ¬AfterB);
2522
if ( rv != SECSuccess ) {
2525
newerbefore = PR_FALSE;
2526
if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
2527
newerbefore = PR_TRUE;
2529
newerafter = PR_FALSE;
2530
if ( LL_CMP(notAfterA, >, notAfterB) ) {
2531
newerafter = PR_TRUE;
2534
/* check if A is valid at sorttime */
2535
if ( CERT_CheckCertValidTimes(certa, sorttime, PR_FALSE)
2536
!= secCertTimeValid ) {
2537
aNotValid = PR_TRUE;
2540
/* check if B is valid at sorttime */
2541
if ( CERT_CheckCertValidTimes(certb, sorttime, PR_FALSE)
2542
!= secCertTimeValid ) {
2543
bNotValid = PR_TRUE;
2546
/* a is valid, b is not */
2547
if ( bNotValid && ( ! aNotValid ) ) {
2551
/* b is valid, a is not */
2552
if ( aNotValid && ( ! bNotValid ) ) {
2556
/* a and b are either valid or not valid */
2557
if ( newerbefore && newerafter ) {
2561
if ( ( !newerbefore ) && ( !newerafter ) ) {
2565
if ( newerbefore ) {
2566
/* cert A was issued after cert B, but expires sooner */
2569
/* cert B was issued after cert A, but expires sooner */
2576
CERT_AddCertToListSorted(CERTCertList *certs,
2577
CERTCertificate *cert,
2581
CERTCertListNode *node;
2582
CERTCertListNode *head;
2585
node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
2586
sizeof(CERTCertListNode));
2587
if ( node == NULL ) {
2591
head = CERT_LIST_HEAD(certs);
2593
while ( !CERT_LIST_END(head, certs) ) {
2595
/* if cert is already in the list, then don't add it again */
2596
if ( cert == head->cert ) {
2598
/* don't keep a reference */
2599
CERT_DestroyCertificate(cert);
2603
ret = (* f)(cert, head->cert, arg);
2604
/* if sort function succeeds, then insert before current node */
2606
PR_INSERT_BEFORE(&node->links, &head->links);
2610
head = CERT_LIST_NEXT(head);
2612
/* if we get to the end, then just insert it at the tail */
2613
PR_INSERT_BEFORE(&node->links, &certs->list);
2616
/* certs->count++; */
2624
/* This routine is here because pcertdb.c still has a call to it.
2625
* The SMIME profile code in pcertdb.c should be split into high (find
2626
* the email cert) and low (store the profile) code. At that point, we
2627
* can move this to certhigh.c where it belongs.
2629
* remove certs from a list that don't have keyUsage and certType
2630
* that match the given usage.
2633
CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage,
2636
unsigned int requiredKeyUsage;
2637
unsigned int requiredCertType;
2638
CERTCertListNode *node, *savenode;
2641
if (certList == NULL) goto loser;
2643
rv = CERT_KeyUsageAndTypeForCertUsage(usage, ca, &requiredKeyUsage,
2645
if ( rv != SECSuccess ) {
2649
node = CERT_LIST_HEAD(certList);
2651
while ( !CERT_LIST_END(node, certList) ) {
2653
PRBool bad = (PRBool)(!node->cert);
2655
/* bad key usage ? */
2657
CERT_CheckKeyUsage(node->cert, requiredKeyUsage) != SECSuccess ) {
2660
/* bad cert type ? */
2662
unsigned int certType = 0;
2664
/* This function returns a more comprehensive cert type that
2665
* takes trust flags into consideration. Should probably
2666
* fix the cert decoding code to do this.
2668
(void)CERT_IsCACert(node->cert, &certType);
2670
certType = node->cert->nsCertType;
2672
if ( !( certType & requiredCertType ) ) {
2678
/* remove the node if it is bad */
2679
savenode = CERT_LIST_NEXT(node);
2680
CERT_RemoveCertListNode(node);
2683
node = CERT_LIST_NEXT(node);
2692
PRBool CERT_IsUserCert(CERTCertificate* cert)
2695
((cert->trust->sslFlags & CERTDB_USER ) ||
2696
(cert->trust->emailFlags & CERTDB_USER ) ||
2697
(cert->trust->objectSigningFlags & CERTDB_USER )) ) {
2705
CERT_FilterCertListForUserCerts(CERTCertList *certList)
2707
CERTCertListNode *node, *freenode;
2708
CERTCertificate *cert;
2714
node = CERT_LIST_HEAD(certList);
2716
while ( ! CERT_LIST_END(node, certList) ) {
2718
if ( PR_TRUE != CERT_IsUserCert(cert) ) {
2719
/* Not a User Cert, so remove this cert from the list */
2721
node = CERT_LIST_NEXT(node);
2722
CERT_RemoveCertListNode(freenode);
2724
/* Is a User cert, so leave it in the list */
2725
node = CERT_LIST_NEXT(node);
2732
static PZLock *certRefCountLock = NULL;
2735
* Acquire the cert reference count lock
2736
* There is currently one global lock for all certs, but I'm putting a cert
2737
* arg here so that it will be easy to make it per-cert in the future if
2738
* that turns out to be necessary.
2741
CERT_LockCertRefCount(CERTCertificate *cert)
2743
if ( certRefCountLock == NULL ) {
2744
nss_InitLock(&certRefCountLock, nssILockRefLock);
2745
PORT_Assert(certRefCountLock != NULL);
2748
PZ_Lock(certRefCountLock);
2753
* Free the cert reference count lock
2756
CERT_UnlockCertRefCount(CERTCertificate *cert)
2760
PORT_Assert(certRefCountLock != NULL);
2762
prstat = PZ_Unlock(certRefCountLock);
2764
PORT_Assert(prstat == PR_SUCCESS);
2769
static PZLock *certTrustLock = NULL;
2772
* Acquire the cert trust lock
2773
* There is currently one global lock for all certs, but I'm putting a cert
2774
* arg here so that it will be easy to make it per-cert in the future if
2775
* that turns out to be necessary.
2778
CERT_LockCertTrust(CERTCertificate *cert)
2780
if ( certTrustLock == NULL ) {
2781
nss_InitLock(&certTrustLock, nssILockCertDB);
2782
PORT_Assert(certTrustLock != NULL);
2785
PZ_Lock(certTrustLock);
2790
* Free the cert trust lock
2793
CERT_UnlockCertTrust(CERTCertificate *cert)
2797
PORT_Assert(certTrustLock != NULL);
2799
prstat = PZ_Unlock(certTrustLock);
2801
PORT_Assert(prstat == PR_SUCCESS);
2808
* Get the StatusConfig data for this handle
2811
CERT_GetStatusConfig(CERTCertDBHandle *handle)
2813
return handle->statusConfig;
2817
* Set the StatusConfig data for this handle. There
2818
* should not be another configuration set.
2821
CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig)
2823
PORT_Assert(handle->statusConfig == NULL);
2824
handle->statusConfig = statusConfig;
2828
* Code for dealing with subjKeyID to cert mappings.
2831
static PLHashTable *gSubjKeyIDHash = NULL;
2832
static PRLock *gSubjKeyIDLock = NULL;
2834
static void *cert_AllocTable(void *pool, PRSize size)
2836
return PORT_Alloc(size);
2839
static void cert_FreeTable(void *pool, void *item)
2844
static PLHashEntry* cert_AllocEntry(void *pool, const void *key)
2846
return PORT_New(PLHashEntry);
2849
static void cert_FreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
2851
SECITEM_FreeItem((SECItem*)(he->value), PR_TRUE);
2852
if (flag == HT_FREE_ENTRY) {
2853
SECITEM_FreeItem((SECItem*)(he->key), PR_TRUE);
2858
static PLHashAllocOps cert_AllocOps = {
2859
cert_AllocTable, cert_FreeTable, cert_AllocEntry, cert_FreeEntry
2863
cert_CreateSubjectKeyIDHashTable(void)
2865
gSubjKeyIDHash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
2866
SECITEM_HashCompare,
2867
&cert_AllocOps, NULL);
2868
if (!gSubjKeyIDHash) {
2869
PORT_SetError(SEC_ERROR_NO_MEMORY);
2872
gSubjKeyIDLock = PR_NewLock();
2873
if (!gSubjKeyIDLock) {
2874
PL_HashTableDestroy(gSubjKeyIDHash);
2875
gSubjKeyIDHash = NULL;
2876
PORT_SetError(SEC_ERROR_NO_MEMORY);
2884
cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert)
2886
SECItem *newKeyID, *oldVal, *newVal;
2887
SECStatus rv = SECFailure;
2889
if (!gSubjKeyIDLock) {
2890
/* If one is created, then both are there. So only check for one. */
2894
newVal = SECITEM_DupItem(&cert->derCert);
2896
PORT_SetError(SEC_ERROR_NO_MEMORY);
2899
newKeyID = SECITEM_DupItem(subjKeyID);
2901
SECITEM_FreeItem(newVal, PR_TRUE);
2902
PORT_SetError(SEC_ERROR_NO_MEMORY);
2906
PR_Lock(gSubjKeyIDLock);
2907
/* The hash table implementation does not free up the memory
2908
* associated with the key of an already existing entry if we add a
2909
* duplicate, so we would wind up leaking the previously allocated
2910
* key if we don't remove before adding.
2912
oldVal = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
2914
PL_HashTableRemove(gSubjKeyIDHash, subjKeyID);
2917
rv = (PL_HashTableAdd(gSubjKeyIDHash, newKeyID, newVal)) ? SECSuccess :
2919
PR_Unlock(gSubjKeyIDLock);
2925
cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID)
2928
if (!gSubjKeyIDLock)
2931
PR_Lock(gSubjKeyIDLock);
2932
rv = (PL_HashTableRemove(gSubjKeyIDHash, subjKeyID)) ? SECSuccess :
2934
PR_Unlock(gSubjKeyIDLock);
2939
cert_DestroySubjectKeyIDHashTable(void)
2941
if (gSubjKeyIDHash) {
2942
PR_Lock(gSubjKeyIDLock);
2943
PL_HashTableDestroy(gSubjKeyIDHash);
2944
gSubjKeyIDHash = NULL;
2945
PR_Unlock(gSubjKeyIDLock);
2946
PR_DestroyLock(gSubjKeyIDLock);
2947
gSubjKeyIDLock = NULL;
2953
cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID)
2957
if (!gSubjKeyIDLock)
2960
PR_Lock(gSubjKeyIDLock);
2961
val = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
2963
val = SECITEM_DupItem(val);
2965
PR_Unlock(gSubjKeyIDLock);
2970
CERT_FindCertBySubjectKeyID(CERTCertDBHandle *handle, SECItem *subjKeyID)
2972
CERTCertificate *cert = NULL;
2975
derCert = cert_FindDERCertBySubjectKeyID(subjKeyID);
2977
cert = CERT_FindCertByDERCert(handle, derCert);
2978
SECITEM_FreeItem(derCert, PR_TRUE);