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/SecPolicySearch.h>
38 #include <Security/oidsalg.h>
39 #include <Security/cssmapi.h>
40 #include <Security/oidscert.h>
41 #include <Security/oidscert.h>
43 /* for errKCDuplicateItem */
44 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
48 #define dprintf(args...) printf(args)
50 #define dprintf(args...)
53 /* @@@ Remove this once it's back in the appropriate header. */
54 static const uint8 X509V1IssuerNameStd
[] = {INTEL_X509V3_CERT_R08
, 23};
55 static const CSSM_OID OID_X509V1IssuerNameStd
= {INTEL_X509V3_CERT_R08_LENGTH
+1, (uint8
*)X509V1IssuerNameStd
};
58 * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case
59 * insensitive and we're supposed to ignore leading and trailing
60 * whitespace, and collapse multiple whitespace characters into one.
63 CERT_NormalizeString(CSSM_DATA_PTR string
)
65 char *pD
, *pCh
, *pEos
;
70 pD
= pCh
= (char *)string
->Data
;
71 pEos
= pCh
+ string
->Length
- 1;
73 /* Strip trailing NULL terminators */
77 /* Remove trailing spaces */
81 /* Point to one past last non-space character */
84 /* skip all leading whitespace */
85 while(isspace(*pCh
) && (pCh
< pEos
))
88 /* Eliminate multiple whitespace and convent to upper case.
89 * pCh points to first non-white char.
90 * pD still points to start of string. */
97 /* skip 'til next nonwhite */
98 while(isspace(*pCh
) && (pCh
< pEos
))
103 string
->Length
= pD
- (char *)string
->Data
;
107 * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case
108 * insensitive and we're supposed to ignore leading and trailing
109 * whitespace, and collapse multiple whitespace characters into one.
111 * Incoming NSS_Name is assumed to be entirely within specifed coder's
112 * address space; we'll be munging some of that and possibly replacing
113 * some pointers with others allocated from the same space.
116 CERT_NormalizeX509NameNSS(NSS_Name
*nssName
)
120 for (rdn
= *nssName
->rdns
; rdn
; ++rdn
)
123 for (attr
= *rdn
->atvs
; attr
; ++attr
)
126 * attr->value is an ASN_ANY containing an encoded
127 * string. We only normalize Prinatable String types.
128 * If we find one, decode it, normalize it, encode the
129 * result, and put the encoding back in attr->value.
130 * We temporarily "leak" the original string, which only
131 * has a lifetime of the incoming SecNssCoder.
133 NSS_TaggedItem
*attrVal
= &attr
->value
;
134 if(attrVal
->tag
!= SEC_ASN1_PRINTABLE_STRING
)
137 CERT_NormalizeString(&attrVal
->item
);
142 SecCertificateRef
CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray
, char *name
)
144 SecCertificateRef certificate
;
145 OSStatus status
=SecCertificateFindByEmail(keychainOrArray
,name
,&certificate
);
146 return status
==noErr
?certificate
:NULL
;
149 SecPublicKeyRef
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
)
155 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
)
160 SecPublicKeyRef
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
)
166 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
)
171 void CERT_DestroyCertificate(SecCertificateRef cert
)
176 SecCertificateRef
CERT_DupCertificate(SecCertificateRef cert
)
182 SecIdentityRef
CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray
,
183 char *nickname
, SECCertUsage usage
, Boolean validOnly
, void *proto_win
)
185 SecIdentityRef identityRef
= NULL
;
186 SecCertificateRef cert
= CERT_FindCertByNicknameOrEmailAddr(keychainOrArray
, nickname
);
190 SecIdentityCreateWithCertificate(keychainOrArray
, cert
, &identityRef
);
196 SecCertificateRef
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
,
197 char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
)
199 SecItemClass itemClass
= kSecCertificateItemClass
;
200 SecKeychainSearchRef searchRef
;
201 SecKeychainItemRef itemRef
= NULL
;
203 SecKeychainAttribute attrs
[1];
204 const char *serialNumber
= "12345678";
205 // const SecKeychainAttributeList attrList;
207 attrs
[1].tag
= kSecLabelItemAttr
;
208 attrs
[1].length
= strlen(nickname
)+1;
209 attrs
[1].data
= nickname
;
211 attrs
[1].tag
= kSecSerialNumberItemAttr
;
212 attrs
[1].length
= (UInt32
)strlen(serialNumber
)+1;
213 attrs
[1].data
= (uint8
*)serialNumber
;
215 SecKeychainAttributeList attrList
= { 0, attrs
};
217 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
,itemClass
,&attrList
,&searchRef
);
220 printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status
);
223 status
= SecKeychainSearchCopyNext(searchRef
,&itemRef
);
225 printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status
);
226 CFRelease(searchRef
);
227 return (SecCertificateRef
)itemRef
;
231 startNewClass(X509Certificate)
232 CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
233 CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
234 PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
235 Alias, kSecAlias, "Alias", 0, NULL, BLOB)
236 Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
237 Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
238 SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
239 SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
240 PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
244 CFArrayRef
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
)
246 SecPolicySearchRef searchRef
= NULL
;
247 SecPolicyRef policy
= NULL
;
248 CFArrayRef wrappedCert
= NULL
;
249 SecTrustRef trust
= NULL
;
250 CFArrayRef certChain
= NULL
;
251 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
;
252 CFDataRef actionData
= NULL
;
258 status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, &CSSMOID_APPLE_X509_BASIC
, NULL
, &searchRef
);
261 status
= SecPolicySearchCopyNext(searchRef
, &policy
);
265 wrappedCert
= CERT_CertListFromCert(cert
);
266 status
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
);
270 /* Tell SecTrust that we don't care if any certs in the chain have expired,
271 nor do we want to stop when encountering a cert with a trust setting;
272 we always want to build the full chain.
274 CSSM_APPLE_TP_ACTION_DATA localActionData
= {
275 CSSM_APPLE_TP_ACTION_VERSION
,
276 CSSM_TP_ACTION_ALLOW_EXPIRED
| CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT
278 actionData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)&localActionData
, sizeof(localActionData
), kCFAllocatorNull
);
282 status
= SecTrustSetParameters(trust
, CSSM_TP_ACTION_DEFAULT
, actionData
);
286 status
= SecTrustEvaluate(trust
, NULL
);
290 status
= SecTrustGetResult(trust
, NULL
, &certChain
, &statusChain
);
294 /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */
295 if (!includeRoot
&& CFArrayGetCount(certChain
) > 1)
297 CFMutableArrayRef subChain
= CFArrayCreateMutableCopy(NULL
, 0, certChain
);
298 CFRelease(certChain
);
299 certChain
= subChain
;
301 CFArrayRemoveValueAtIndex(subChain
, CFArrayGetCount(subChain
) - 1);
306 CFRelease(searchRef
);
310 CFRelease(wrappedCert
);
314 CFRelease(actionData
);
315 if (certChain
&& status
)
317 CFRelease(certChain
);
324 CFArrayRef
CERT_CertListFromCert(SecCertificateRef cert
)
326 const void *value
= cert
;
327 return cert
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
;
330 CFArrayRef
CERT_DupCertList(CFArrayRef oldList
)
336 // Extract a public key object from a SubjectPublicKeyInfo
337 SecPublicKeyRef
CERT_ExtractPublicKey(SecCertificateRef cert
)
339 SecPublicKeyRef keyRef
= NULL
;
340 SecCertificateCopyPublicKey(cert
,&keyRef
);
344 SECStatus
CERT_CheckCertUsage (SecCertificateRef cert
,unsigned char usage
)
347 // @@@ It's all good, it's ok.
351 // Find a certificate in the database by a email address
352 // "emailAddr" is the email address to look up
353 SecCertificateRef
CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray
, char *emailAddr
)
359 // Find a certificate in the database by a DER encoded certificate
360 // "derCert" is the DER encoded certificate
361 SecCertificateRef
CERT_FindCertByDERCert(SecKeychainRef keychainOrArray
, const SECItem
*derCert
)
363 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
364 SecCertificateRef cert
= NULL
;
367 rv
= SecCertificateCreateFromData(derCert
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
370 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
378 static int compareCssmData(
382 if((d1
== NULL
) || (d2
== NULL
)) {
385 if(d1
->Length
!= d2
->Length
) {
388 if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) {
394 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
395 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
396 SecCertificateRef
CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray
,
397 CSSM_DATA_PTR
*rawCerts
, PRArenaPool
*pl
, const SecCmsIssuerAndSN
*issuerAndSN
)
399 SecCertificateRef certificate
;
400 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
405 * First search the rawCerts array.
407 for(dex
=0; dex
<numRawCerts
; dex
++) {
408 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
409 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
414 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, certificate
);
416 CFRelease(certificate
);
419 if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
420 CFRelease(certificate
);
423 if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
424 CFRelease(certificate
);
428 dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", 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
, 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
= compareCssmData(subjKeyID
, &skid
);
470 SECITEM_FreeItem(&skid
, PR_FALSE
);
475 CFRelease(certificate
);
478 /* now search keychain(s) */
479 OSStatus status
= SecCertificateFindBySubjectKeyID(keychainOrArray
,subjKeyID
,&certificate
);
482 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
489 static SecIdentityRef
490 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray
, SecCertificateRef certificate
)
492 SecIdentityRef identity
= NULL
;
493 SecIdentityCreateWithCertificate(keychainOrArray
, certificate
, &identity
);
495 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT
);
501 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
503 SecCertificateRef certificate
= CERT_FindCertByIssuerAndSN(keychainOrArray
, NULL
, NULL
, issuerAndSN
);
507 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
511 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray
, const SECItem
*subjKeyID
)
513 SecCertificateRef certificate
= CERT_FindCertBySubjectKeyID(keychainOrArray
, NULL
, subjKeyID
);
517 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
520 // find the smime symmetric capabilities profile for a given cert
521 SECItem
*CERT_FindSMimeProfile(SecCertificateRef cert
)
526 // Return the decoded value of the subjectKeyID extension. The caller should
527 // free up the storage allocated in retItem->data.
528 SECStatus
CERT_FindSubjectKeyIDExtension (SecCertificateRef cert
, SECItem
*retItem
)
530 CSSM_DATA_PTR fieldValue
= NULL
;
532 CSSM_X509_EXTENSION
*extp
;
533 CE_SubjectKeyID
*skid
;
535 ortn
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
537 if(ortn
|| (fieldValue
== NULL
)) {
538 /* this cert doesn't have that extension */
541 extp
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
542 skid
= (CE_SubjectKeyID
*)extp
->value
.parsedValue
;
543 retItem
->Data
= (uint8
*)PORT_Alloc(skid
->Length
);
544 retItem
->Length
= skid
->Length
;
545 memmove(retItem
->Data
, skid
->Data
, retItem
->Length
);
546 SecCertificateReleaseFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
551 // Extract the issuer and serial number from a certificate
552 SecCmsIssuerAndSN
*CERT_GetCertIssuerAndSN(PRArenaPool
*pl
, SecCertificateRef cert
)
555 SecCmsIssuerAndSN
*certIssuerAndSN
;
556 CSSM_CL_HANDLE clHandle
;
557 CSSM_DATA_PTR serialNumber
= 0;
558 CSSM_DATA_PTR issuer
= 0;
559 CSSM_DATA certData
= {};
560 CSSM_HANDLE resultsHandle
= 0;
561 uint32 numberOfFields
= 0;
565 mark
= PORT_ArenaMark(pl
);
567 status
= SecCertificateGetCLHandle(cert
, &clHandle
);
570 status
= SecCertificateGetData(cert
, &certData
);
574 /* Get the issuer from the cert. */
575 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
576 &OID_X509V1IssuerNameStd
, &resultsHandle
, &numberOfFields
, &issuer
);
578 if (result
|| numberOfFields
< 1)
580 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
585 /* Get the serialNumber from the cert. */
586 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
587 &CSSMOID_X509V1SerialNumber
, &resultsHandle
, &numberOfFields
, &serialNumber
);
588 if (result
|| numberOfFields
< 1)
590 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
594 /* Allocate the SecCmsIssuerAndSN struct. */
595 certIssuerAndSN
= (SecCmsIssuerAndSN
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
));
596 if (certIssuerAndSN
== NULL
)
599 /* Copy the issuer. */
600 certIssuerAndSN
->derIssuer
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, issuer
->Length
);
601 if (!certIssuerAndSN
->derIssuer
.Data
)
603 PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
->Data
, issuer
->Length
);
604 certIssuerAndSN
->derIssuer
.Length
= issuer
->Length
;
606 /* Copy the serialNumber. */
607 certIssuerAndSN
->serialNumber
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, serialNumber
->Length
);
608 if (!certIssuerAndSN
->serialNumber
.Data
)
610 PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
->Data
, serialNumber
->Length
);
611 certIssuerAndSN
->serialNumber
.Length
= serialNumber
->Length
;
613 PORT_ArenaUnmark(pl
, mark
);
615 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
616 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
618 return certIssuerAndSN
;
621 PORT_ArenaRelease(pl
, mark
);
624 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
626 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
628 PORT_SetError(SEC_INTERNAL_ONLY
);
632 // import a collection of certs into the temporary or permanent cert database
633 SECStatus
CERT_ImportCerts(SecKeychainRef keychain
, SECCertUsage usage
, unsigned int ncerts
,
634 SECItem
**derCerts
, SecCertificateRef
**retCerts
, Boolean keepCerts
, Boolean caOnly
, char *nickname
)
636 OSStatus rv
= SECFailure
;
637 SecCertificateRef cert
;
640 // @@@ Do something with caOnly and nickname
641 if (caOnly
|| nickname
)
644 for (ci
= 0; ci
< ncerts
; ++ci
)
646 rv
= SecCertificateCreateFromData(derCerts
[ci
], CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
651 rv
= SecCertificateAddToKeychain(cert
, keychain
);
654 if (rv
== errKCDuplicateItem
)
676 SECStatus
CERT_SaveSMimeProfile(SecCertificateRef cert
, SECItem
*emailProfile
,SECItem
*profileTime
)
678 fprintf(stderr
, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
682 // Check the hostname to make sure that it matches the shexp that
683 // is given in the common name of the certificate.
684 SECStatus
CERT_VerifyCertName(SecCertificateRef cert
, const char *hostname
)
686 fprintf(stderr
, "WARNING: CERT_VerifyCertName unimplemented\n");
691 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
692 ** verify a certificate by checking validity times against a certain time,
693 ** that we trust the issuer, and that the signature on the certificate is
695 ** "cert" the certificate to verify
696 ** "checkSig" only check signatures if true
699 CERT_VerifyCert(SecKeychainRef keychainOrArray
, SecCertificateRef cert
,
700 const CSSM_DATA_PTR
*otherCerts
, /* intermediates */
701 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef
*trustRef
)
703 CFMutableArrayRef certificates
= NULL
;
704 SecTrustRef trust
= NULL
;
706 int numOtherCerts
= SecCmsArrayCount((void **)otherCerts
);
710 * Certs to evaluate: first the leaf - our cert - then all the rest we know
711 * about. It's OK for otherCerts to contain a copy of the leaf.
713 certificates
= CFArrayCreateMutable(NULL
, numOtherCerts
+ 1, &kCFTypeArrayCallBacks
);
714 CFArrayAppendValue(certificates
, cert
);
715 for(dex
=0; dex
<numOtherCerts
; dex
++) {
716 SecCertificateRef intCert
;
718 rv
= SecCertificateCreateFromData(otherCerts
[dex
],
719 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
724 CFArrayAppendValue(certificates
, intCert
);
727 rv
= SecTrustCreateWithCertificates(certificates
, policies
, &trust
);
728 CFRelease(certificates
);
733 rv
= SecTrustSetKeychains(trust
, keychainOrArray
);
737 CFDateRef verifyDate
= CFDateCreate(NULL
, stime
);
738 rv
= SecTrustSetVerifyDate(trust
, verifyDate
);
739 CFRelease(verifyDate
);
749 SecTrustResultType result
;
750 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
751 rv
= SecTrustEvaluate(trust
, &result
);
757 case kSecTrustResultProceed
:
758 case kSecTrustResultUnspecified
:
759 /* TP Verification succeeded and there was either a UserTurst entry
760 telling us to procceed, or no user trust setting was specified. */
764 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
776 CFRelease(certificates
);
781 CERT_PolicyForCertUsage(SECCertUsage certUsage
)
783 SecPolicySearchRef search
= NULL
;
784 SecPolicyRef policy
= NULL
;
785 const CSSM_OID
*policyOID
;
790 case certUsageSSLServerWithStepUp
:
792 case certUsageVerifyCA
:
796 case certUsageSSLClient
:
797 case certUsageSSLServer
:
798 policyOID
= &CSSMOID_APPLE_TP_SSL
;
800 case certUsageUserCertImport
:
801 policyOID
= &CSSMOID_APPLE_TP_CSR_GEN
;
803 case certUsageStatusResponder
:
804 policyOID
= &CSSMOID_APPLE_TP_REVOCATION_OCSP
;
806 case certUsageObjectSigner
:
807 case certUsageProtectedObjectSigner
:
808 policyOID
= &CSSMOID_APPLE_ISIGN
;
810 case certUsageEmailSigner
:
811 case certUsageEmailRecipient
:
812 policyOID
= &CSSMOID_APPLE_X509_BASIC
;
817 rv
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, policyOID
, NULL
, &search
);
821 rv
= SecPolicySearchCopyNext(search
, &policy
);
826 if(search
) CFRelease(search
);