-/*
- * cert.c
- * security_smime
- *
- * Created by john on Wed Mar 12 2003.
- * Copyright (c) 2003 __MyCompanyName__. All rights reserved.
- *
- */
-
-#include "cert.h"
-#include "cmstpriv.h"
-#include <security_asn1/secerr.h>
-#include <Security/SecKeychain.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecKeychainSearch.h>
-#include <Security/SecIdentityPriv.h>
-#include <Security/SecIdentitySearch.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecPolicySearch.h>
-#include <Security/oidsalg.h>
-#include <Security/cssmapi.h>
-#include <Security/oidscert.h>
-#include <Security/oidscert.h>
-
-/* for errKCDuplicateItem */
-#include <Security/SecBase.h>
-
-/* @@@ Remove this once it's back in the appropriate header. */
-static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23};
-static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd};
-
-/*
- * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case
- * insensitive and we're supposed to ignore leading and trailing
- * whitespace, and collapse multiple whitespace characters into one.
- */
-static void
-CERT_NormalizeString(CSSM_DATA_PTR string)
-{
- char *pD, *pCh, *pEos;
-
- if (!string->Length)
- return;
-
- pD = pCh = (char *)string->Data;
- pEos = pCh + string->Length - 1;
-
- /* Strip trailing NULL terminators */
- while(*pEos == 0)
- pEos--;
-
- /* Remove trailing spaces */
- while(isspace(*pEos))
- pEos--;
-
- /* Point to one past last non-space character */
- pEos++;
-
- /* skip all leading whitespace */
- while(isspace(*pCh) && (pCh < pEos))
- pCh++;
-
- /* Eliminate multiple whitespace and convent to upper case.
- * pCh points to first non-white char.
- * pD still points to start of string. */
- while(pCh < pEos)
- {
- char ch = *pCh++;
- *pD++ = toupper(ch);
- if(isspace(ch))
- {
- /* skip 'til next nonwhite */
- while(isspace(*pCh) && (pCh < pEos))
- pCh++;
- }
- }
-
- string->Length = pD - (char *)string->Data;
-}
-
-/*
- * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case
- * insensitive and we're supposed to ignore leading and trailing
- * whitespace, and collapse multiple whitespace characters into one.
- *
- * Incoming NSS_Name is assumed to be entirely within specifed coder's
- * address space; we'll be munging some of that and possibly replacing
- * some pointers with others allocated from the same space.
- */
-void
-CERT_NormalizeX509NameNSS(NSS_Name *nssName)
-{
- NSS_RDN *rdn;
-
- for (rdn = *nssName->rdns; rdn; ++rdn)
- {
- NSS_ATV *attr;
- for (attr = *rdn->atvs; attr; ++attr)
- {
- /*
- * attr->value is an ASN_ANY containing an encoded
- * string. We only normalize Prinatable String types.
- * If we find one, decode it, normalize it, encode the
- * result, and put the encoding back in attr->value.
- * We temporarily "leak" the original string, which only
- * has a lifetime of the incoming SecNssCoder.
- */
- NSS_TaggedItem *attrVal = &attr->value;
- if(attrVal->tag != SEC_ASN1_PRINTABLE_STRING)
- continue;
-
- CERT_NormalizeString(&attrVal->item);
- }
- }
-}
-
-SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray, char *name)
-{
- SecCertificateRef certificate;
- OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate);
- return status==errSecSuccess?certificate:NULL;
-}
-
-SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
-{
- CFRetain(pubKey);
- return pubKey;
-}
-
-void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
-{
- CFRelease(pubKey);
-}
-
-SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey)
-{
- CFRetain(privKey);
- return privKey;
-}
-
-void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey)
-{
- CFRelease(privKey);
-}
-
-void CERT_DestroyCertificate(SecCertificateRef cert)
-{
- CFRelease(cert);
-}
-
-SecCertificateRef CERT_DupCertificate(SecCertificateRef cert)
-{
- CFRetain(cert);
- return cert;
-}
-
-SecIdentityRef CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray,
- char *nickname, SECCertUsage usage, Boolean validOnly, void *proto_win)
-{
- SecIdentityRef identityRef = NULL;
- SecCertificateRef cert = CERT_FindCertByNicknameOrEmailAddr(keychainOrArray, nickname);
- if (!cert)
- return NULL;
-
- SecIdentityCreateWithCertificate(keychainOrArray, cert, &identityRef);
- CFRelease(cert);
-
- return identityRef;
-}
-
-SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
- char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win)
-{
- SecItemClass itemClass = kSecCertificateItemClass;
- SecKeychainSearchRef searchRef;
- SecKeychainItemRef itemRef = NULL;
- OSStatus status;
- SecKeychainAttribute attrs[1];
- const char *serialNumber = "12345678";
- // const SecKeychainAttributeList attrList;
-#if 0
- attrs[0].tag = kSecLabelItemAttr;
- attrs[0].length = strlen(nickname)+1;
- attrs[0].data = nickname;
-#else
- attrs[0].tag = kSecSerialNumberItemAttr;
- attrs[0].length = strlen(serialNumber)+1;
- attrs[0].data = (uint8 *)serialNumber;
-#endif
- SecKeychainAttributeList attrList = { 0, attrs };
- // 12 34 56 78
- status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef);
- if (status)
- {
- printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%ld",status);
- return NULL;
- }
- status = SecKeychainSearchCopyNext(searchRef,&itemRef);
- if (status)
- printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%ld",status);
- CFRelease(searchRef);
- return (SecCertificateRef)itemRef;
-}
-
-/*
-startNewClass(X509Certificate)
-CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
-CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
-PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
-Alias, kSecAliasItemAttr, "Alias", 0, NULL, BLOB)
-Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
-Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
-SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
-SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
-PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
-endNewClass()
-*/
-
-CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot)
-{
- SecPolicySearchRef searchRef = NULL;
- SecPolicyRef policy = NULL;
- CFArrayRef wrappedCert = NULL;
- SecTrustRef trust = NULL;
- CFArrayRef certChain = NULL;
- CSSM_TP_APPLE_EVIDENCE_INFO *statusChain;
- OSStatus status = 0;
- SecTrustResultType trustResult = kSecTrustResultInvalid;
-
- if (!cert)
- goto loser;
-
- status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
- if (status)
- goto loser;
- status = SecPolicySearchCopyNext(searchRef, &policy);
- if (status)
- goto loser;
-
- wrappedCert = CERT_CertListFromCert(cert);
- status = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
- if (status)
- goto loser;
-
- status = SecTrustEvaluate(trust, &trustResult);
- if (status)
- goto loser;
-
- status = SecTrustGetResult(trust, NULL, &certChain, &statusChain);
- if (status)
- goto loser;
-
- /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */
- if (!includeRoot && CFArrayGetCount(certChain) > 1)
- {
- CFMutableArrayRef subChain = CFArrayCreateMutableCopy(NULL, 0, certChain);
- CFRelease(certChain);
- certChain = subChain;
- if (subChain)
- CFArrayRemoveValueAtIndex(subChain, CFArrayGetCount(subChain) - 1);
- }
-
-loser:
- if (searchRef)
- CFRelease(searchRef);
- if (policy)
- CFRelease(policy);
- if (wrappedCert)
- CFRelease(wrappedCert);
- if (trust)
- CFRelease(trust);
- if (certChain && status)
- {
- CFRelease(certChain);
- certChain = NULL;
- }
-
- return certChain;
-}
-
-CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
-{
- const void *value = cert;
- return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
-}
-
-CFArrayRef CERT_DupCertList(CFArrayRef oldList)
-{
- CFRetain(oldList);
- return oldList;
-}
-
-// Extract a public key object from a SubjectPublicKeyInfo
-SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
-{
- SecPublicKeyRef keyRef = NULL;
- SecCertificateCopyPublicKey(cert,&keyRef);
- return keyRef;
-}
-
-SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage)
-{
- // abort();
- // @@@ It's all good, it's ok.
- return SECSuccess;
-}
-
-// Find a certificate in the database by a email address
-// "emailAddr" is the email address to look up
-SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr)
-{
- abort();
- return NULL;
-}
-
-// Find a certificate in the database by a DER encoded certificate
-// "derCert" is the DER encoded certificate
-SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert)
-{
- // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
- SecCertificateRef cert = NULL;
- OSStatus rv;
-
- rv = SecCertificateCreateFromData(derCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
- if (rv && cert)
- {
- PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
- CFRelease(cert);
- cert = NULL;
- }
-
- return cert;
-}
-
-// Generate a certificate key from the issuer and serialnumber, then look it up in the database.
-// Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
-SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
-{
- SecCertificateRef certificate;
- OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer,
- &issuerAndSN->serialNumber, &certificate);
- if (status)
- {
- PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
- certificate = NULL;
- }
-
- return certificate;
-}
-
-SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
-{
- SecCertificateRef certificate;
- OSStatus status = SecCertificateFindBySubjectKeyID(keychainOrArray,subjKeyID,&certificate);
- if (status)
- {
- PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
- certificate = NULL;
- }
-
- return certificate;
-}
-
-static SecIdentityRef
-CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray, SecCertificateRef certificate)
-{
- SecIdentityRef identity = NULL;
- SecIdentityCreateWithCertificate(keychainOrArray, certificate, &identity);
- if (!identity)
- PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT);
-
- return identity;
-}
-
-SecIdentityRef
-CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
-{
- SecCertificateRef certificate = CERT_FindCertByIssuerAndSN(keychainOrArray, issuerAndSN);
- if (!certificate)
- return NULL;
-
- return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
-}
-
-SecIdentityRef
-CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID)
-{
- SecCertificateRef certificate = CERT_FindCertBySubjectKeyID(keychainOrArray, subjKeyID);
- if (!certificate)
- return NULL;
-
- return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
-}
-
-// find the smime symmetric capabilities profile for a given cert
-SECItem *CERT_FindSMimeProfile(SecCertificateRef cert)
-{
- return NULL;
-}
-
-// Return the decoded value of the subjectKeyID extension. The caller should
-// free up the storage allocated in retItem->data.
-SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert,SECItem *retItem)
-{
- fprintf(stderr, "WARNING: CERT_FindSubjectKeyIDExtension unimplemented\n");
- return SECFailure;
-}
-
-static void * appMalloc (uint32 size, void *allocRef) {
- return (malloc (size));
-}
-
-static void appFree (void *mem_ptr, void *allocRef) {
- free (mem_ptr);
- return;
-}
-
-static void * appRealloc (void *ptr, uint32 size, void *allocRef) {
- return (realloc (ptr, size));
-}
-
-static void * appCalloc (uint32 num, uint32 size, void *allocRef) {
- return (calloc (num, size));
-}
-
-static CSSM_API_MEMORY_FUNCS memFuncs = {
- appMalloc,
- appFree,
- appRealloc,
- appCalloc,
- NULL
- };
-
-// return a valid CL handle
-static int InitializeCL (CSSM_CL_HANDLE *clHandle)
-{
- CSSM_VERSION version = {2, 0};
-
- // load the module
- CSSM_RETURN result = CSSM_ModuleLoad (&gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
- if (result != 0)
- {
- return false;
- }
-
- result = CSSM_ModuleAttach (&gGuidAppleX509CL, &version, &memFuncs, 0, CSSM_SERVICE_CL, 0, 0, NULL, 0, NULL, clHandle);
- if (result != 0)
- {
- return false;
- }
-
- return true;
-}
-
-// cleanup a CL handle
-static void CloseCL (CSSM_CL_HANDLE clHandle)
-{
- CSSM_ModuleDetach (clHandle);
- CSSM_ModuleUnload (&gGuidAppleX509CL, NULL, NULL);
-}
-
-// Extract the issuer and serial number from a certificate
-SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert)
-{
- OSStatus status;
- SecCmsIssuerAndSN *certIssuerAndSN;
- CSSM_CL_HANDLE clHandle;
- CSSM_DATA_PTR serialNumber = 0;
- CSSM_DATA_PTR issuer = 0;
- CSSM_DATA certData = {};
- CSSM_HANDLE resultsHandle = 0;
- uint32 numberOfFields = 0;
- CSSM_RETURN result;
- void *mark;
-
- mark = PORT_ArenaMark(pl);
-
- if (!InitializeCL (&clHandle))
- goto loser;
- status = SecCertificateGetData(cert, &certData);
- if (status)
- goto loser;
-
- /* Get the issuer from the cert. */
- result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer);
-
- /* @@@ Remove this once we are sure CSSMOID_X509V1IssuerNameStd is working. */
- /* Fall back on old normalized issuer if the new oid isn't supported yet. */
- if (result)
- result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1IssuerName, &resultsHandle, &numberOfFields, &issuer);
-
- if (result || numberOfFields < 1)
- goto loser;
- result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
- if (result)
- goto loser;
-
-
- /* Get the serialNumber from the cert. */
- result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber);
- if (result || numberOfFields < 1)
- goto loser;
- result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
- if (result)
- goto loser;
-
- /* Allocate the SecCmsIssuerAndSN struct. */
- certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
- if (certIssuerAndSN == NULL)
- goto loser;
-
- /* Copy the issuer. */
- certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length);
- if (!certIssuerAndSN->derIssuer.Data)
- goto loser;
- PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length);
- certIssuerAndSN->derIssuer.Length = issuer->Length;
-
- /* Copy the serialNumber. */
- certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length);
- if (!certIssuerAndSN->serialNumber.Data)
- goto loser;
- PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length);
- certIssuerAndSN->serialNumber.Length = serialNumber->Length;
-
- PORT_ArenaUnmark(pl, mark);
-
- CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
- CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
-
- CloseCL (clHandle);
-
- return certIssuerAndSN;
-
-loser:
- PORT_ArenaRelease(pl, mark);
-
- if (serialNumber)
- CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
- if (issuer)
- CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
-
- CloseCL (clHandle);
-
- PORT_SetError(SEC_INTERNAL_ONLY);
- return NULL;
-}
-
-// import a collection of certs into the temporary or permanent cert database
-SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned int ncerts,
- SECItem **derCerts, SecCertificateRef **retCerts, Boolean keepCerts, Boolean caOnly, char *nickname)
-{
- OSStatus rv = SECFailure;
- SecCertificateRef cert;
- unsigned int ci;
-
- // @@@ Do something with caOnly and nickname
- if (caOnly || nickname)
- abort();
-
- for (ci = 0; ci < ncerts; ++ci)
- {
- rv = SecCertificateCreateFromData(derCerts[ci], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
- if (rv)
- break;
- if (keepCerts)
- {
- rv = SecCertificateAddToKeychain(cert, keychain);
- if (rv)
- {
- if (rv == errKCDuplicateItem)
- rv = errSecSuccess;
- else
- {
- CFRelease(cert);
- break;
- }
- }
- }
-
- if (retCerts)
- {
- // @@@ not yet
- abort();
- }
- else
- CFRelease(cert);
- }
-
- return rv;
-}
-
-SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime)
-{
- fprintf(stderr, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
- return SECSuccess;
-}
-
-// Check the hostname to make sure that it matches the shexp that
-// is given in the common name of the certificate.
-SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname)
-{
- fprintf(stderr, "WARNING: CERT_VerifyCertName unimplemented\n");
- return SECSuccess;
-}
-
-/*
-** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
-** verify a certificate by checking validity times against a certain time,
-** that we trust the issuer, and that the signature on the certificate is
-** valid.
-** "cert" the certificate to verify
-** "checkSig" only check signatures if true
-*/
-SECStatus
-CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert,
- CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
-{
- CFArrayRef certificates;
- const void *certs = cert;
- SecTrustRef trust = NULL;
- OSStatus rv;
-
- certificates = CFArrayCreate(NULL, &certs, 1, &kCFTypeArrayCallBacks);
- rv = SecTrustCreateWithCertificates(certificates, policies, &trust);
- CFRelease(certificates);
- if (rv)
- goto loser;
-
- rv = SecTrustSetKeychains(trust, keychainOrArray);
- if (rv)
- goto loser;
-
- CFDateRef verifyDate = CFDateCreate(NULL, stime);
- rv = SecTrustSetVerifyDate(trust, verifyDate);
- CFRelease(verifyDate);
- if (rv)
- goto loser;
-
- if (trustRef)
- {
- *trustRef = trust;
- }
- else
- {
- SecTrustResultType result;
- /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
- rv = SecTrustEvaluate(trust, &result);
- if (rv)
- goto loser;
-
- switch (result)
- {
- case kSecTrustResultProceed:
- case kSecTrustResultUnspecified:
- /* TP Verification succeeded and there was either a UserTurst entry
- telling us to procceed, or no user trust setting was specified. */
- CFRelease(trust);
- break;
- default:
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- rv = SECFailure;
- goto loser;
- break;
- }
- }
-
- return SECSuccess;
-loser:
- if (trust)
- CFRelease(trust);
-
- return rv;
-}
-
-CFTypeRef
-CERT_PolicyForCertUsage(SECCertUsage certUsage)
-{
- SecPolicySearchRef search;
- SecPolicyRef policy = NULL;
- const CSSM_OID *policyOID;
- OSStatus rv;
-
- switch (certUsage)
- {
- case certUsageSSLServerWithStepUp:
- case certUsageSSLCA:
- case certUsageVerifyCA:
- case certUsageAnyCA:
- goto loser;
- break;
- case certUsageSSLClient:
- case certUsageSSLServer:
- policyOID = &CSSMOID_APPLE_TP_SSL;
- break;
- case certUsageUserCertImport:
- policyOID = &CSSMOID_APPLE_TP_CSR_GEN;
- break;
- case certUsageStatusResponder:
- policyOID = &CSSMOID_APPLE_TP_REVOCATION_OCSP;
- break;
- case certUsageObjectSigner:
- case certUsageProtectedObjectSigner:
- policyOID = &CSSMOID_APPLE_ISIGN;
- break;
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- policyOID = &CSSMOID_APPLE_X509_BASIC;
- break;
- default:
- goto loser;
- }
- rv = SecPolicySearchCreate(CSSM_CERT_X_509v3, policyOID, NULL, &search);
- if (rv)
- goto loser;
-
- rv = SecPolicySearchCopyNext(search, &policy);
- if (rv)
- goto loser;
-
-loser:
- CFRelease(search);
- return policy;
-}