#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 {
}
}
// 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);
}
}
{ "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;
- 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);
// 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
- secdebug("csinterp", "cert field notation \"%s\" not understood", key.c_str());
+ secinfo("csinterp", "cert field notation \"%s\" not understood", key.c_str());
return false;
}
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<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()
{
- 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;
}