X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..8a50f688fe9358387648fb83fbfecbefe8d32669:/OSX/libsecurity_codesigning/lib/reqinterp.cpp?ds=inline diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index effd233e..b685802b 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 { @@ -146,6 +149,7 @@ bool Requirement::Interpreter::eval(int depth) Match match(*this); return certFieldValue(key, match, cert); } +#if TARGET_OS_OSX case opCertGeneric: { SecCertificateRef cert = mContext->cert(get()); @@ -160,6 +164,7 @@ bool Requirement::Interpreter::eval(int depth) Match match(*this); return certFieldPolicy(key, match, cert); } +#endif case opTrustedCert: return trustedCert(get()); case opTrustedCerts: @@ -187,7 +192,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); } } @@ -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) { +// 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; @@ -244,13 +251,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,19 +267,21 @@ 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()); +#endif 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 @@ -295,7 +305,7 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match & { return cert && certificateHasPolicy(cert, oid) && match(kCFBooleanTrue); } - +#endif // // 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)) - 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; } @@ -331,12 +411,16 @@ bool Requirement::Interpreter::verifyAnchor(SecCertificateRef cert, const unsign { // get certificate bytes if (cert) { + SHA1 hasher; +#if TARGET_OS_OSX CSSM_DATA certData; MacOSError::check(SecCertificateGetData(cert, &certData)); // verify hash - SHA1 hasher; hasher(certData.Data, certData.Length); +#else + hasher(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert)); +#endif return hasher.verify(digest); } return false; @@ -394,6 +478,8 @@ bool Requirement::Interpreter::trustedCert(int slot) // 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; @@ -431,6 +517,9 @@ SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef ::free(errors); MacOSError::throwMe(rc); } +#else + return kSecTrustSettingsResultUnspecified; +#endif }