From ee5f17c73ddf6cea151be3383378b7972c71f538 Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 29 Jul 2020 21:07:50 +0000 Subject: [PATCH] Security-59306.140.5.tar.gz --- OSX/authd/process.c | 19 +++- OSX/libsecurityd/lib/eventlistener.cpp | 9 +- OSX/libsecurityd/lib/ssclient.cpp | 4 +- OSX/libsecurityd/lib/sscommon.h | 4 +- OSX/sec/Security/SecPolicy.c | 62 ++++++++++- OSX/sec/Security/SecPolicy.list | 3 + securityd/src/main.cpp | 35 +----- .../TrustTests/EvaluationTests/ECTests_data.h | 75 +++++++------ tests/TrustTests/EvaluationTests/NISTTests.m | 104 ++++++++++++++++++ .../EvaluationTests/TrustEvaluationTestCase.m | 4 + trust/headers/SecPolicyPriv.h | 36 ++++++ trust/trustd/SecPolicyServer.c | 74 ++++++------- 12 files changed, 304 insertions(+), 125 deletions(-) diff --git a/OSX/authd/process.c b/OSX/authd/process.c index da50d542..4e5b5c16 100644 --- a/OSX/authd/process.c +++ b/OSX/authd/process.c @@ -8,6 +8,7 @@ #include "authtoken.h" #include "authutilities.h" #include "ccaudit.h" +#include #include #include @@ -139,6 +140,12 @@ process_create(const audit_info_s * auditInfo, session_t session) proc->dispatch_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); check(proc->dispatch_queue != NULL); + // to have at least some code URL just for case later methods fail + int retval = proc_pidpath(proc->auditInfo.pid, proc->code_url, sizeof(proc->code_url)); + if ( retval <= 0 ) { + os_log_error(AUTHD_LOG, "process: PID %d pidpathfailed %d", proc->auditInfo.pid, retval); + } + CFMutableDictionaryRef codeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDataRef auditToken = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *)&auditInfo->opaqueToken, sizeof(auditInfo->opaqueToken), kCFAllocatorNull); if (auditToken) { @@ -152,13 +159,19 @@ process_create(const audit_info_s * auditInfo, session_t session) } status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &codeRef); CFReleaseSafe(codeDict); - if (status) { os_log_error(AUTHD_LOG, "process: PID %d failed to create code ref %d", proc->auditInfo.pid, (int)status); CFReleaseNull(proc); goto done; } + status = SecCodeCopyPath(codeRef, kSecCSDefaultFlags, &code_url); + if (status == errSecSuccess) { + CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)proc->code_url, sizeof(proc->code_url)); + } else { + os_log_error(AUTHD_LOG, "process: PID %d failed to get path %d", proc->auditInfo.pid, (int)status); + } + status = SecCodeCheckValidity(codeRef, kSecCSDefaultFlags, NULL); require_noerr_action(status, done, os_log_error(AUTHD_LOG, "process: PID %d SecCodeCheckValidity failed with %d", proc->auditInfo.pid, (int)status)); @@ -176,10 +189,6 @@ process_create(const audit_info_s * auditInfo, session_t session) value = NULL; } - if (SecCodeCopyPath(codeRef, kSecCSDefaultFlags, &code_url) == errSecSuccess) { - CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)proc->code_url, sizeof(proc->code_url)); - } - if (CFDictionaryGetValueIfPresent(code_info, kSecCodeInfoIdentifier, &value)) { if (CFGetTypeID(value) == CFStringGetTypeID()) { proc->code_identifier = _copy_cf_string(value, NULL); diff --git a/OSX/libsecurityd/lib/eventlistener.cpp b/OSX/libsecurityd/lib/eventlistener.cpp index efe37a67..ed26dbf8 100644 --- a/OSX/libsecurityd/lib/eventlistener.cpp +++ b/OSX/libsecurityd/lib/eventlistener.cpp @@ -42,14 +42,7 @@ typedef std::list EventListenerList; static const char* GetNotificationName () { - // the name we give the client depends on the value of the environment variable "SECURITYSERVER" - const char* name = getenv (SECURITYSERVER_BOOTSTRAP_ENV); - if (name == NULL) - { - name = SharedMemoryCommon::kDefaultSecurityMessagesName; - } - - return name; + return SharedMemoryCommon::kDefaultSecurityMessagesName; } diff --git a/OSX/libsecurityd/lib/ssclient.cpp b/OSX/libsecurityd/lib/ssclient.cpp index a6341b12..6f15092b 100644 --- a/OSX/libsecurityd/lib/ssclient.cpp +++ b/OSX/libsecurityd/lib/ssclient.cpp @@ -166,9 +166,7 @@ Port ClientSession::findSecurityd() { if (!mContactName) { - mContactName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); - if (!mContactName) - mContactName = SECURITYSERVER_BOOTSTRAP_NAME; + mContactName = SECURITYSERVER_BOOTSTRAP_NAME; } secinfo("SSclnt", "Locating %s", mContactName); diff --git a/OSX/libsecurityd/lib/sscommon.h b/OSX/libsecurityd/lib/sscommon.h index e0710366..96b37163 100644 --- a/OSX/libsecurityd/lib/sscommon.h +++ b/OSX/libsecurityd/lib/sscommon.h @@ -61,11 +61,9 @@ using MachPlusPlus::ReceivePort; // -// The default Mach bootstrap registration name for SecurityServer, -// and the environment variable to override it +// The Mach bootstrap registration name for SecurityServer // #define SECURITYSERVER_BOOTSTRAP_NAME "com.apple.SecurityServer" -#define SECURITYSERVER_BOOTSTRAP_ENV "SECURITYSERVER" // // Types of ACL bearers diff --git a/OSX/sec/Security/SecPolicy.c b/OSX/sec/Security/SecPolicy.c index bc7bb235..2e15999c 100644 --- a/OSX/sec/Security/SecPolicy.c +++ b/OSX/sec/Security/SecPolicy.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -2693,11 +2694,18 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void) { - if (SecIsInternalRelease()) { +#if RC_SEED_BUILD + // Seed builds permit the QA signer + return CreateConfigurationProfileSigner(true); +#else // !RC_SEED_BUILD + if (os_variant_has_internal_diagnostics("com.apple.security")) { + // Internal builds permit the QA signer return CreateConfigurationProfileSigner(true); } else { + // GM builds do not trust the QA signer return CreateConfigurationProfileSigner(false); } +#endif // !RC_SEED_BUILD } SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void) @@ -4175,3 +4183,55 @@ errOut: CFReleaseSafe(options); return result; } + +CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + // X509, ignoring date validity + SecPolicyAddBasicCertOptions(options); + + add_ku(options, kSecKeyUsageDigitalSignature); + + CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, + CFSTR("Escrow Service ID Key")); + + /* Exactly 2 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + + require(result = SecPolicyCreate(kSecPolicyAppleEscrowServiceIdKeySigning, + kSecPolicyNameEscrowServiceIdKeySigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + add_ku(options, kSecKeyUsageDigitalSignature); + + CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, + CFSTR("Effaceable Service ID Key")); + + /* Exactly 2 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + + require(result = SecPolicyCreate(kSecPolicyApplePCSEscrowServiceIdKeySigning, + kSecPolicyNamePCSEscrowServiceIdKeySigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} diff --git a/OSX/sec/Security/SecPolicy.list b/OSX/sec/Security/SecPolicy.list index c3ee5011..621b1855 100644 --- a/OSX/sec/Security/SecPolicy.list +++ b/OSX/sec/Security/SecPolicy.list @@ -101,3 +101,6 @@ POLICYMACRO(KeyTransparency, 93, E, KT, POLICYMACRO(LegacySSL, 94, E, legacySSL, , , LegacySSL) POLICYMACRO(Alisha, 95, E, Alisha, , Y, Alisha) POLICYMACRO(MeasuredBootPolicySigning, 96, E, MeasuredBootPolicySigning, , Y, MeasuredBootPolicySigning) +// 97-99 used on master +POLICYMACRO(EscrowServiceIdKeySigning, 100, E, AppleEscrowServiceIdKeySigning, , Y, EscrowServiceIdKeySigning) +POLICYMACRO(PCSEscrowServiceIdKeySigning, 101, E, ApplePCSEscrowServiceIdKeySigning, , Y, PCSEscrowServiceIdKeySigning) diff --git a/securityd/src/main.cpp b/securityd/src/main.cpp index 5eb758a8..e94f68b1 100644 --- a/securityd/src/main.cpp +++ b/securityd/src/main.cpp @@ -101,8 +101,6 @@ int main(int argc, char *argv[]) // program arguments (preset to defaults) bool debugMode = false; - const char *bootstrapName = NULL; - const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName; bool doFork = false; bool reExecute = false; int workerTimeout = 0; @@ -124,7 +122,7 @@ int main(int argc, char *argv[]) extern char *optarg; extern int optind; int arg; - while ((arg = getopt(argc, argv, "c:dE:imN:s:t:T:uvWX")) != -1) { + while ((arg = getopt(argc, argv, "c:dE:ims:t:T:uvWX")) != -1) { switch (arg) { case 'c': tokenCacheDir = optarg; @@ -141,9 +139,6 @@ int main(int argc, char *argv[]) case 'm': mdsIsInstalled = true; break; - case 'N': - bootstrapName = optarg; - break; case 's': smartCardOptions = optarg; break; @@ -174,30 +169,13 @@ int main(int argc, char *argv[]) } // take no non-option arguments - if (optind < argc) + if (optind < argc) { usage(argv[0]); - - // figure out the bootstrap name - if (!bootstrapName) { - bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); - if (!bootstrapName) - { - bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; - } - else - { -#ifndef __clang_analyzer__ - messagingName = bootstrapName; -#endif - } } - else - { -#ifndef __clang_analyzer__ - messagingName = bootstrapName; -#endif - } - + + const char *bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; + const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName; + // configure logging first if (debugMode) { Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); @@ -316,7 +294,6 @@ static void usage(const char *me) fprintf(stderr, "Usage: %s [-dwX]" "\n\t[-c tokencache] smartcard token cache directory" "\n\t[-e equivDatabase] path to code equivalence database" - "\n\t[-N serviceName] MACH service name" "\n\t[-s off|on|conservative|aggressive] smartcard operation level" "\n\t[-t maxthreads] [-T threadTimeout] server thread control" "\n", me); diff --git a/tests/TrustTests/EvaluationTests/ECTests_data.h b/tests/TrustTests/EvaluationTests/ECTests_data.h index dcdee64f..a4224def 100644 --- a/tests/TrustTests/EvaluationTests/ECTests_data.h +++ b/tests/TrustTests/EvaluationTests/ECTests_data.h @@ -698,43 +698,48 @@ unsigned char End_P521_combined_SHA512_cer[733]={ 0x4F,0x29,0xC3,0xA9,0x04,0xE3,0xB9,0xCB,0xA3,0xF7,0xF0,0x80,0x5C,0x61,0xCF,0x1F, 0x8B,0xEE,0x79,0xBD,0x16,0x2D,0x5B,0xF3,0xBD,0xF2,0x84,0x49,0xF8, }; + +/* The signature of this root has been invalidated in order to add Basic Constraints + * in support of . Because the root is treated as an anchor by the tests, + * the invalid signature does not cause the tests to fail. */ /* subject:/CN=\x00R\x00O\x00O\x00T\x00_\x00P\x002\x005\x006 */ /* issuer :/CN=\x00R\x00O\x00O\x00T\x00_\x00P\x002\x005\x006 */ -unsigned char RootP256_cer[539]={ - 0x30,0x82,0x02,0x17,0x30,0x82,0x01,0xB0,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x8F, - 0x92,0x09,0xDB,0xA4,0xFC,0xDA,0xA1,0x45,0xC2,0xFA,0x59,0x87,0xC6,0xEA,0xE6,0x30, - 0x18,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x30,0x0D,0x06,0x09,0x60,0x86, - 0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x30,0x1D,0x31,0x1B,0x30,0x19,0x06, - 0x03,0x55,0x04,0x03,0x1E,0x12,0x00,0x52,0x00,0x4F,0x00,0x4F,0x00,0x54,0x00,0x5F, - 0x00,0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x30,0x1E,0x17,0x0D,0x30,0x31,0x30,0x34, - 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x30,0x31,0x32,0x33, - 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x1D,0x31,0x1B,0x30,0x19,0x06,0x03, - 0x55,0x04,0x03,0x1E,0x12,0x00,0x52,0x00,0x4F,0x00,0x4F,0x00,0x54,0x00,0x5F,0x00, - 0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42, - 0x00,0x04,0x85,0x59,0x2A,0x87,0x8E,0x6A,0x9B,0xB9,0x19,0xD4,0x73,0x82,0x24,0xC1, - 0x03,0x15,0xB3,0xF1,0x70,0x88,0x1B,0xAA,0xBA,0x57,0xE8,0x76,0x9F,0xC0,0xCE,0xF6, - 0xA9,0xBB,0x19,0xF5,0x6B,0x09,0x63,0xFB,0x69,0xA1,0x3D,0x88,0x67,0x3E,0x7E,0x1F, - 0x7B,0x18,0xC8,0xF2,0x31,0xE6,0xD7,0x54,0xD5,0xA7,0xAA,0x09,0x9C,0x15,0xD1,0x8D, - 0x37,0x7F,0xA3,0x81,0xC3,0x30,0x81,0xC0,0x30,0x81,0xBD,0x06,0x0F,0x2B,0x06,0x01, - 0x04,0x01,0x82,0x37,0x13,0x82,0xDF,0x67,0x86,0xA3,0x53,0x01,0x04,0x81,0xA9,0x30, - 0x81,0xA6,0x04,0x12,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x53, - 0x61,0x6D,0x70,0x6C,0x65,0x00,0x04,0x0A,0x52,0x4F,0x4F,0x54,0x5F,0x50,0x32,0x35, - 0x36,0x00,0x02,0x01,0x00,0x02,0x01,0x00,0x04,0x14,0x45,0x00,0x43,0x00,0x44,0x00, - 0x53,0x00,0x41,0x00,0x5F,0x00,0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x00,0x04,0x68, - 0x45,0x43,0x53,0x32,0x20,0x00,0x00,0x00,0x85,0x59,0x2A,0x87,0x8E,0x6A,0x9B,0xB9, - 0x19,0xD4,0x73,0x82,0x24,0xC1,0x03,0x15,0xB3,0xF1,0x70,0x88,0x1B,0xAA,0xBA,0x57, - 0xE8,0x76,0x9F,0xC0,0xCE,0xF6,0xA9,0xBB,0x19,0xF5,0x6B,0x09,0x63,0xFB,0x69,0xA1, - 0x3D,0x88,0x67,0x3E,0x7E,0x1F,0x7B,0x18,0xC8,0xF2,0x31,0xE6,0xD7,0x54,0xD5,0xA7, - 0xAA,0x09,0x9C,0x15,0xD1,0x8D,0x37,0x7F,0x61,0x97,0x7D,0x85,0xBF,0x7E,0x4E,0xD5, - 0x70,0x08,0xF2,0xE8,0xB5,0xBC,0x39,0x59,0xB3,0x23,0x97,0x5F,0xD4,0xCB,0x63,0x74, - 0xB9,0x88,0x6D,0xD6,0xF4,0xB8,0x20,0xA8,0x30,0x18,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x04,0x03,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, - 0x05,0x00,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x44,0xC4,0xBD,0x7A,0xDE,0x6F,0x41, - 0xA6,0x78,0x82,0xFD,0x32,0xB7,0x55,0xCA,0xE3,0x21,0x01,0x1C,0xD5,0x6A,0x0B,0x19, - 0xA4,0xA9,0x4D,0x06,0x6F,0xB2,0xE8,0xBF,0x9E,0x02,0x20,0x20,0x1C,0x24,0xEA,0x39, - 0x24,0xEB,0x91,0xBE,0x73,0x76,0xAF,0xFC,0x99,0x60,0xEC,0x22,0xFD,0x43,0xBF,0xDA, - 0xF3,0x7F,0xE4,0x8E,0x6C,0xA5,0x46,0xBF,0x64,0x01,0x3D, +unsigned char RootP256_cer[]={ + 0x30, 0x82, 0x02, 0x28, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x8f, + 0x92, 0x09, 0xdb, 0xa4, 0xfc, 0xda, 0xa1, 0x45, 0xc2, 0xfa, 0x59, 0x87, 0xc6, 0xea, 0xe6, 0x30, + 0x18, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x1e, 0x12, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x5f, + 0x00, 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x34, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, 0x33, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x1e, 0x12, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x5f, 0x00, + 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, + 0x00, 0x04, 0x85, 0x59, 0x2a, 0x87, 0x8e, 0x6a, 0x9b, 0xb9, 0x19, 0xd4, 0x73, 0x82, 0x24, 0xc1, + 0x03, 0x15, 0xb3, 0xf1, 0x70, 0x88, 0x1b, 0xaa, 0xba, 0x57, 0xe8, 0x76, 0x9f, 0xc0, 0xce, 0xf6, + 0xa9, 0xbb, 0x19, 0xf5, 0x6b, 0x09, 0x63, 0xfb, 0x69, 0xa1, 0x3d, 0x88, 0x67, 0x3e, 0x7e, 0x1f, + 0x7b, 0x18, 0xc8, 0xf2, 0x31, 0xe6, 0xd7, 0x54, 0xd5, 0xa7, 0xaa, 0x09, 0x9c, 0x15, 0xd1, 0x8d, + 0x37, 0x7f, 0xa3, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x81, 0xbd, 0x06, 0x0f, 0x2b, 0x06, + 0x01, 0x04, 0x01, 0x82, 0x37, 0x13, 0x82, 0xdf, 0x67, 0x86, 0xa3, 0x53, 0x01, 0x04, 0x81, 0xa9, + 0x30, 0x81, 0xa6, 0x04, 0x12, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x04, 0x0a, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x32, + 0x35, 0x36, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x04, 0x14, 0x45, 0x00, 0x43, 0x00, 0x44, + 0x00, 0x53, 0x00, 0x41, 0x00, 0x5f, 0x00, 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x04, + 0x68, 0x45, 0x43, 0x53, 0x32, 0x20, 0x00, 0x00, 0x00, 0x85, 0x59, 0x2a, 0x87, 0x8e, 0x6a, 0x9b, + 0xb9, 0x19, 0xd4, 0x73, 0x82, 0x24, 0xc1, 0x03, 0x15, 0xb3, 0xf1, 0x70, 0x88, 0x1b, 0xaa, 0xba, + 0x57, 0xe8, 0x76, 0x9f, 0xc0, 0xce, 0xf6, 0xa9, 0xbb, 0x19, 0xf5, 0x6b, 0x09, 0x63, 0xfb, 0x69, + 0xa1, 0x3d, 0x88, 0x67, 0x3e, 0x7e, 0x1f, 0x7b, 0x18, 0xc8, 0xf2, 0x31, 0xe6, 0xd7, 0x54, 0xd5, + 0xa7, 0xaa, 0x09, 0x9c, 0x15, 0xd1, 0x8d, 0x37, 0x7f, 0x61, 0x97, 0x7d, 0x85, 0xbf, 0x7e, 0x4e, + 0xd5, 0x70, 0x08, 0xf2, 0xe8, 0xb5, 0xbc, 0x39, 0x59, 0xb3, 0x23, 0x97, 0x5f, 0xd4, 0xcb, 0x63, + 0x74, 0xb9, 0x88, 0x6d, 0xd6, 0xf4, 0xb8, 0x20, 0xa8, 0x30, 0x18, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x44, 0xc4, 0xbd, 0x7a, 0xde, 0x6f, + 0x41, 0xa6, 0x78, 0x82, 0xfd, 0x32, 0xb7, 0x55, 0xca, 0xe3, 0x21, 0x01, 0x1c, 0xd5, 0x6a, 0x0b, + 0x19, 0xa4, 0xa9, 0x4d, 0x06, 0x6f, 0xb2, 0xe8, 0xbf, 0x9e, 0x02, 0x20, 0x20, 0x1c, 0x24, 0xea, + 0x39, 0x24, 0xeb, 0x91, 0xbe, 0x73, 0x76, 0xaf, 0xfc, 0x99, 0x60, 0xec, 0x22, 0xfd, 0x43, 0xbf, + 0xda, 0xf3, 0x7f, 0xe4, 0x8e, 0x6c, 0xa5, 0x46, 0xbf, 0x64, 0x01, 0x3d }; /* subject:/C=US/ST=CA/L=Mountain View/O=Sun Microsystems Laboratories/OU=Test CA (secp256r1)/CN=dev.experimentalstuff.com */ diff --git a/tests/TrustTests/EvaluationTests/NISTTests.m b/tests/TrustTests/EvaluationTests/NISTTests.m index 094fb916..7c192713 100644 --- a/tests/TrustTests/EvaluationTests/NISTTests.m +++ b/tests/TrustTests/EvaluationTests/NISTTests.m @@ -49,4 +49,108 @@ CFReleaseSafe(basicPolicy); } +- (void)testNoBasicConstraintsAnchor_UserTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidMissingbasicConstraintsTest1EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"MissingbasicConstraintsCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + + id persistentRef = [self addTrustSettingsForCert:ca]; + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraints); + } + + [self removeTrustSettingsForCert:ca persistentRef:persistentRef]; + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNoBasicConstraintsAnchor_AppTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidMissingbasicConstraintsTest1EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"MissingbasicConstraintsCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + NSArray *anchor = @[(__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + XCTAssertEqual(errSecSuccess, SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchor)); + + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraints); + } + + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNotCABasicConstraintsAnchor_UserTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidcAFalseTest2EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"basicConstraintsCriticalcAFalseCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + + id persistentRef = [self addTrustSettingsForCert:ca]; + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraintsCA); + } + + [self removeTrustSettingsForCert:ca persistentRef:persistentRef]; + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNotCABasicConstraintsAnchor_AppTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidcAFalseTest2EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"basicConstraintsCriticalcAFalseCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + NSArray *anchor = @[(__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + XCTAssertEqual(errSecSuccess, SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchor)); + + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraintsCA); + } + + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + @end diff --git a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m index 99f8383f..712566e9 100644 --- a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m +++ b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m @@ -181,6 +181,10 @@ const CFStringRef kTestSystemRootKey = CFSTR("TestSystemRoot"); { NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".cer" subdirectory:dir]; + if (!url) { + url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".crt" + subdirectory:dir]; + } NSData *certData = [NSData dataWithContentsOfURL:url]; if (!certData) { return nil; diff --git a/trust/headers/SecPolicyPriv.h b/trust/headers/SecPolicyPriv.h index 15019c8e..3927772e 100644 --- a/trust/headers/SecPolicyPriv.h +++ b/trust/headers/SecPolicyPriv.h @@ -191,6 +191,10 @@ extern const CFStringRef kSecPolicyAppleAlisha API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); extern const CFStringRef kSecPolicyAppleMeasuredBootPolicySigning API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyAppleEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); /*! @@ -1860,6 +1864,38 @@ __nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateMeasuredBootPolicySigning(void) API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +/*! + @function SecPolicyCreateEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + +/*! + @function SecPolicyCreatePCSEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying PCS Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + /* * Legacy functions (OS X only) */ diff --git a/trust/trustd/SecPolicyServer.c b/trust/trustd/SecPolicyServer.c index 2cec6688..e826197b 100644 --- a/trust/trustd/SecPolicyServer.c +++ b/trust/trustd/SecPolicyServer.c @@ -2945,7 +2945,6 @@ bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) { CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc); SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); CFIndex anchor_ix = SecPVCGetCertificateCount(pvc) - 1; - bool is_anchor = (ix == anchor_ix && SecPathBuilderIsAnchored(pvc->builder)); if (!SecCertificateIsValid(cert, verifyTime)) { /* Certificate has expired. */ @@ -2968,53 +2967,46 @@ bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) { } } - if (is_anchor) { - /* Perform anchor specific checks. */ - /* Don't think we have any of these. */ - } else { - /* Perform intermediate specific checks. */ - - /* (k) Basic constraints only relevant for v3 and later. */ - if (SecCertificateVersion(cert) >= 3) { - const SecCEBasicConstraints *bc = - SecCertificateGetBasicConstraints(cert); - if (!bc) { - /* Basic constraints not present, illegal. */ - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, - ix, kCFBooleanFalse, true)) { - goto errOut; - } - } else if (!bc->isCA) { - /* Basic constraints not marked as isCA, illegal. */ - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraintsCA, - ix, kCFBooleanFalse, true)) { - goto errOut; - } + /* (k) Basic constraints only relevant for v3 and later. */ + if (SecCertificateVersion(cert) >= 3) { + const SecCEBasicConstraints *bc = + SecCertificateGetBasicConstraints(cert); + if (!bc) { + /* Basic constraints not present, illegal. */ + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, + ix, kCFBooleanFalse, true)) { + goto errOut; } - } - /* For a v1 or v2 certificate in an intermediate slot (not a leaf and - not an anchor), we additionally require that the certificate chain - does not end in a v3 or later anchor. [rdar://32204517] */ - else if (ix > 0 && ix < anchor_ix) { - SecCertificateRef anchor = SecPVCGetCertificateAtIndex(pvc, anchor_ix); - if (SecCertificateVersion(anchor) >= 3) { - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, - ix, kCFBooleanFalse, true)) { - goto errOut; - } + } else if (!bc->isCA) { + /* Basic constraints not marked as isCA, illegal. */ + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraintsCA, + ix, kCFBooleanFalse, true)) { + goto errOut; } } - /* (l) max_path_length is checked elsewhere. */ - - /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */ - SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert); - if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) { - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage, - ix, kCFBooleanFalse, true)) { + } + /* For a v1 or v2 certificate in an intermediate slot (not a leaf and + not an anchor), we additionally require that the certificate chain + does not end in a v3 or later anchor. [rdar://32204517] */ + else if (ix > 0 && ix < anchor_ix) { + SecCertificateRef anchor = SecPVCGetCertificateAtIndex(pvc, anchor_ix); + if (SecCertificateVersion(anchor) >= 3) { + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, + ix, kCFBooleanFalse, true)) { goto errOut; } } } + /* (l) max_path_length is checked elsewhere. */ + + /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */ + SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert); + if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) { + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage, + ix, kCFBooleanFalse, true)) { + goto errOut; + } + } errOut: return SecPVCIsOkResult(pvc); -- 2.45.2