2 * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
29 #include <security_asn1/secerr.h>
30 #include <Security/SecKeychain.h>
31 #include <Security/SecKeychainItem.h>
32 #include <Security/SecKeychainSearch.h>
33 #include <Security/SecIdentity.h>
34 #include <Security/SecIdentityPriv.h>
35 #include <Security/SecIdentitySearch.h>
36 #include <Security/SecCertificatePriv.h>
37 #include <Security/SecPolicyPriv.h>
38 #include <Security/oidsalg.h>
39 #include <Security/cssmapi.h>
40 #include <Security/oidscert.h>
41 #include <Security/oidscert.h>
44 /* for errKCDuplicateItem */
45 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
49 #define dprintf(args...) fprintf(stderr, args)
51 #define dprintf(args...)
54 /* @@@ Remove this once it's back in the appropriate header. */
55 static const uint8 X509V1IssuerNameStd
[] = {INTEL_X509V3_CERT_R08
, 23};
56 static const CSSM_OID OID_X509V1IssuerNameStd
= {INTEL_X509V3_CERT_R08_LENGTH
+1, (uint8
*)X509V1IssuerNameStd
};
59 * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case
60 * insensitive and we're supposed to ignore leading and trailing
61 * whitespace, and collapse multiple whitespace characters into one.
64 CERT_NormalizeString(CSSM_DATA_PTR string
)
66 char *pD
, *pCh
, *pEos
;
71 pD
= pCh
= (char *)string
->Data
;
72 pEos
= pCh
+ string
->Length
- 1;
74 /* Strip trailing NULL terminators */
78 /* Remove trailing spaces */
82 /* Point to one past last non-space character */
85 /* skip all leading whitespace */
86 while(isspace(*pCh
) && (pCh
< pEos
))
89 /* Eliminate multiple whitespace and convent to upper case.
90 * pCh points to first non-white char.
91 * pD still points to start of string. */
98 /* skip 'til next nonwhite */
99 while(isspace(*pCh
) && (pCh
< pEos
))
104 string
->Length
= pD
- (char *)string
->Data
;
108 * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case
109 * insensitive and we're supposed to ignore leading and trailing
110 * whitespace, and collapse multiple whitespace characters into one.
112 * Incoming NSS_Name is assumed to be entirely within specifed coder's
113 * address space; we'll be munging some of that and possibly replacing
114 * some pointers with others allocated from the same space.
117 CERT_NormalizeX509NameNSS(NSS_Name
*nssName
)
121 for (rdn
= *nssName
->rdns
; rdn
; ++rdn
)
124 for (attr
= *rdn
->atvs
; attr
; ++attr
)
127 * attr->value is an ASN_ANY containing an encoded
128 * string. We only normalize Prinatable String types.
129 * If we find one, decode it, normalize it, encode the
130 * result, and put the encoding back in attr->value.
131 * We temporarily "leak" the original string, which only
132 * has a lifetime of the incoming SecNssCoder.
134 NSS_TaggedItem
*attrVal
= &attr
->value
;
135 if(attrVal
->tag
!= SEC_ASN1_PRINTABLE_STRING
)
138 CERT_NormalizeString(&attrVal
->item
);
143 SecCertificateRef
CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray
, char *name
)
145 SecCertificateRef certificate
;
146 OSStatus status
=SecCertificateFindByEmail(keychainOrArray
,name
,&certificate
);
147 return status
==noErr
?certificate
:NULL
;
150 SecPublicKeyRef
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
)
156 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
)
161 SecPublicKeyRef
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
)
167 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
)
172 void CERT_DestroyCertificate(SecCertificateRef cert
)
177 SecCertificateRef
CERT_DupCertificate(SecCertificateRef cert
)
183 SecIdentityRef
CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray
,
184 char *nickname
, SECCertUsage usage
, Boolean validOnly
, void *proto_win
)
186 SecIdentityRef identityRef
= NULL
;
187 SecCertificateRef cert
= CERT_FindCertByNicknameOrEmailAddr(keychainOrArray
, nickname
);
191 SecIdentityCreateWithCertificate(keychainOrArray
, cert
, &identityRef
);
197 SecCertificateRef
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
,
198 char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
)
200 SecItemClass itemClass
= kSecCertificateItemClass
;
201 SecKeychainSearchRef searchRef
;
202 SecKeychainItemRef itemRef
= NULL
;
204 SecKeychainAttribute attrs
[1];
205 const char *serialNumber
= "12345678";
206 // const SecKeychainAttributeList attrList;
208 attrs
[0].tag
= kSecLabelItemAttr
;
209 attrs
[0].length
= strlen(nickname
)+1;
210 attrs
[0].data
= nickname
;
212 attrs
[0].tag
= kSecSerialNumberItemAttr
;
213 attrs
[0].length
= (UInt32
)strlen(serialNumber
)+1;
214 attrs
[0].data
= (uint8
*)serialNumber
;
216 SecKeychainAttributeList attrList
= { 0, attrs
};
218 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
,itemClass
,&attrList
,&searchRef
);
221 printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status
);
224 status
= SecKeychainSearchCopyNext(searchRef
,&itemRef
);
226 printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status
);
227 CFRelease(searchRef
);
228 return (SecCertificateRef
)itemRef
;
232 startNewClass(X509Certificate)
233 CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
234 CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
235 PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
236 Alias, kSecAlias, "Alias", 0, NULL, BLOB)
237 Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
238 Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
239 SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
240 SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
241 PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
245 CFArrayRef
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
)
247 SecPolicyRef policy
= NULL
;
248 CFArrayRef wrappedCert
= NULL
;
249 SecTrustRef trust
= NULL
;
250 CFMutableArrayRef certs
= NULL
;
252 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
257 policy
= SecPolicyCreateBasicX509();
261 wrappedCert
= CERT_CertListFromCert(cert
);
262 status
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
);
266 /* SecTrustEvaluate will build us the best chain available using its heuristics.
267 * We'll ignore the trust result. */
268 status
= SecTrustEvaluate(trust
, &trustResult
);
271 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
273 /* If we weren't able to build a chain to a self-signed cert, warn. */
274 Boolean isSelfSigned
= false;
275 SecCertificateRef lastCert
= SecTrustGetCertificateAtIndex(trust
, count
- 1);
276 if (lastCert
&& (0 == SecCertificateIsSelfSigned(lastCert
, &isSelfSigned
)) && !isSelfSigned
) {
277 CFStringRef commonName
= NULL
;
278 (void)SecCertificateCopyCommonName(cert
, &commonName
);
279 fprintf(stderr
, "Warning: unable to build chain to self-signed root for signer \"%s\"",
280 commonName
? CFStringGetCStringPtr(commonName
, kCFStringEncodingUTF8
) : "");
281 if (commonName
) { CFRelease(commonName
); }
284 /* We don't drop the root if there is only 1 certificate in the chain. */
285 if (!includeRoot
&& count
> 1) { count
--; }
287 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
);
288 for(idx
= 0; idx
< count
; idx
++)
289 CFArrayAppendValue(certs
, SecTrustGetCertificateAtIndex(trust
, idx
));
295 CFRelease(wrappedCert
);
307 CFArrayRef
CERT_CertListFromCert(SecCertificateRef cert
)
309 const void *value
= cert
;
310 return cert
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
;
313 CFArrayRef
CERT_DupCertList(CFArrayRef oldList
)
319 // Extract a public key object from a SubjectPublicKeyInfo
320 SecPublicKeyRef
CERT_ExtractPublicKey(SecCertificateRef cert
)
322 return SecCertificateCopyKey(cert
);
325 SECStatus
CERT_CheckCertUsage (SecCertificateRef cert
,unsigned char usage
)
328 // @@@ It's all good, it's ok.
332 // Find a certificate in the database by a email address
333 // "emailAddr" is the email address to look up
334 SecCertificateRef
CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray
, char *emailAddr
)
340 // Find a certificate in the database by a DER encoded certificate
341 // "derCert" is the DER encoded certificate
342 SecCertificateRef
CERT_FindCertByDERCert(SecKeychainRef keychainOrArray
, const SECItem
*derCert
)
344 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
345 SecCertificateRef cert
= NULL
;
348 rv
= SecCertificateCreateFromData(derCert
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
351 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
359 int CERT_CompareCssmData(const CSSM_DATA
*d1
, const CSSM_DATA
*d2
)
361 if((d1
== NULL
) || (d2
== NULL
)) {
364 if(d1
->Length
!= d2
->Length
) {
367 if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) {
373 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
374 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
375 SecCertificateRef
CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray
,
376 CSSM_DATA_PTR
*rawCerts
, CFArrayRef certList
, PRArenaPool
*pl
, const SecCmsIssuerAndSN
*issuerAndSN
)
378 SecCertificateRef certificate
= NULL
;
379 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
384 * First search the rawCerts array.
386 for(dex
=0; dex
<numRawCerts
; dex
++) {
387 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
388 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
393 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, certificate
);
395 CFRelease(certificate
);
398 if(!CERT_CompareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
399 CFRelease(certificate
);
402 if(!CERT_CompareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
403 CFRelease(certificate
);
407 dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate
);
411 /* Search the user-added certList */
412 if (certList
&& CFArrayGetCount(certList
)) {
413 CFIndex c
, count
= CFArrayGetCount(certList
);
414 for (c
= 0; c
< count
; c
++) {
415 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
);
416 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, cert
);
420 if(!CERT_CompareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
423 if(!CERT_CompareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
429 if (certificate
) { return certificate
; }
432 /* now search keychain(s) */
433 OSStatus status
= SecCertificateFindByIssuerAndSN(keychainOrArray
, &issuerAndSN
->derIssuer
,
434 &issuerAndSN
->serialNumber
, &certificate
);
437 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
444 SecCertificateRef
CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray
,
445 CSSM_DATA_PTR
*rawCerts
, CFArrayRef certList
, const SECItem
*subjKeyID
)
447 SecCertificateRef certificate
;
448 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
454 * First search the rawCerts array.
456 for(dex
=0; dex
<numRawCerts
; dex
++) {
458 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
459 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
464 if(CERT_FindSubjectKeyIDExtension(certificate
, &skid
)) {
465 CFRelease(certificate
);
469 match
= CERT_CompareCssmData(subjKeyID
, &skid
);
470 SECITEM_FreeItem(&skid
, PR_FALSE
);
475 CFRelease(certificate
);
478 /* Search the user-added certList */
479 if (certList
&& CFArrayGetCount(certList
)) {
480 CFDataRef subjectkeyid
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subjKeyID
->Data
, subjKeyID
->Length
, kCFAllocatorNull
);
481 CFIndex c
, count
= CFArrayGetCount(certList
);
482 for (c
= 0; c
< count
; c
++) {
483 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
);
484 CFDataRef skid
= (cert
) ? SecCertificateGetSubjectKeyID(cert
) : NULL
;
485 if (skid
&& CFEqual(skid
, subjectkeyid
)) {
491 if (subjectkeyid
) { CFRelease(subjectkeyid
); };
492 if (certificate
) { return certificate
; }
495 /* now search keychain(s) */
496 OSStatus status
= SecCertificateFindBySubjectKeyID(keychainOrArray
,subjKeyID
,&certificate
);
499 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
506 static SecIdentityRef
507 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray
, SecCertificateRef CF_CONSUMED certificate
)
509 SecIdentityRef identity
= NULL
;
510 SecIdentityCreateWithCertificate(keychainOrArray
, certificate
, &identity
);
512 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT
);
514 CFRelease(certificate
);
521 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
523 SecCertificateRef certificate
= CERT_FindCertByIssuerAndSN(keychainOrArray
, NULL
, NULL
, NULL
, issuerAndSN
);
527 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
531 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray
, const SECItem
*subjKeyID
)
533 SecCertificateRef certificate
= CERT_FindCertBySubjectKeyID(keychainOrArray
, NULL
, NULL
, subjKeyID
);
537 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
540 // find the smime symmetric capabilities profile for a given cert
541 SECItem
*CERT_FindSMimeProfile(SecCertificateRef cert
)
546 // Return the decoded value of the subjectKeyID extension. The caller should
547 // free up the storage allocated in retItem->data.
548 SECStatus
CERT_FindSubjectKeyIDExtension (SecCertificateRef cert
, SECItem
*retItem
)
550 CSSM_DATA_PTR fieldValue
= NULL
;
552 CSSM_X509_EXTENSION
*extp
;
553 CE_SubjectKeyID
*skid
;
555 ortn
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
557 if(ortn
|| (fieldValue
== NULL
)) {
558 /* this cert doesn't have that extension */
561 extp
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
562 skid
= (CE_SubjectKeyID
*)extp
->value
.parsedValue
;
563 retItem
->Data
= (uint8
*)PORT_Alloc(skid
->Length
);
564 retItem
->Length
= skid
->Length
;
565 memmove(retItem
->Data
, skid
->Data
, retItem
->Length
);
566 SecCertificateReleaseFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
571 // Extract the issuer and serial number from a certificate
572 SecCmsIssuerAndSN
*CERT_GetCertIssuerAndSN(PRArenaPool
*pl
, SecCertificateRef cert
)
575 SecCmsIssuerAndSN
*certIssuerAndSN
;
576 SecCertificateRef certRef
;
577 SecCertificateRef itemImplRef
= NULL
;
578 CSSM_CL_HANDLE clHandle
;
579 CSSM_DATA_PTR serialNumber
= 0;
580 CSSM_DATA_PTR issuer
= 0;
581 CSSM_DATA certData
= {};
582 CSSM_HANDLE resultsHandle
= 0;
583 uint32 numberOfFields
= 0;
587 mark
= PORT_ArenaMark(pl
);
589 /* Retain input cert and get pointer to its data */
590 certRef
= (SecCertificateRef
)((cert
) ? CFRetain(cert
) : NULL
);
591 status
= SecCertificateGetData(certRef
, &certData
);
595 // Convert unified input certRef to itemImpl instance.
596 // note: must not release this instance while we're using its CL handle!
597 itemImplRef
= SecCertificateCreateItemImplInstance(cert
);
598 status
= SecCertificateGetCLHandle_legacy(itemImplRef
, &clHandle
);
600 status
= SecCertificateGetCLHandle(certRef
, &clHandle
);
605 /* Get the issuer from the cert. */
606 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
607 &OID_X509V1IssuerNameStd
, &resultsHandle
, &numberOfFields
, &issuer
);
609 if (result
|| numberOfFields
< 1)
611 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
615 /* Get the serialNumber from the cert. */
616 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
617 &CSSMOID_X509V1SerialNumber
, &resultsHandle
, &numberOfFields
, &serialNumber
);
618 if (result
|| numberOfFields
< 1)
620 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
624 /* Allocate the SecCmsIssuerAndSN struct. */
625 certIssuerAndSN
= (SecCmsIssuerAndSN
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
));
626 if (certIssuerAndSN
== NULL
)
629 /* Copy the issuer. */
630 certIssuerAndSN
->derIssuer
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, issuer
->Length
);
631 if (!certIssuerAndSN
->derIssuer
.Data
)
633 PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
->Data
, issuer
->Length
);
634 certIssuerAndSN
->derIssuer
.Length
= issuer
->Length
;
636 /* Copy the serialNumber. */
637 certIssuerAndSN
->serialNumber
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, serialNumber
->Length
);
638 if (!certIssuerAndSN
->serialNumber
.Data
)
640 PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
->Data
, serialNumber
->Length
);
641 certIssuerAndSN
->serialNumber
.Length
= serialNumber
->Length
;
643 PORT_ArenaUnmark(pl
, mark
);
645 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
646 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
649 CFRelease(itemImplRef
);
653 return certIssuerAndSN
;
656 PORT_ArenaRelease(pl
, mark
);
659 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
661 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
663 CFRelease(itemImplRef
);
667 PORT_SetError(SEC_INTERNAL_ONLY
);
671 // import a collection of certs into the temporary or permanent cert database
672 SECStatus
CERT_ImportCerts(SecKeychainRef keychain
, SECCertUsage usage
, unsigned int ncerts
,
673 SECItem
**derCerts
, SecCertificateRef
**retCerts
, Boolean keepCerts
, Boolean caOnly
, char *nickname
)
675 OSStatus rv
= SECFailure
;
676 SecCertificateRef cert
;
679 // @@@ Do something with caOnly and nickname
680 if (caOnly
|| nickname
)
683 for (ci
= 0; ci
< ncerts
; ++ci
)
685 rv
= SecCertificateCreateFromData(derCerts
[ci
], CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
690 rv
= SecCertificateAddToKeychain(cert
, keychain
);
693 if (rv
== errKCDuplicateItem
)
715 SECStatus
CERT_SaveSMimeProfile(SecCertificateRef cert
, SECItem
*emailProfile
,SECItem
*profileTime
)
717 fprintf(stderr
, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
721 // Check the hostname to make sure that it matches the shexp that
722 // is given in the common name of the certificate.
723 SECStatus
CERT_VerifyCertName(SecCertificateRef cert
, const char *hostname
)
725 fprintf(stderr
, "WARNING: CERT_VerifyCertName unimplemented\n");
730 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
731 ** verify a certificate by checking validity times against a certain time,
732 ** that we trust the issuer, and that the signature on the certificate is
734 ** "cert" the certificate to verify
735 ** "checkSig" only check signatures if true
738 CERT_VerifyCert(SecKeychainRef keychainOrArray
, SecCertificateRef cert
,
739 const CSSM_DATA_PTR
*otherCerts
, /* intermediates */
740 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef
*trustRef
)
742 CFMutableArrayRef certificates
= NULL
;
743 SecTrustRef trust
= NULL
;
745 int numOtherCerts
= SecCmsArrayCount((void **)otherCerts
);
749 * Certs to evaluate: first the leaf - our cert - then all the rest we know
750 * about. It's OK for otherCerts to contain a copy of the leaf.
752 certificates
= CFArrayCreateMutable(NULL
, numOtherCerts
+ 1, &kCFTypeArrayCallBacks
);
753 CFArrayAppendValue(certificates
, cert
);
754 for(dex
=0; dex
<numOtherCerts
; dex
++) {
755 SecCertificateRef intCert
;
757 rv
= SecCertificateCreateFromData(otherCerts
[dex
],
758 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
763 CFArrayAppendValue(certificates
, intCert
);
766 rv
= SecTrustCreateWithCertificates(certificates
, policies
, &trust
);
767 CFRelease(certificates
);
772 rv
= SecTrustSetKeychains(trust
, keychainOrArray
);
776 CFDateRef verifyDate
= CFDateCreate(NULL
, stime
);
777 rv
= SecTrustSetVerifyDate(trust
, verifyDate
);
778 CFRelease(verifyDate
);
788 SecTrustResultType result
;
789 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
790 rv
= SecTrustEvaluate(trust
, &result
);
796 case kSecTrustResultProceed
:
797 case kSecTrustResultUnspecified
:
798 /* TP Verification succeeded and there was either a UserTurst entry
799 telling us to procceed, or no user trust setting was specified. */
803 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
812 #if 0 /* debugging */
813 syslog(LOG_ERR
, "CERT_VerifyCert has failed with %d (input policies and output trust follow)",
815 if (policies
) CFShow(policies
);
816 if (trust
) CFShow(trust
);
821 CFRelease(certificates
);
826 CERT_PolicyForCertUsage(SECCertUsage certUsage
)
828 SecPolicyRef policy
= NULL
;
832 case certUsageSSLServerWithStepUp
:
834 case certUsageVerifyCA
:
838 case certUsageSSLClient
:
839 policy
= SecPolicyCreateSSL(false, NULL
);
841 case certUsageSSLServer
:
842 policy
= SecPolicyCreateSSL(true, NULL
);
844 case certUsageStatusResponder
:
845 policy
= SecPolicyCreateOCSPSigner();
847 case certUsageObjectSigner
:
848 case certUsageProtectedObjectSigner
:
849 case certUsageUserCertImport
:
850 case certUsageEmailSigner
:
851 case certUsageEmailRecipient
:
852 policy
= SecPolicyCreateBasicX509();