5 * Created by john on Wed Mar 12 2003.
6 * Copyright (c) 2003 __MyCompanyName__. All rights reserved.
14 #include <security_asn1/secerr.h>
15 #include <Security/SecKeychain.h>
16 #include <Security/SecKeychainItem.h>
17 #include <Security/SecKeychainSearch.h>
18 #include <Security/SecIdentity.h>
19 #include <Security/SecIdentityPriv.h>
20 #include <Security/SecIdentitySearch.h>
21 #include <Security/SecCertificatePriv.h>
22 #include <Security/SecPolicySearch.h>
23 #include <Security/oidsalg.h>
24 #include <Security/cssmapi.h>
25 #include <Security/oidscert.h>
26 #include <Security/oidscert.h>
28 /* for errKCDuplicateItem */
29 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
33 #define dprintf(args...) printf(args)
35 #define dprintf(args...)
38 /* @@@ Remove this once it's back in the appropriate header. */
39 static const uint8 X509V1IssuerNameStd
[] = {INTEL_X509V3_CERT_R08
, 23};
40 static const CSSM_OID OID_X509V1IssuerNameStd
= {INTEL_X509V3_CERT_R08_LENGTH
+1, (uint8
*)X509V1IssuerNameStd
};
43 * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case
44 * insensitive and we're supposed to ignore leading and trailing
45 * whitespace, and collapse multiple whitespace characters into one.
48 CERT_NormalizeString(CSSM_DATA_PTR string
)
50 char *pD
, *pCh
, *pEos
;
55 pD
= pCh
= (char *)string
->Data
;
56 pEos
= pCh
+ string
->Length
- 1;
58 /* Strip trailing NULL terminators */
62 /* Remove trailing spaces */
66 /* Point to one past last non-space character */
69 /* skip all leading whitespace */
70 while(isspace(*pCh
) && (pCh
< pEos
))
73 /* Eliminate multiple whitespace and convent to upper case.
74 * pCh points to first non-white char.
75 * pD still points to start of string. */
82 /* skip 'til next nonwhite */
83 while(isspace(*pCh
) && (pCh
< pEos
))
88 string
->Length
= pD
- (char *)string
->Data
;
92 * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case
93 * insensitive and we're supposed to ignore leading and trailing
94 * whitespace, and collapse multiple whitespace characters into one.
96 * Incoming NSS_Name is assumed to be entirely within specifed coder's
97 * address space; we'll be munging some of that and possibly replacing
98 * some pointers with others allocated from the same space.
101 CERT_NormalizeX509NameNSS(NSS_Name
*nssName
)
105 for (rdn
= *nssName
->rdns
; rdn
; ++rdn
)
108 for (attr
= *rdn
->atvs
; attr
; ++attr
)
111 * attr->value is an ASN_ANY containing an encoded
112 * string. We only normalize Prinatable String types.
113 * If we find one, decode it, normalize it, encode the
114 * result, and put the encoding back in attr->value.
115 * We temporarily "leak" the original string, which only
116 * has a lifetime of the incoming SecNssCoder.
118 NSS_TaggedItem
*attrVal
= &attr
->value
;
119 if(attrVal
->tag
!= SEC_ASN1_PRINTABLE_STRING
)
122 CERT_NormalizeString(&attrVal
->item
);
127 SecCertificateRef
CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray
, char *name
)
129 SecCertificateRef certificate
;
130 OSStatus status
=SecCertificateFindByEmail(keychainOrArray
,name
,&certificate
);
131 return status
==noErr
?certificate
:NULL
;
134 SecPublicKeyRef
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
)
140 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
)
145 SecPublicKeyRef
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
)
151 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
)
156 void CERT_DestroyCertificate(SecCertificateRef cert
)
161 SecCertificateRef
CERT_DupCertificate(SecCertificateRef cert
)
167 SecIdentityRef
CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray
,
168 char *nickname
, SECCertUsage usage
, Boolean validOnly
, void *proto_win
)
170 SecIdentityRef identityRef
= NULL
;
171 SecCertificateRef cert
= CERT_FindCertByNicknameOrEmailAddr(keychainOrArray
, nickname
);
175 SecIdentityCreateWithCertificate(keychainOrArray
, cert
, &identityRef
);
181 SecCertificateRef
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
,
182 char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
)
184 SecItemClass itemClass
= kSecCertificateItemClass
;
185 SecKeychainSearchRef searchRef
;
186 SecKeychainItemRef itemRef
= NULL
;
188 SecKeychainAttribute attrs
[1];
189 const char *serialNumber
= "12345678";
190 // const SecKeychainAttributeList attrList;
192 attrs
[1].tag
= kSecLabelItemAttr
;
193 attrs
[1].length
= strlen(nickname
)+1;
194 attrs
[1].data
= nickname
;
196 attrs
[1].tag
= kSecSerialNumberItemAttr
;
197 attrs
[1].length
= (UInt32
)strlen(serialNumber
)+1;
198 attrs
[1].data
= (uint8
*)serialNumber
;
200 SecKeychainAttributeList attrList
= { 0, attrs
};
202 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
,itemClass
,&attrList
,&searchRef
);
205 printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status
);
208 status
= SecKeychainSearchCopyNext(searchRef
,&itemRef
);
210 printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status
);
211 CFRelease(searchRef
);
212 return (SecCertificateRef
)itemRef
;
216 startNewClass(X509Certificate)
217 CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
218 CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
219 PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
220 Alias, kSecAlias, "Alias", 0, NULL, BLOB)
221 Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
222 Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
223 SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
224 SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
225 PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
229 CFArrayRef
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
)
231 SecPolicySearchRef searchRef
= NULL
;
232 SecPolicyRef policy
= NULL
;
233 CFArrayRef wrappedCert
= NULL
;
234 SecTrustRef trust
= NULL
;
235 CFArrayRef certChain
= NULL
;
236 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
;
237 CFDataRef actionData
= NULL
;
243 status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, &CSSMOID_APPLE_X509_BASIC
, NULL
, &searchRef
);
246 status
= SecPolicySearchCopyNext(searchRef
, &policy
);
250 wrappedCert
= CERT_CertListFromCert(cert
);
251 status
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
);
255 /* Tell SecTrust that we don't care if any certs in the chain have expired,
256 nor do we want to stop when encountering a cert with a trust setting;
257 we always want to build the full chain.
259 CSSM_APPLE_TP_ACTION_DATA localActionData
= {
260 CSSM_APPLE_TP_ACTION_VERSION
,
261 CSSM_TP_ACTION_ALLOW_EXPIRED
| CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT
263 actionData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)&localActionData
, sizeof(localActionData
), kCFAllocatorNull
);
267 status
= SecTrustSetParameters(trust
, CSSM_TP_ACTION_DEFAULT
, actionData
);
271 status
= SecTrustEvaluate(trust
, NULL
);
275 status
= SecTrustGetResult(trust
, NULL
, &certChain
, &statusChain
);
279 /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */
280 if (!includeRoot
&& CFArrayGetCount(certChain
) > 1)
282 CFMutableArrayRef subChain
= CFArrayCreateMutableCopy(NULL
, 0, certChain
);
283 CFRelease(certChain
);
284 certChain
= subChain
;
286 CFArrayRemoveValueAtIndex(subChain
, CFArrayGetCount(subChain
) - 1);
291 CFRelease(searchRef
);
295 CFRelease(wrappedCert
);
299 CFRelease(actionData
);
300 if (certChain
&& status
)
302 CFRelease(certChain
);
309 CFArrayRef
CERT_CertListFromCert(SecCertificateRef cert
)
311 const void *value
= cert
;
312 return cert
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
;
315 CFArrayRef
CERT_DupCertList(CFArrayRef oldList
)
321 // Extract a public key object from a SubjectPublicKeyInfo
322 SecPublicKeyRef
CERT_ExtractPublicKey(SecCertificateRef cert
)
324 SecPublicKeyRef keyRef
= NULL
;
325 SecCertificateCopyPublicKey(cert
,&keyRef
);
329 SECStatus
CERT_CheckCertUsage (SecCertificateRef cert
,unsigned char usage
)
332 // @@@ It's all good, it's ok.
336 // Find a certificate in the database by a email address
337 // "emailAddr" is the email address to look up
338 SecCertificateRef
CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray
, char *emailAddr
)
344 // Find a certificate in the database by a DER encoded certificate
345 // "derCert" is the DER encoded certificate
346 SecCertificateRef
CERT_FindCertByDERCert(SecKeychainRef keychainOrArray
, const SECItem
*derCert
)
348 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
349 SecCertificateRef cert
= NULL
;
352 rv
= SecCertificateCreateFromData(derCert
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
355 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
363 static int compareCssmData(
367 if((d1
== NULL
) || (d2
== NULL
)) {
370 if(d1
->Length
!= d2
->Length
) {
373 if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) {
379 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
380 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
381 SecCertificateRef
CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray
,
382 CSSM_DATA_PTR
*rawCerts
, PRArenaPool
*pl
, const SecCmsIssuerAndSN
*issuerAndSN
)
384 SecCertificateRef certificate
;
385 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
390 * First search the rawCerts array.
392 for(dex
=0; dex
<numRawCerts
; dex
++) {
393 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
394 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
399 SecCmsIssuerAndSN
*isn
= CERT_GetCertIssuerAndSN(pl
, certificate
);
401 CFRelease(certificate
);
404 if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) {
405 CFRelease(certificate
);
408 if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) {
409 CFRelease(certificate
);
413 dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate
);
417 /* now search keychain(s) */
418 OSStatus status
= SecCertificateFindByIssuerAndSN(keychainOrArray
, &issuerAndSN
->derIssuer
,
419 &issuerAndSN
->serialNumber
, &certificate
);
422 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
429 SecCertificateRef
CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray
,
430 CSSM_DATA_PTR
*rawCerts
, const SECItem
*subjKeyID
)
432 SecCertificateRef certificate
;
433 int numRawCerts
= SecCmsArrayCount((void **)rawCerts
);
439 * First search the rawCerts array.
441 for(dex
=0; dex
<numRawCerts
; dex
++) {
443 ortn
= SecCertificateCreateFromData(rawCerts
[dex
],
444 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
449 if(CERT_FindSubjectKeyIDExtension(certificate
, &skid
)) {
450 CFRelease(certificate
);
454 match
= compareCssmData(subjKeyID
, &skid
);
455 SECITEM_FreeItem(&skid
, PR_FALSE
);
460 CFRelease(certificate
);
463 /* now search keychain(s) */
464 OSStatus status
= SecCertificateFindBySubjectKeyID(keychainOrArray
,subjKeyID
,&certificate
);
467 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
);
474 static SecIdentityRef
475 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray
, SecCertificateRef certificate
)
477 SecIdentityRef identity
= NULL
;
478 SecIdentityCreateWithCertificate(keychainOrArray
, certificate
, &identity
);
480 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT
);
486 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
488 SecCertificateRef certificate
= CERT_FindCertByIssuerAndSN(keychainOrArray
, NULL
, NULL
, issuerAndSN
);
492 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
496 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray
, const SECItem
*subjKeyID
)
498 SecCertificateRef certificate
= CERT_FindCertBySubjectKeyID(keychainOrArray
, NULL
, subjKeyID
);
502 return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
);
505 // find the smime symmetric capabilities profile for a given cert
506 SECItem
*CERT_FindSMimeProfile(SecCertificateRef cert
)
511 // Return the decoded value of the subjectKeyID extension. The caller should
512 // free up the storage allocated in retItem->data.
513 SECStatus
CERT_FindSubjectKeyIDExtension (SecCertificateRef cert
, SECItem
*retItem
)
515 CSSM_DATA_PTR fieldValue
= NULL
;
517 CSSM_X509_EXTENSION
*extp
;
518 CE_SubjectKeyID
*skid
;
520 ortn
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
522 if(ortn
|| (fieldValue
== NULL
)) {
523 /* this cert doesn't have that extension */
526 extp
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
527 skid
= (CE_SubjectKeyID
*)extp
->value
.parsedValue
;
528 retItem
->Data
= (uint8
*)PORT_Alloc(skid
->Length
);
529 retItem
->Length
= skid
->Length
;
530 memmove(retItem
->Data
, skid
->Data
, retItem
->Length
);
531 SecCertificateReleaseFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
,
536 // Extract the issuer and serial number from a certificate
537 SecCmsIssuerAndSN
*CERT_GetCertIssuerAndSN(PRArenaPool
*pl
, SecCertificateRef cert
)
540 SecCmsIssuerAndSN
*certIssuerAndSN
;
541 CSSM_CL_HANDLE clHandle
;
542 CSSM_DATA_PTR serialNumber
= 0;
543 CSSM_DATA_PTR issuer
= 0;
544 CSSM_DATA certData
= {};
545 CSSM_HANDLE resultsHandle
= 0;
546 uint32 numberOfFields
= 0;
550 mark
= PORT_ArenaMark(pl
);
552 status
= SecCertificateGetCLHandle(cert
, &clHandle
);
555 status
= SecCertificateGetData(cert
, &certData
);
559 /* Get the issuer from the cert. */
560 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
561 &OID_X509V1IssuerNameStd
, &resultsHandle
, &numberOfFields
, &issuer
);
563 if (result
|| numberOfFields
< 1)
565 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
570 /* Get the serialNumber from the cert. */
571 result
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
,
572 &CSSMOID_X509V1SerialNumber
, &resultsHandle
, &numberOfFields
, &serialNumber
);
573 if (result
|| numberOfFields
< 1)
575 result
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
);
579 /* Allocate the SecCmsIssuerAndSN struct. */
580 certIssuerAndSN
= (SecCmsIssuerAndSN
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
));
581 if (certIssuerAndSN
== NULL
)
584 /* Copy the issuer. */
585 certIssuerAndSN
->derIssuer
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, issuer
->Length
);
586 if (!certIssuerAndSN
->derIssuer
.Data
)
588 PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
->Data
, issuer
->Length
);
589 certIssuerAndSN
->derIssuer
.Length
= issuer
->Length
;
591 /* Copy the serialNumber. */
592 certIssuerAndSN
->serialNumber
.Data
= (uint8
*) PORT_ArenaAlloc(pl
, serialNumber
->Length
);
593 if (!certIssuerAndSN
->serialNumber
.Data
)
595 PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
->Data
, serialNumber
->Length
);
596 certIssuerAndSN
->serialNumber
.Length
= serialNumber
->Length
;
598 PORT_ArenaUnmark(pl
, mark
);
600 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
601 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
603 return certIssuerAndSN
;
606 PORT_ArenaRelease(pl
, mark
);
609 CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
);
611 CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
);
613 PORT_SetError(SEC_INTERNAL_ONLY
);
617 // import a collection of certs into the temporary or permanent cert database
618 SECStatus
CERT_ImportCerts(SecKeychainRef keychain
, SECCertUsage usage
, unsigned int ncerts
,
619 SECItem
**derCerts
, SecCertificateRef
**retCerts
, Boolean keepCerts
, Boolean caOnly
, char *nickname
)
621 OSStatus rv
= SECFailure
;
622 SecCertificateRef cert
;
625 // @@@ Do something with caOnly and nickname
626 if (caOnly
|| nickname
)
629 for (ci
= 0; ci
< ncerts
; ++ci
)
631 rv
= SecCertificateCreateFromData(derCerts
[ci
], CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
);
636 rv
= SecCertificateAddToKeychain(cert
, keychain
);
639 if (rv
== errKCDuplicateItem
)
661 SECStatus
CERT_SaveSMimeProfile(SecCertificateRef cert
, SECItem
*emailProfile
,SECItem
*profileTime
)
663 fprintf(stderr
, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
667 // Check the hostname to make sure that it matches the shexp that
668 // is given in the common name of the certificate.
669 SECStatus
CERT_VerifyCertName(SecCertificateRef cert
, const char *hostname
)
671 fprintf(stderr
, "WARNING: CERT_VerifyCertName unimplemented\n");
676 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
677 ** verify a certificate by checking validity times against a certain time,
678 ** that we trust the issuer, and that the signature on the certificate is
680 ** "cert" the certificate to verify
681 ** "checkSig" only check signatures if true
684 CERT_VerifyCert(SecKeychainRef keychainOrArray
, SecCertificateRef cert
,
685 const CSSM_DATA_PTR
*otherCerts
, /* intermediates */
686 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef
*trustRef
)
688 CFMutableArrayRef certificates
= NULL
;
689 SecTrustRef trust
= NULL
;
691 int numOtherCerts
= SecCmsArrayCount((void **)otherCerts
);
695 * Certs to evaluate: first the leaf - our cert - then all the rest we know
696 * about. It's OK for otherCerts to contain a copy of the leaf.
698 certificates
= CFArrayCreateMutable(NULL
, numOtherCerts
+ 1, &kCFTypeArrayCallBacks
);
699 CFArrayAppendValue(certificates
, cert
);
700 for(dex
=0; dex
<numOtherCerts
; dex
++) {
701 SecCertificateRef intCert
;
703 rv
= SecCertificateCreateFromData(otherCerts
[dex
],
704 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
709 CFArrayAppendValue(certificates
, intCert
);
712 rv
= SecTrustCreateWithCertificates(certificates
, policies
, &trust
);
713 CFRelease(certificates
);
718 rv
= SecTrustSetKeychains(trust
, keychainOrArray
);
722 CFDateRef verifyDate
= CFDateCreate(NULL
, stime
);
723 rv
= SecTrustSetVerifyDate(trust
, verifyDate
);
724 CFRelease(verifyDate
);
734 SecTrustResultType result
;
735 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
736 rv
= SecTrustEvaluate(trust
, &result
);
742 case kSecTrustResultProceed
:
743 case kSecTrustResultUnspecified
:
744 /* TP Verification succeeded and there was either a UserTurst entry
745 telling us to procceed, or no user trust setting was specified. */
749 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
761 CFRelease(certificates
);
766 CERT_PolicyForCertUsage(SECCertUsage certUsage
)
768 SecPolicySearchRef search
= NULL
;
769 SecPolicyRef policy
= NULL
;
770 const CSSM_OID
*policyOID
;
775 case certUsageSSLServerWithStepUp
:
777 case certUsageVerifyCA
:
781 case certUsageSSLClient
:
782 case certUsageSSLServer
:
783 policyOID
= &CSSMOID_APPLE_TP_SSL
;
785 case certUsageUserCertImport
:
786 policyOID
= &CSSMOID_APPLE_TP_CSR_GEN
;
788 case certUsageStatusResponder
:
789 policyOID
= &CSSMOID_APPLE_TP_REVOCATION_OCSP
;
791 case certUsageObjectSigner
:
792 case certUsageProtectedObjectSigner
:
793 policyOID
= &CSSMOID_APPLE_ISIGN
;
795 case certUsageEmailSigner
:
796 case certUsageEmailRecipient
:
797 policyOID
= &CSSMOID_APPLE_X509_BASIC
;
802 rv
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, policyOID
, NULL
, &search
);
806 rv
= SecPolicySearchCopyNext(search
, &policy
);
811 if(search
) CFRelease(search
);