]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/crypto_cssm.c
ipsec-317.220.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / crypto_cssm.c
index 9b0e3495743955059e9a611158e1db8c07b81429..008ba514b8565409b428d8b97b8524d361862f27 100644 (file)
  * Framework and CSSM
  */
 
-#include <Security/SecBase.h>
+#include "config.h"
+
 #include <Security/SecCertificate.h>
 #include <Security/SecPolicy.h>
+#include <Security/SecTrust.h>
+#include <Security/SecKeyPriv.h>
 #include <Security/SecIdentity.h>
+#include <Security/SecItem.h>
+#include <TargetConditionals.h>
+#include <Security/SecItemPriv.h>
+#ifndef HAVE_OPENSSL
+#include <Security/SecTrustPriv.h>
+#include <Security/SecPolicyPriv.h>
+#include <Security/SecCertificatePriv.h>
+#else
+#include <Security/SecBase.h>
 #include <Security/SecIdentityPriv.h>
-#include <Security/SecIdentitySearch.h>
-#include <Security/SecKeychain.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecKeychainItemPriv.h>
-#include <Security/SecKey.h>
+#include <Security/SecCertificateOIDs.h>
 #include <Security/SecKeyPriv.h>
-#include <Security/SecTrust.h>
 #include <Security/oidsalg.h>
 #include <Security/cssmapi.h>
 #include <Security/SecPolicySearch.h>
+#endif
 #include <CoreFoundation/CoreFoundation.h>
+#if !TARGET_OS_EMBEDDED
+#include <Security/SecIdentitySearch.h>
+#include <Security/SecKeychain.h>
+#include <Security/SecKeychainItem.h>
+#include <Security/SecKeychainItemPriv.h>
 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+#endif
 #include "plog.h"
 #include "debug.h"
 #include "misc.h"
+#include "oakley.h"
+#include "gcmalloc.h"
+
 
 #include "crypto_cssm.h"
 
 
+static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef);
+
+
+
+static SecPolicyRef
+crypto_cssm_x509cert_get_SecPolicyRef (CFStringRef hostname)
+{
+       SecPolicyRef            policyRef = NULL;
+       CFDictionaryRef         properties = NULL;
+       const void                      *key[] = { kSecPolicyName };
+       const void                      *value[] = { hostname };
+
+       if (hostname) {
+               properties = CFDictionaryCreate(NULL, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+               if (properties == NULL) {
+                       plog(ASL_LEVEL_ERR, 
+                               "unable to create dictionary for policy properties.\n");
+               }
+       }       
+       policyRef = SecPolicyCreateWithProperties(kSecPolicyAppleIPsec, properties);
+       if (properties)
+               CFRelease(properties);
+       return policyRef;
+}
 
-static OSStatus FindPolicy(const CSSM_OID *policyOID, SecPolicyRef *policyRef);
-static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef);
-static OSStatus CopySystemKeychain(SecKeychainRef *keychainRef);
-static const char *GetSecurityErrorString(OSStatus err);
+SecCertificateRef
+crypto_cssm_x509cert_CreateSecCertificateRef (vchar_t *cert)
+{
+       SecCertificateRef       certRef = NULL;
 
+       CFDataRef cert_data = CFDataCreateWithBytesNoCopy(NULL, (uint8_t*)cert->v, cert->l, kCFAllocatorNull);
+    if (cert_data) {
+        certRef = SecCertificateCreateWithData(NULL, cert_data);
+        CFRelease(cert_data);
+    }
+
+       if (certRef == NULL) {
+               plog(ASL_LEVEL_ERR, 
+                        "unable to get a certifcate reference.\n");
+       }
+       return certRef;
+}
+
+/* HACK!!! - temporary until this prototype gets moved */
+extern CFDataRef SecCertificateCopySubjectSequence( SecCertificateRef certificate);
+
+CFDataRef
+crypto_cssm_CopySubjectSequence(SecCertificateRef certRef)
+{
+    CFDataRef subject = NULL;
+
+    subject = SecCertificateCopySubjectSequence(certRef);
+    return subject;
+    
+}
+
+
+cert_status_t
+crypto_cssm_check_x509cert_dates (SecCertificateRef certificateRef)
+{
+       cert_status_t       certStatus = CERT_STATUS_OK;
+#ifndef HAVE_OPENSSL
+       CFAbsoluteTime          timeNow = 0;
+       CFAbsoluteTime          notvalidbeforedate = 0;
+       CFAbsoluteTime          notvalidafterdate = 0;
+       CFDateRef                       nowcfdatedata = NULL;
+       CFDateRef                       notvalidbeforedatedata = NULL;
+       CFDateRef                       notvalidafterdatedata = NULL;
+       CFArrayRef                      certProparray = NULL;
+
+       if ((timeNow = CFAbsoluteTimeGetCurrent())) {
+               if (SecCertificateIsValid(certificateRef, timeNow)) {
+                       plog(ASL_LEVEL_NOTICE, "Certificate expiration date is OK\n");
+                       certStatus = CERT_STATUS_OK;
+               } else {
+                       nowcfdatedata = CFDateCreate( NULL, timeNow);
+
+                       if ((notvalidbeforedate = SecCertificateNotValidBefore(certificateRef))) {
+                               notvalidbeforedatedata = CFDateCreate(NULL, notvalidbeforedate);
+                       }
+
+                       if ((notvalidafterdate = SecCertificateNotValidAfter(certificateRef))) {
+                               notvalidafterdatedata = CFDateCreate(NULL, notvalidafterdate);
+                       }
+
+                       int year = 0;
+                       int month = 0;
+                       int day = 0;
+                       int hour = 0;
+                       int minute = 0;
+                       CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar);
+                       if (calendar)
+                       {
+                               if (notvalidbeforedate) {
+                                       CFCalendarDecomposeAbsoluteTime(calendar, notvalidbeforedate, "yMdHm", &year, &month, &day, &hour, &minute);
+                                       plog(ASL_LEVEL_DEBUG, "Certificate not valid before yr %d, mon %d, days %d, hours %d, min %d\n", year, month, day, hour, minute);
+                               }
+
+                               if (notvalidafterdate) {
+                                       CFCalendarDecomposeAbsoluteTime(calendar, notvalidafterdate, "yMdHm", &year, &month, &day, &hour, &minute);
+                                       plog(ASL_LEVEL_DEBUG, "Certificate not valid after yr %d, mon %d, days %d, hours %d, min %d\n", year, month, day, hour, minute);
+                               }
+                               CFRelease(calendar);
+                       }
+
+                       if (nowcfdatedata != NULL) {
+                               if (notvalidbeforedatedata && CFDateCompare(nowcfdatedata, notvalidbeforedatedata, NULL) == kCFCompareLessThan){
+                                       plog(ASL_LEVEL_ERR,
+                                                "current time before valid time\n");
+                                       certStatus = CERT_STATUS_PREMATURE;
+                               } else if (notvalidafterdatedata && (CFDateCompare( nowcfdatedata, notvalidafterdatedata, NULL ) == kCFCompareGreaterThan)){
+                                       plog(ASL_LEVEL_ERR,
+                                                "current time after valid time\n");
+                                       certStatus = CERT_STATUS_EXPIRED;
+                               }
+                       }
+               }
+       } else {
+               plog(ASL_LEVEL_ERR, "CFAbsoluteTimeGetCurrent() failed");
+               certStatus = CERT_STATUS_INVALID;
+       }
+
+       if (notvalidbeforedatedata)
+               CFRelease(notvalidbeforedatedata);
+       if (notvalidafterdatedata)
+               CFRelease(notvalidafterdatedata);
+       if (certProparray)
+               CFRelease(certProparray);
+       if (nowcfdatedata)
+               CFRelease(nowcfdatedata);
+#endif
+       return certStatus;
+}
 
 /*
  * Verify cert using security framework
  */
-int crypto_cssm_check_x509cert(vchar_t *cert)
+int crypto_cssm_check_x509cert (cert_t *hostcert, cert_t *certchain, CFStringRef hostname, SecKeyRef *publicKeyRef)
 {
+       cert_t             *p;
+       cert_status_t       certStatus = 0;
        OSStatus                        status;
-       SecCertificateRef       certRef = 0;
-       CSSM_DATA                       certData;
-       CSSM_OID                        ourPolicyOID = CSSMOID_APPLE_TP_IP_SEC; 
-       SecPolicyRef            policyRef = 0;
-
-       // create cert ref
-       certData.Length = cert->l;
-       certData.Data = (uint8 *)cert->v;
-       status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER,
-               &certRef);
-       if (status != noErr)
-               goto end;
+       CFIndex             certArrayRefNumValues = 0;
+       CFIndex             n = 0;
+       int                 certArraySiz;
+       SecCertificateRef  *certArrayRef = NULL;
+       SecPolicyRef            policyRef = crypto_cssm_x509cert_get_SecPolicyRef(hostname);
        
-       // get our policy object
-       status = FindPolicy(&ourPolicyOID, &policyRef);
-       if (status != noErr)
-               goto end;
-               
-       // setup policy options ???
-       // no options used at present - verification of subjectAltName fields, etc.
-       // are done elsewhere in racoon in oakley_check_certid()
+       if (!hostcert || !certchain) {
+               return -1;
+       }
+       
+       // find the total number of certs
+       for (p = certchain; p; p = p->chain, n++);
+       if (n> 1) {
+               plog(ASL_LEVEL_DEBUG, 
+                        "%s: checking chain of %d certificates.\n", __FUNCTION__, (int)n);
+       }
+       
+       certArraySiz = n * sizeof(CFTypeRef);
+       certArrayRef = CFAllocatorAllocate(NULL, certArraySiz, 0);
+       if (!certArrayRef) {
+               return -1;
+       }
+       bzero(certArrayRef, certArraySiz);
+       if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&hostcert->cert))) {
+               /* don't overwrite any pending status */
+               if (!hostcert->status) {
+                       hostcert->status = crypto_cssm_check_x509cert_dates(certArrayRef[certArrayRefNumValues]);
+                       if (hostcert->status) {
+                               plog(ASL_LEVEL_ERR, 
+                                        "host certificate failed date verification: %d.\n", hostcert->status);
+                               certStatus = hostcert->status;
+                       }
+               }
+               certArrayRefNumValues++;
+       }
+       for (p = certchain; p && certArrayRefNumValues < n; p = p->chain) {
+               if (p != hostcert) {
+                       if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&p->cert))) {
+                               /* don't overwrite any pending status */
+                               if (!p->status) {
+                                       p->status = crypto_cssm_check_x509cert_dates(certArrayRef[certArrayRefNumValues]);
+                                       if (p->status) {
+                                               plog(ASL_LEVEL_ERR, 
+                                                        "other certificate in chain failed date verification: %d.\n", p->status);
+                                               if (!certStatus) {
+                                                       certStatus = p->status;
+                                               }
+                                       }
+                               }
+                               certArrayRefNumValues++;
+                       }
+               }
+       }
        
        // evaluate cert
-       status = EvaluateCert(certRef, policyRef);
+       status = EvaluateCert(certArrayRef, certArrayRefNumValues, policyRef, publicKeyRef);
        
+       while (certArrayRefNumValues) {
+               CFRelease(certArrayRef[--certArrayRefNumValues]);
+       }
+       CFAllocatorDeallocate(NULL, certArrayRef);
        
-end:
-
-       if (certRef)
-               CFRelease(certRef);
        if (policyRef)
                CFRelease(policyRef);
        
        if (status != noErr && status != -1) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
+               plog(ASL_LEVEL_ERR, 
+                        "check_x509cert error %d %s.\n", (int)status, GetSecurityErrorString(status));
+               status = -1;
+       } else if (certStatus == CERT_STATUS_PREMATURE || certStatus == CERT_STATUS_EXPIRED) {
                status = -1;
-       }               
+       }
        return status;
+       
+}
 
+
+int crypto_cssm_verify_x509sign(SecKeyRef publicKeyRef, vchar_t *hash, vchar_t *signature, Boolean useSHA1)
+{
+       return SecKeyRawVerify(publicKeyRef, useSHA1 ? kSecPaddingPKCS1SHA1 : kSecPaddingPKCS1, (uint8_t*)hash->v, hash->l, (uint8_t*)signature->v, signature->l);
 }
 
 /*
@@ -113,138 +299,58 @@ end:
 vchar_t* crypto_cssm_getsign(CFDataRef persistentCertRef, vchar_t* hash)
 {
 
-       OSStatus                                                status;
-       SecCertificateRef                               certificateRef = NULL;
+       OSStatus                                                status = -1;
        SecIdentityRef                                  identityRef = NULL;
-       SecIdentitySearchRef                    idSearchRef = NULL;
-       SecKeychainRef                                  keychainRef = NULL;
        SecKeyRef                                               privateKeyRef = NULL;
-       const CSSM_KEY                                  *cssmKey = NULL;
-       CSSM_CSP_HANDLE                                 cspHandle = nil;
-       CSSM_CC_HANDLE                                  cssmContextHandle = nil;
-       const CSSM_ACCESS_CREDENTIALS   *credentials = NULL;
-       //CSSM_SIZE                                             bytesEncrypted = 0;     //%%%%HWR fix this - need new headers on Leopard
-       uint32                                                  bytesEncrypted = 0;
-       CSSM_DATA                                               clearData;
-       CSSM_DATA                                               cipherData;
-       CSSM_DATA                                               remData;
-       CSSM_CONTEXT_ATTRIBUTE                  newAttr;
        vchar_t                                                 *sig = NULL;
 
-       remData.Length = 0;
-       remData.Data = 0;
 
-       if (persistentCertRef) {                        
-               // get cert from keychain
-               status = SecKeychainItemCopyFromPersistentReference(persistentCertRef, (SecKeychainItemRef*)&certificateRef);
-               if (status != noErr)
-                       goto end;
-       
-               // get keychain ref where cert is contained
-               status = SecKeychainItemCopyKeychain((SecKeychainItemRef)certificateRef, &keychainRef);
-               if (status != noErr)
-                       goto end;
-       
-               // get identity from the certificate
-               status = SecIdentityCreateWithCertificate(keychainRef, certificateRef, &identityRef);
-               if (status != noErr)
-                       goto end;       
-                       
-       } else {
-               // copy system keychain
-               status = CopySystemKeychain(&keychainRef);
-               if (status != noErr)
-                       goto end;
-
-               // serach for first identity in system keychain
-               status = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_SIGN, &idSearchRef);
-               if (status != noErr)
-                       goto end;
-               
-               status = SecIdentitySearchCopyNext(idSearchRef, &identityRef);
-               if (status != noErr)
-                       goto end;
-
-               // get certificate from identity
-               status = SecIdentityCopyCertificate(identityRef, &certificateRef);
-               if (status != noErr)
-                       goto end;
-       }
+       CFDictionaryRef         persistFind = NULL;
+       const void                      *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass,
+#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+                                                           kSecUseSystemKeychain,
+#endif
+                                                         };
+       const void                      *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity,
+#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+                                                             kCFBooleanTrue,
+#endif
+                                                           };
+    
+#define SIG_BUF_SIZE 1024
        
-                                       
-       // get private key from identity
-       status = SecIdentityCopyPrivateKey(identityRef, &privateKeyRef);
-       if (status != noErr)
-               goto end;
-               
-       // get CSSM_KEY pointer from key ref
-       status = SecKeyGetCSSMKey(privateKeyRef, &cssmKey);
-       if (status != noErr)
+       /* find identity by persistent ref */
+       persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
+                                     (sizeof(keys_persist) / sizeof(*keys_persist)), NULL, NULL);
+       if (persistFind == NULL)
                goto end;
-               
-       // get CSSM CSP handle
-       status = SecKeychainGetCSPHandle(keychainRef, &cspHandle);
-       if (status != noErr)
-               goto end;
-               
-       // create CSSM credentials to unlock private key for encryption - no UI to be used
-       status = SecKeyGetCredentials(privateKeyRef, CSSM_ACL_AUTHORIZATION_ENCRYPT,
-                               kSecCredentialTypeNoUI, &credentials);
-       if (status != noErr)
-               goto end;       
-
-       // create asymmetric context for encryption
-       status = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA, credentials, cssmKey, 
-                       CSSM_PADDING_PKCS1, &cssmContextHandle);
+       
+       status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
        if (status != noErr)
                goto end;
                
-       // add mode attribute to use private key for encryption
-       newAttr.AttributeType     = CSSM_ATTRIBUTE_MODE;
-       newAttr.AttributeLength   = sizeof(uint32);
-       newAttr.Attribute.Data    = (CSSM_DATA_PTR)CSSM_ALGMODE_PRIVATE_KEY;
-       status = CSSM_UpdateContextAttributes(cssmContextHandle, 1, &newAttr);
-       if(status != noErr)
-               goto end;
-                       
-       // and finally - encrypt data
-       clearData.Length = hash->l;
-       clearData.Data = (uint8 *)hash->v;
-       cipherData.Length = 0;
-       cipherData.Data = NULL;
-       status = CSSM_EncryptData(cssmContextHandle, &clearData, 1, &cipherData, 1, &bytesEncrypted, 
-                                               &remData);
+       status = SecIdentityCopyPrivateKey(identityRef, &privateKeyRef);
        if (status != noErr)
                goto end;
-       
-       if (remData.Length != 0) {      // something didn't go right - should be zero
-               status = -1;
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "unencrypted data remaining after encrypting hash.\n");
-               goto end;
-       }
 
        // alloc buffer for result
-       sig = vmalloc(0);
+       sig = vmalloc(SIG_BUF_SIZE);
        if (sig == NULL)
                goto end;
-               
-       sig->l = cipherData.Length;
-       sig->v = (caddr_t)cipherData.Data;
+       
+       status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1, (uint8_t*)hash->v,
+                           hash->l, (uint8_t*)sig->v, &sig->l);                                
+                                       
                
 end:
-       if (certificateRef)
-               CFRelease(certificateRef);
-       if (keychainRef)
-               CFRelease(keychainRef);
        if (identityRef)
                CFRelease(identityRef);
        if (privateKeyRef)
                CFRelease(privateKeyRef);
-       if (idSearchRef)
-               CFRelease(idSearchRef);
-       if (cssmContextHandle)
-               CSSM_DeleteContext(cssmContextHandle);
+               
+       if (persistFind)
+               CFRelease(persistFind);
+       
        if (status != noErr) {
                if (sig) {
                        vfree(sig);
@@ -253,8 +359,8 @@ end:
        }
 
        if (status != noErr && status != -1) {
-               plog(LLV_ERROR, LOCATION, NULL
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
+               plog(ASL_LEVEL_ERR
+                       "getsign error %d %s.\n", (int)status, GetSecurityErrorString(status));
                status = -1;
        }                       
        return sig;
@@ -265,127 +371,96 @@ end:
 /*
  * Retrieve a cert from the keychain
  */
-vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef)
+vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef,
+                                  cert_status_t *certStatus)
 {
 
-       OSStatus                                status;
-       CSSM_DATA                               cssmData;
+       OSStatus                                status = -1;
        vchar_t                                 *cert = NULL;
+       SecCertificateRef               certificateRef = NULL;          
+       CFDictionaryRef         persistFind = NULL;
+       size_t                  dataLen;
+       CFDataRef               certData = NULL;
        SecIdentityRef                  identityRef = NULL;
-       SecIdentitySearchRef    idSearchRef = NULL;
-       SecKeychainRef                  keychainRef = NULL;
-       SecCertificateRef               certificateRef = NULL;
-
+       const void              *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass,
+#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+                                                   kSecUseSystemKeychain,
+#endif
+                                                 };
+       const void              *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity,
+#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+                                                     kCFBooleanTrue,
+#endif
+                                                   };
+       
+       /* find identity by persistent ref */
+       persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
+               (sizeof(keys_persist) / sizeof(*keys_persist)), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       if (persistFind == NULL)
+               goto end;
+    
+       status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
+       if (status != noErr)
+               goto end;
 
-       // get cert ref
-       if (persistentCertRef) {
-               status = SecKeychainItemCopyFromPersistentReference(persistentCertRef, (SecKeychainItemRef*)&certificateRef);
-               if (status != noErr)
-                       goto end;
-       } else {
-               // copy system keychain
-               status = CopySystemKeychain(&keychainRef);
-               if (status != noErr)
-                       goto end;
-
-               // find first identity in system keychain
-               status = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_SIGN, &idSearchRef);
-               if (status != noErr)
-                       goto end;
-               
-               status = SecIdentitySearchCopyNext(idSearchRef, &identityRef);
-               if (status != noErr)
-                       goto end;
-
-               // get certificate from identity
-               status = SecIdentityCopyCertificate(identityRef, &certificateRef);
-               if (status != noErr)
-                       goto end;
-               
-       }
-               
-       // get certificate data
-       cssmData.Length = 0;
-       cssmData.Data = NULL;
-       status = SecCertificateGetData(certificateRef, &cssmData);
+       status = SecIdentityCopyCertificate(identityRef, &certificateRef);
        if (status != noErr)
                goto end;
-               
-       if (cssmData.Length == 0)
+
+       certData = SecCertificateCopyData(certificateRef);
+       if (certData == NULL)
+               goto end;
+       
+       dataLen = CFDataGetLength(certData);
+       if (dataLen == 0)
                goto end;
        
-       cert = vmalloc(cssmData.Length);
+       cert = vmalloc(dataLen);
        if (cert == NULL)
                goto end;       
        
-       // cssmData struct just points to the data
-       // data must be copied to be returned
-       memcpy(cert->v, cssmData.Data, cssmData.Length);        
+       CFDataGetBytes(certData, CFRangeMake(0, dataLen), (uint8_t*)cert->v); 
+                               
+       // verify expiry or missing fields
+       if (certStatus) {
+               *certStatus = crypto_cssm_check_x509cert_dates(certificateRef);
+       }
                
 end:
+    if (identityRef)
+               CFRelease(identityRef);
        if (certificateRef)
                CFRelease(certificateRef);
-       if (identityRef)
-               CFRelease(identityRef);
-       if (idSearchRef)
-               CFRelease(idSearchRef);
-       if (keychainRef)
-               CFRelease(keychainRef);
-
+       if (persistFind)
+               CFRelease(persistFind);
+       if (certData)
+               CFRelease(certData);
+       
        if (status != noErr && status != -1) {
-               plog(LLV_ERROR, LOCATION, NULL
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
+               plog(ASL_LEVEL_ERR
+                       "get_x509cert error %d %s.\n", (int)status, GetSecurityErrorString(status));
                status = -1;
        }                       
        return cert;
 
 }
 
-
-/*
- * Find a policy ref by OID
- */
-static OSStatus FindPolicy(const CSSM_OID *policyOID, SecPolicyRef *policyRef)
-{
-       
-       OSStatus                        status;
-       SecPolicySearchRef      searchRef = nil;
-       
-       status = SecPolicySearchCreate(CSSM_CERT_X_509v3, policyOID, NULL, &searchRef);
-       if (status != noErr)
-               goto end;
-               
-       status = SecPolicySearchCopyNext(searchRef, policyRef);
-       
-end:
-       if (searchRef)
-               CFRelease(searchRef);
-
-       if (status != noErr) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
-               status = -1;
-       }                       
-       return status;
-}
-               
-
 /*
  * Evaluate the trust of a cert using the policy provided
  */
-static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef)
+static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef)
 {
        OSStatus                                        status;
        SecTrustRef                                     trustRef = 0;
        SecTrustResultType                      evalResult;
+
+       CFArrayRef                                      errorStrings;
        
-       SecCertificateRef                       evalCertArray[1] = { cert };
-       
-       CFArrayRef                      cfCertRef = CFArrayCreate((CFAllocatorRef) NULL, (void*)evalCertArray, 1,
-                                                                               &kCFTypeArrayCallBacks);
+       CFArrayRef      cfCertRef = CFArrayCreate((CFAllocatorRef) NULL, (void*)evalCertArray, evalCertArrayNumValues,
+                                                               &kCFTypeArrayCallBacks);
                                                                                
        if (!cfCertRef) {
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                        "unable to create CFArray.\n");         
                return -1;
        }
@@ -393,17 +468,77 @@ static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef)
        status = SecTrustCreateWithCertificates(cfCertRef, policyRef, &trustRef);
        if (status != noErr)
                goto end;
-               
+
        status = SecTrustEvaluate(trustRef, &evalResult);
        if (status != noErr)
                goto end;
        
        if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "error evaluating certificate.\n");
+               plog(ASL_LEVEL_ERR, "Error evaluating certificate.\n");
+
+               switch (evalResult) {
+                       case kSecTrustResultInvalid:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultInvalid.\n");
+                               break;
+                       case kSecTrustResultProceed:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultProceed.\n");
+                               break;
+                       case kSecTrustResultDeny:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultDeny.\n");
+                               break;
+                       case kSecTrustResultUnspecified:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultUnspecified.\n");
+                               break;
+                       case kSecTrustResultRecoverableTrustFailure:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
+                               break;
+                       case kSecTrustResultFatalTrustFailure:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultFatalTrustFailure.\n");
+                               break;
+                       case kSecTrustResultOtherError:
+                               plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultOtherError.\n");
+                               break;
+                       default:
+                               plog(ASL_LEVEL_DEBUG, "eval result unknown: value = %d.\n", (int)evalResult);
+                               break;
+               }
+
+               errorStrings =  SecTrustCopyProperties(trustRef);
+               if (errorStrings) {
+                       
+                       CFDictionaryRef dict;
+                       CFStringRef val;
+                       const char *str;        
+                       CFIndex count, maxcount = CFArrayGetCount(errorStrings);
+               
+                       plog(ASL_LEVEL_ERR, "---------------Returned error strings: ---------------.\n");
+                       for (count = 0; count < maxcount; count++) {
+                               dict = CFArrayGetValueAtIndex(errorStrings, count);
+                               if (dict && (CFGetTypeID(dict) == CFDictionaryGetTypeID())) {
+                                       val = CFDictionaryGetValue(dict, kSecPropertyKeyType);
+                                       if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
+                                               str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);    
+                                               if (str)                
+                                                       plog(ASL_LEVEL_ERR, "type = %s.\n", str);
+                                       }
+                                       val = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
+                                       if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
+                                               str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);    
+                                               if (str)                
+                                                       plog(ASL_LEVEL_ERR, "value = %s.\n", str);
+                                       }
+                               }
+                       }
+                       plog(ASL_LEVEL_ERR, "-----------------------------------------------------.\n");                        
+                       CFRelease(errorStrings);
+               }
+                               
                status = -1;
+               goto end;
        }
                        
+       /* get and return the public key */
+       *publicKeyRef = SecTrustCopyPublicKey(trustRef);
        
 end:
        if (cfCertRef)
@@ -412,40 +547,13 @@ end:
                CFRelease(trustRef);
 
        if (status != noErr && status != -1) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
-               status = -1;
-       }                       
-       return status;
-}
-
-
-/*
- * Copy the system keychain
- */
-static OSStatus CopySystemKeychain(SecKeychainRef *keychainRef)
-{
-
-       OSStatus status;
-
-       status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
-       if (status != noErr)
-               goto end;
-
-       status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, keychainRef);
-       
-end:
-
-       if (status != noErr) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                       "error %d %s.\n", status, GetSecurityErrorString(status));
+               plog(ASL_LEVEL_ERR, 
+                       "EvaluateCert error %d %s.\n", (int)status, GetSecurityErrorString(status));
                status = -1;
        }                       
        return status;
-
 }
 
-
 /* 
  * Return string representation of Security-related OSStatus.
  */
@@ -455,16 +563,22 @@ GetSecurityErrorString(OSStatus err)
     switch(err) {
                case noErr:
                        return "noErr";
-               case memFullErr:
+       
+               /* SecBase.h: */
+               case errSecNotAvailable:
+                       return "errSecNotAvailable";
+
+#if !TARGET_OS_EMBEDDED
+        case memFullErr:
                        return "memFullErr";
                case paramErr:
                        return "paramErr";
                case unimpErr:
                        return "unimpErr";
-       
-               /* SecBase.h: */
-               case errSecNotAvailable:
-                       return "errSecNotAvailable";
+#endif
+
+#ifndef HAVE_OPENSSL
+        /* SecBase.h: */
                case errSecReadOnly:
                        return "errSecReadOnly";
                case errSecAuthFailed:
@@ -479,10 +593,6 @@ GetSecurityErrorString(OSStatus err)
                        return "errSecDuplicateCallback";
                case errSecInvalidCallback:
                        return "errSecInvalidCallback";
-               case errSecDuplicateItem:
-                       return "errSecDuplicateItem";
-               case errSecItemNotFound:
-                       return "errSecItemNotFound";
                case errSecBufferTooSmall:
                        return "errSecBufferTooSmall";
                case errSecDataTooLarge:
@@ -529,6 +639,11 @@ GetSecurityErrorString(OSStatus err)
                        return "errSecNoAccessForItem";
                case errSecInvalidOwnerEdit:
                        return "errSecInvalidOwnerEdit";
+#endif
+               case errSecDuplicateItem:
+                       return "errSecDuplicateItem";
+               case errSecItemNotFound:
+                       return "errSecItemNotFound";
                default:
                        return "<unknown>";
     }