]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_codesigning/lib/reqinterp.cpp
Security-58286.31.2.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / reqinterp.cpp
index effd233ee54c8f82e4fa0d8dd44caadd923fad4c..b685802b5c6568d2a7f82dfb9cd18b8056f5df81 100644 (file)
@@ -30,6 +30,9 @@
 #include <Security/SecCertificatePriv.h>
 #include <security_utilities/memutils.h>
 #include <security_utilities/logging.h>
 #include <Security/SecCertificatePriv.h>
 #include <security_utilities/memutils.h>
 #include <security_utilities/logging.h>
+#include <sys/csr.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFUnserialize.h>
 #include "csutilities.h"
 
 namespace Security {
 #include "csutilities.h"
 
 namespace Security {
@@ -146,6 +149,7 @@ bool Requirement::Interpreter::eval(int depth)
                        Match match(*this);
                        return certFieldValue(key, match, cert);
                }
                        Match match(*this);
                        return certFieldValue(key, match, cert);
                }
+#if TARGET_OS_OSX
        case opCertGeneric:
                {
                        SecCertificateRef cert = mContext->cert(get<int32_t>());
        case opCertGeneric:
                {
                        SecCertificateRef cert = mContext->cert(get<int32_t>());
@@ -160,6 +164,7 @@ bool Requirement::Interpreter::eval(int depth)
                        Match match(*this);
                        return certFieldPolicy(key, match, cert);
                }
                        Match match(*this);
                        return certFieldPolicy(key, match, cert);
                }
+#endif
        case opTrustedCert:
                return trustedCert(get<int32_t>());
        case opTrustedCerts:
        case opTrustedCert:
                return trustedCert(get<int32_t>());
        case opTrustedCerts:
@@ -187,7 +192,7 @@ bool Requirement::Interpreter::eval(int depth)
                        }
                }
                // unrecognized opcode and no way to interpret it
                        }
                }
                // unrecognized opcode and no way to interpret it
-               secdebug("csinterp", "opcode 0x%x cannot be handled; aborting", op);
+               secinfo("csinterp", "opcode 0x%x cannot be handled; aborting", op);
                MacOSError::throwMe(errSecCSUnimplemented);
        }
 }
                MacOSError::throwMe(errSecCSUnimplemented);
        }
 }
@@ -219,6 +224,8 @@ bool Requirement::Interpreter::entitlementValue(const string &key, const Match &
 
 bool Requirement::Interpreter::certFieldValue(const string &key, const Match &match, SecCertificateRef cert)
 {
 
 bool Requirement::Interpreter::certFieldValue(const string &key, const Match &match, SecCertificateRef cert)
 {
+// XXX: Not supported on embedded yet due to lack of supporting API
+#if TARGET_OS_OSX
        // no cert, no chance
        if (cert == NULL)
                return false;
        // no cert, no chance
        if (cert == NULL)
                return false;
@@ -244,13 +251,14 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma
                { "subject.UID", &CSSMOID_UserID },
                { NULL, NULL }
        };
                { "subject.UID", &CSSMOID_UserID },
                { NULL, NULL }
        };
-       
+
        // DN-component single-value match
        for (const CertField *cf = certFields; cf->name; cf++)
                if (cf->name == key) {
                        CFRef<CFStringRef> value;
        // DN-component single-value match
        for (const CertField *cf = certFields; cf->name; cf++)
                if (cf->name == key) {
                        CFRef<CFStringRef> value;
-                       if (OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref())) {
-                               secdebug("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc);
+            OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref());
+                       if (rc) {
+                               secinfo("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc);
                                return false;
                        }
                        return match(value);
                                return false;
                        }
                        return match(value);
@@ -259,19 +267,21 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma
        // email multi-valued match (any of...)
        if (key == "email") {
                CFRef<CFArrayRef> value;
        // email multi-valued match (any of...)
        if (key == "email") {
                CFRef<CFArrayRef> value;
-               if (OSStatus rc = SecCertificateCopyEmailAddresses(cert, &value.aref())) {
-                       secdebug("csinterp", "cert %p lookup for email failed rc=%d", cert, (int)rc);
+        OSStatus rc = SecCertificateCopyEmailAddresses(cert, &value.aref());
+               if (rc) {
+                       secinfo("csinterp", "cert %p lookup for email failed rc=%d", cert, (int)rc);
                        return false;
                }
                return match(value);
        }
 
        // unrecognized key. Fail but do not abort to promote backward compatibility down the road
                        return false;
                }
                return match(value);
        }
 
        // unrecognized key. Fail but do not abort to promote backward compatibility down the road
-       secdebug("csinterp", "cert field notation \"%s\" not understood", key.c_str());
+       secinfo("csinterp", "cert field notation \"%s\" not understood", key.c_str());
+#endif
        return false;
 }
 
        return false;
 }
 
-       
+#if TARGET_OS_OSX
 bool Requirement::Interpreter::certFieldGeneric(const string &key, const Match &match, SecCertificateRef cert)
 {
        // the key is actually a (binary) OID value
 bool Requirement::Interpreter::certFieldGeneric(const string &key, const Match &match, SecCertificateRef cert)
 {
        // the key is actually a (binary) OID value
@@ -295,7 +305,7 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match &
 {
        return cert && certificateHasPolicy(cert, oid) && match(kCFBooleanTrue);
 }
 {
        return cert && certificateHasPolicy(cert, oid) && match(kCFBooleanTrue);
 }
-
+#endif
 
 //
 // Check the Apple-signed condition
 
 //
 // Check the Apple-signed condition
@@ -303,23 +313,93 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match &
 bool Requirement::Interpreter::appleAnchored()
 {
        if (SecCertificateRef cert = mContext->cert(anchorCert))
 bool Requirement::Interpreter::appleAnchored()
 {
        if (SecCertificateRef cert = mContext->cert(anchorCert))
-               if (isAppleCA(cert)
-#if defined(TEST_APPLE_ANCHOR)
-                       || verifyAnchor(cert, testAppleAnchorHash())
-#endif
-               )
+               if (isAppleCA(cert))
                return true;
        return false;
 }
 
                return true;
        return false;
 }
 
+static CFStringRef kAMFINVRAMTrustedKeys = CFSTR("AMFITrustedKeys");
+
+CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors()
+{
+    __block CFRef<CFMutableArrayRef> keys = makeCFMutableArray(0);
+
+    try {
+        io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
+        if (entry == IO_OBJECT_NULL)
+            return NULL;
+
+        CFRef<CFDataRef> configData = (CFDataRef)IORegistryEntryCreateCFProperty(entry, kAMFINVRAMTrustedKeys, kCFAllocatorDefault, 0);
+        IOObjectRelease(entry);
+        if (!configData)
+            return NULL;
+
+        CFRef<CFDictionaryRef> configDict = CFDictionaryRef(IOCFUnserializeWithSize((const char *)CFDataGetBytePtr(configData),
+                                                                                    (size_t)CFDataGetLength(configData),
+                                                                                    kCFAllocatorDefault, 0, NULL));
+        if (!configDict)
+            return NULL;
+
+        CFArrayRef trustedKeys = CFArrayRef(CFDictionaryGetValue(configDict, CFSTR("trustedKeys")));
+        if (!trustedKeys && CFGetTypeID(trustedKeys) != CFArrayGetTypeID())
+            return NULL;
+
+        cfArrayApplyBlock(trustedKeys, ^(const void *value) {
+            CFDictionaryRef key = CFDictionaryRef(value);
+            if (!key && CFGetTypeID(key) != CFDictionaryGetTypeID())
+                return;
+
+            CFDataRef hash = CFDataRef(CFDictionaryGetValue(key, CFSTR("certDigest")));
+            if (!hash && CFGetTypeID(hash) != CFDataGetTypeID())
+                return;
+            CFArrayAppendValue(keys, hash);
+        });
+
+    } catch (...) {
+    }
+
+    if (CFArrayGetCount(keys) == 0)
+        return NULL;
+
+    return keys.yield();
+}
+
+bool Requirement::Interpreter::appleLocalAnchored()
+{
+    static CFArrayRef additionalTrustedCertificates = NULL;
+
+    if (csr_check(CSR_ALLOW_APPLE_INTERNAL))
+        return false;
+
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        additionalTrustedCertificates = getAdditionalTrustedAnchors();
+    });
+
+    if (additionalTrustedCertificates == NULL)
+        return false;
+
+    CFRef<CFDataRef> hash = SecCertificateCopySHA256Digest(mContext->cert(leafCert));
+    if (!hash)
+        return false;
+
+    if (CFArrayContainsValue(additionalTrustedCertificates, CFRangeMake(0, CFArrayGetCount(additionalTrustedCertificates)), hash))
+        return true;
+
+    return false;
+}
+
 bool Requirement::Interpreter::appleSigned()
 {
 bool Requirement::Interpreter::appleSigned()
 {
-       if (appleAnchored())
+    if (appleAnchored()) {
                if (SecCertificateRef intermed = mContext->cert(-2))    // first intermediate
                        // first intermediate common name match (exact)
                        if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed)
                                        && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed))
                                return true;
                if (SecCertificateRef intermed = mContext->cert(-2))    // first intermediate
                        // first intermediate common name match (exact)
                        if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed)
                                        && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed))
                                return true;
+    } else if (appleLocalAnchored()) {
+        return true;
+    }
        return false;
 }
 
        return false;
 }
 
@@ -331,12 +411,16 @@ bool Requirement::Interpreter::verifyAnchor(SecCertificateRef cert, const unsign
 {
        // get certificate bytes
        if (cert) {
 {
        // get certificate bytes
        if (cert) {
+        SHA1 hasher;
+#if TARGET_OS_OSX
                CSSM_DATA certData;
                MacOSError::check(SecCertificateGetData(cert, &certData));
                
                // verify hash
                CSSM_DATA certData;
                MacOSError::check(SecCertificateGetData(cert, &certData));
                
                // verify hash
-               SHA1 hasher;
                hasher(certData.Data, certData.Length);
                hasher(certData.Data, certData.Length);
+#else
+        hasher(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert));
+#endif
                return hasher.verify(digest);
        }
        return false;
                return hasher.verify(digest);
        }
        return false;
@@ -394,6 +478,8 @@ bool Requirement::Interpreter::trustedCert(int slot)
 //
 SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef cert, bool isAnchor)
 {
 //
 SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef cert, bool isAnchor)
 {
+    // XXX: Not supported on embedded yet due to lack of supporting API
+#if TARGET_OS_OSX
        // the SPI input is the uppercase hex form of the SHA-1 of the certificate...
        assert(cert);
        SHA1::Digest digest;
        // the SPI input is the uppercase hex form of the SHA-1 of the certificate...
        assert(cert);
        SHA1::Digest digest;
@@ -431,6 +517,9 @@ SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef
                ::free(errors);
                MacOSError::throwMe(rc);
        }
                ::free(errors);
                MacOSError::throwMe(rc);
        }
+#else
+    return kSecTrustSettingsResultUnspecified;
+#endif
 }
 
 
 }