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
;
256 policy
= SecPolicyCreateBasicX509();
260 wrappedCert
= CERT_CertListFromCert(cert
);
261 status
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
);
265 /* SecTrustEvaluate will build us the best chain available using its heuristics.
266 * We'll ignore the trust result. */
267 status
= SecTrustEvaluate(trust
, NULL
);
270 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
272 /* If we weren't able to build a chain to a self-signed cert, warn. */
273 Boolean isSelfSigned
= false;
274 SecCertificateRef lastCert
= SecTrustGetCertificateAtIndex(trust
, count
- 1);
275 if (lastCert
&& (0 == SecCertificateIsSelfSigned(lastCert
, &isSelfSigned
)) && !isSelfSigned
) {
276 CFStringRef commonName
= NULL
;
277 (void)SecCertificateCopyCommonName(cert
, &commonName
);
278 fprintf(stderr
, "Warning: unable to build chain to self-signed root for signer \"%s\"",
279 commonName
? CFStringGetCStringPtr(commonName
, kCFStringEncodingUTF8
) : "");
280 if (commonName
) { CFRelease(commonName
); }
283 /* We don't drop the root if there is only 1 certificate in the chain. */
284 if (!includeRoot
&& count
> 1) { count
--; }
286 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
);
287 for(idx
= 0; idx
< count
; idx
++)
288 CFArrayAppendValue(certs
, SecTrustGetCertificateAtIndex(trust
, idx
));
294 CFRelease(wrappedCert
);
306 CFArrayRef
CERT_CertListFromCert(SecCertificateRef cert
)
308 const void *value
= cert
;
309 return cert
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
;
312 CFArrayRef
CERT_DupCertList(CFArrayRef oldList
)
318 // Extract a public key object from a SubjectPublicKeyInfo
319 SecPublicKeyRef
CERT_ExtractPublicKey(SecCertificateRef cert
)
321 SecPublicKeyRef keyRef
= NULL
;
322 SecCertificateCopyPublicKey(cert
,&keyRef
);
326 SECStatus
CERT_CheckCertUsage (SecCertificateRef cert
,unsigned char usage
)
329 // @@@ It's all good, it's ok.
333 // Find a certificate in the database by a email address
334 // "emailAddr" is the email address to look up
335 SecCertificateRef
CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray
, char *emailAddr
)
341 // Find a certificate in the database by a DER encoded certificate
342 // "derCert" is the DER encoded certificate
343 SecCertificateRef
CERT_FindCertByDERCert(SecKeychainRef keychainOrArray
, const SECItem
*derCert
)
345 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
346 SecCertificateRef cert
= NULL
;
349 rv
= SecCertificateCreateFromData(derCert
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
352 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
360 static int compareCssmData(
364 if((d1
== NULL
) || (d2
== NULL
)) {
367 if(d1
->Length
!= d2
->Length
) {
370 if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) {
376 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
377 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
378 SecCertificateRef
CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray
,
379 CSSM_DATA_PTR
*rawCerts
, CFArrayRef certList
, PRArenaPool
*pl
, const SecCmsIssuerAndSN
*issuerAndSN
)
381 SecCertificateRef certificate
= NULL
;
382 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
387 * First search the rawCerts array.
389 for(dex
=0; dex
<numRawCerts
; dex
++) {
390 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
391 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
396 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, certificate
);
398 CFRelease(certificate
);
401 if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
402 CFRelease(certificate
);
405 if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
406 CFRelease(certificate
);
410 dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate
);
414 /* Search the user-added certList */
415 if (certList
&& CFArrayGetCount(certList
)) {
416 CFIndex c
, count
= CFArrayGetCount(certList
);
417 for (c
= 0; c
< count
; c
++) {
418 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
);
419 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, cert
);
423 if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
426 if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
432 if (certificate
) { return certificate
; }
435 /* now search keychain(s) */
436 OSStatus status
= SecCertificateFindByIssuerAndSN(keychainOrArray
, &issuerAndSN
->derIssuer
,
437 &issuerAndSN
->serialNumber
, &certificate
);
440 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
447 SecCertificateRef
CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray
,
448 CSSM_DATA_PTR
*rawCerts
, CFArrayRef certList
, const SECItem
*subjKeyID
)
450 SecCertificateRef certificate
;
451 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
457 * First search the rawCerts array.
459 for(dex
=0; dex
<numRawCerts
; dex
++) {
461 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
462 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
467 if(CERT_FindSubjectKeyIDExtension(certificate
, &skid
)) {
468 CFRelease(certificate
);
472 match
= compareCssmData(subjKeyID
, &skid
);
473 SECITEM_FreeItem(&skid
, PR_FALSE
);
478 CFRelease(certificate
);
481 /* Search the user-added certList */
482 if (certList
&& CFArrayGetCount(certList
)) {
483 CFDataRef subjectkeyid
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subjKeyID
->Data
, subjKeyID
->Length
, kCFAllocatorNull
);
484 CFIndex c
, count
= CFArrayGetCount(certList
);
485 for (c
= 0; c
< count
; c
++) {
486 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
);
487 CFDataRef skid
= (cert
) ? SecCertificateGetSubjectKeyID(cert
) : NULL
;
488 if (skid
&& CFEqual(skid
, subjectkeyid
)) {
494 if (subjectkeyid
) { CFRelease(subjectkeyid
); };
495 if (certificate
) { return certificate
; }
498 /* now search keychain(s) */
499 OSStatus status
= SecCertificateFindBySubjectKeyID(keychainOrArray
,subjKeyID
,&certificate
);
502 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
509 static SecIdentityRef
510 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray
, SecCertificateRef CF_CONSUMED certificate
)
512 SecIdentityRef identity
= NULL
;
513 SecIdentityCreateWithCertificate(keychainOrArray
, certificate
, &identity
);
515 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT
);
517 CFRelease(certificate
);
524 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
526 SecCertificateRef certificate
= CERT_FindCertByIssuerAndSN(keychainOrArray
, NULL
, NULL
, NULL
, issuerAndSN
);
530 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
534 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray
, const SECItem
*subjKeyID
)
536 SecCertificateRef certificate
= CERT_FindCertBySubjectKeyID(keychainOrArray
, NULL
, NULL
, subjKeyID
);
540 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
543 // find the smime symmetric capabilities profile for a given cert
544 SECItem
*CERT_FindSMimeProfile(SecCertificateRef cert
)
549 // Return the decoded value of the subjectKeyID extension. The caller should
550 // free up the storage allocated in retItem->data.
551 SECStatus
CERT_FindSubjectKeyIDExtension (SecCertificateRef cert
, SECItem
*retItem
)
553 CSSM_DATA_PTR fieldValue
= NULL
;
555 CSSM_X509_EXTENSION
*extp
;
556 CE_SubjectKeyID
*skid
;
558 ortn
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
560 if(ortn
|| (fieldValue
== NULL
)) {
561 /* this cert doesn't have that extension */
564 extp
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
565 skid
= (CE_SubjectKeyID
*)extp
->value
.parsedValue
;
566 retItem
->Data
= (uint8
*)PORT_Alloc(skid
->Length
);
567 retItem
->Length
= skid
->Length
;
568 memmove(retItem
->Data
, skid
->Data
, retItem
->Length
);
569 SecCertificateReleaseFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
574 // Extract the issuer and serial number from a certificate
575 SecCmsIssuerAndSN
*CERT_GetCertIssuerAndSN(PRArenaPool
*pl
, SecCertificateRef cert
)
578 SecCmsIssuerAndSN
*certIssuerAndSN
;
579 SecCertificateRef certRef
;
580 SecCertificateRef itemImplRef
= NULL
;
581 CSSM_CL_HANDLE clHandle
;
582 CSSM_DATA_PTR serialNumber
= 0;
583 CSSM_DATA_PTR issuer
= 0;
584 CSSM_DATA certData
= {};
585 CSSM_HANDLE resultsHandle
= 0;
586 uint32 numberOfFields
= 0;
590 mark
= PORT_ArenaMark(pl
);
592 /* Retain input cert and get pointer to its data */
593 certRef
= (SecCertificateRef
)((cert
) ? CFRetain(cert
) : NULL
);
594 status
= SecCertificateGetData(certRef
, &certData
);
598 // Convert unified input certRef to itemImpl instance.
599 // note: must not release this instance while we're using its CL handle!
600 itemImplRef
= SecCertificateCreateItemImplInstance(cert
);
601 status
= SecCertificateGetCLHandle_legacy(itemImplRef
, &clHandle
);
603 status
= SecCertificateGetCLHandle(certRef
, &clHandle
);
608 /* Get the issuer from the cert. */
609 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
610 &OID_X509V1IssuerNameStd
, &resultsHandle
, &numberOfFields
, &issuer
);
612 if (result
|| numberOfFields
< 1)
614 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
618 /* Get the serialNumber from the cert. */
619 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
620 &CSSMOID_X509V1SerialNumber
, &resultsHandle
, &numberOfFields
, &serialNumber
);
621 if (result
|| numberOfFields
< 1)
623 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
627 /* Allocate the SecCmsIssuerAndSN struct. */
628 certIssuerAndSN
= (SecCmsIssuerAndSN
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
));
629 if (certIssuerAndSN
== NULL
)
632 /* Copy the issuer. */
633 certIssuerAndSN
->derIssuer
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, issuer
->Length
);
634 if (!certIssuerAndSN
->derIssuer
.Data
)
636 PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
->Data
, issuer
->Length
);
637 certIssuerAndSN
->derIssuer
.Length
= issuer
->Length
;
639 /* Copy the serialNumber. */
640 certIssuerAndSN
->serialNumber
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, serialNumber
->Length
);
641 if (!certIssuerAndSN
->serialNumber
.Data
)
643 PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
->Data
, serialNumber
->Length
);
644 certIssuerAndSN
->serialNumber
.Length
= serialNumber
->Length
;
646 PORT_ArenaUnmark(pl
, mark
);
648 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
649 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
652 CFRelease(itemImplRef
);
656 return certIssuerAndSN
;
659 PORT_ArenaRelease(pl
, mark
);
662 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
664 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
666 CFRelease(itemImplRef
);
670 PORT_SetError(SEC_INTERNAL_ONLY
);
674 // import a collection of certs into the temporary or permanent cert database
675 SECStatus
CERT_ImportCerts(SecKeychainRef keychain
, SECCertUsage usage
, unsigned int ncerts
,
676 SECItem
**derCerts
, SecCertificateRef
**retCerts
, Boolean keepCerts
, Boolean caOnly
, char *nickname
)
678 OSStatus rv
= SECFailure
;
679 SecCertificateRef cert
;
682 // @@@ Do something with caOnly and nickname
683 if (caOnly
|| nickname
)
686 for (ci
= 0; ci
< ncerts
; ++ci
)
688 rv
= SecCertificateCreateFromData(derCerts
[ci
], CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
693 rv
= SecCertificateAddToKeychain(cert
, keychain
);
696 if (rv
== errKCDuplicateItem
)
718 SECStatus
CERT_SaveSMimeProfile(SecCertificateRef cert
, SECItem
*emailProfile
,SECItem
*profileTime
)
720 fprintf(stderr
, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
724 // Check the hostname to make sure that it matches the shexp that
725 // is given in the common name of the certificate.
726 SECStatus
CERT_VerifyCertName(SecCertificateRef cert
, const char *hostname
)
728 fprintf(stderr
, "WARNING: CERT_VerifyCertName unimplemented\n");
733 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
734 ** verify a certificate by checking validity times against a certain time,
735 ** that we trust the issuer, and that the signature on the certificate is
737 ** "cert" the certificate to verify
738 ** "checkSig" only check signatures if true
741 CERT_VerifyCert(SecKeychainRef keychainOrArray
, SecCertificateRef cert
,
742 const CSSM_DATA_PTR
*otherCerts
, /* intermediates */
743 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef
*trustRef
)
745 CFMutableArrayRef certificates
= NULL
;
746 SecTrustRef trust
= NULL
;
748 int numOtherCerts
= SecCmsArrayCount((void **)otherCerts
);
752 * Certs to evaluate: first the leaf - our cert - then all the rest we know
753 * about. It's OK for otherCerts to contain a copy of the leaf.
755 certificates
= CFArrayCreateMutable(NULL
, numOtherCerts
+ 1, &kCFTypeArrayCallBacks
);
756 CFArrayAppendValue(certificates
, cert
);
757 for(dex
=0; dex
<numOtherCerts
; dex
++) {
758 SecCertificateRef intCert
;
760 rv
= SecCertificateCreateFromData(otherCerts
[dex
],
761 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
766 CFArrayAppendValue(certificates
, intCert
);
769 rv
= SecTrustCreateWithCertificates(certificates
, policies
, &trust
);
770 CFRelease(certificates
);
775 rv
= SecTrustSetKeychains(trust
, keychainOrArray
);
779 CFDateRef verifyDate
= CFDateCreate(NULL
, stime
);
780 rv
= SecTrustSetVerifyDate(trust
, verifyDate
);
781 CFRelease(verifyDate
);
791 SecTrustResultType result
;
792 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
793 rv
= SecTrustEvaluate(trust
, &result
);
799 case kSecTrustResultProceed
:
800 case kSecTrustResultUnspecified
:
801 /* TP Verification succeeded and there was either a UserTurst entry
802 telling us to procceed, or no user trust setting was specified. */
806 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
815 #if 0 /* debugging */
816 syslog(LOG_ERR
, "CERT_VerifyCert has failed with %d (input policies and output trust follow)",
818 if (policies
) CFShow(policies
);
819 if (trust
) CFShow(trust
);
824 CFRelease(certificates
);
829 CERT_PolicyForCertUsage(SECCertUsage certUsage
)
831 SecPolicyRef policy
= NULL
;
835 case certUsageSSLServerWithStepUp
:
837 case certUsageVerifyCA
:
841 case certUsageSSLClient
:
842 policy
= SecPolicyCreateSSL(false, NULL
);
844 case certUsageSSLServer
:
845 policy
= SecPolicyCreateSSL(true, NULL
);
847 case certUsageStatusResponder
:
848 policy
= SecPolicyCreateOCSPSigner();
850 case certUsageObjectSigner
:
851 case certUsageProtectedObjectSigner
:
852 case certUsageUserCertImport
:
853 case certUsageEmailSigner
:
854 case certUsageEmailRecipient
:
855 policy
= SecPolicyCreateBasicX509();