X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..b04fe171f0375ecd5d8a24747ca1dff85720a0ca:/OSX/libsecurity_codesigning/lib/reqinterp.cpp diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index effd233e..3215df48 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include "csutilities.h" namespace Security { @@ -187,7 +190,7 @@ bool Requirement::Interpreter::eval(int depth) } } // 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); } } @@ -244,13 +247,14 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma { "subject.UID", &CSSMOID_UserID }, { NULL, NULL } }; - + // DN-component single-value match for (const CertField *cf = certFields; cf->name; cf++) if (cf->name == key) { CFRef 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); @@ -259,15 +263,16 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma // email multi-valued match (any of...) if (key == "email") { CFRef 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 - secdebug("csinterp", "cert field notation \"%s\" not understood", key.c_str()); + secinfo("csinterp", "cert field notation \"%s\" not understood", key.c_str()); return false; } @@ -303,23 +308,93 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match & 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; } +static CFStringRef kAMFINVRAMTrustedKeys = CFSTR("AMFITrustedKeys"); + +CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors() +{ + __block CFRef keys = makeCFMutableArray(0); + + try { + io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if (entry == IO_OBJECT_NULL) + return NULL; + + CFRef configData = (CFDataRef)IORegistryEntryCreateCFProperty(entry, kAMFINVRAMTrustedKeys, kCFAllocatorDefault, 0); + IOObjectRelease(entry); + if (!configData) + return NULL; + + CFRef 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 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() { - 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; + } else if (appleLocalAnchored()) { + return true; + } return false; }