From 67d61d2eddbf13b089421b1c08b0353e50c467d7 Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 18 Dec 2020 07:48:56 +0000 Subject: [PATCH] Security-59754.60.13.tar.gz --- Analytics/Clients/LocalKeychainAnalytics.m | 23 +- OSX/Modules | 1 + OSX/authd/authorization.plist | 26 + OSX/authd/engine.c | 2 +- OSX/include/security_asn1 | 1 + OSX/include/security_cdsa_client | 1 + OSX/include/security_cdsa_plugin | 1 + OSX/include/security_cdsa_utilities | 1 + OSX/include/security_cdsa_utils | 1 + OSX/include/security_codesigning | 1 + OSX/include/security_comcryption | 1 + OSX/include/security_cryptkit | 1 + OSX/include/security_filedb | 1 + OSX/include/security_keychain | 1 + OSX/include/security_ocspd | 1 + OSX/include/security_pkcs12 | 1 + OSX/include/security_smime | 1 + OSX/include/security_utilities | 1 + OSX/include/securityd_client | 1 + OSX/libsecurity_asn1/security_asn1 | 1 + .../lib/Authorization.c | 1 + OSX/libsecurity_codesigning/lib/SecCodePriv.h | 2 +- .../lib/SecStaticCode.cpp | 1 + .../lib/StaticCode.cpp | 17 +- .../lib/bundlediskrep.cpp | 14 +- .../lib/bundlediskrep.h | 2 +- .../lib/csutilities.cpp | 206 ++++++++ OSX/libsecurity_codesigning/lib/csutilities.h | 18 + OSX/libsecurity_keychain/Security | 1 + OSX/libsecurity_ssl/Security | 1 + OSX/libsecurity_ssl/security_ssl | 1 + OSX/sec/ipc/com.apple.secd.plist | 7 + OSX/sec/ipc/com.apple.securityd.plist | 7 + OSX/sec/ipc/server.c | 8 + OSX/utilities/SecCoreAnalytics.h | 1 + OSX/utilities/SecCoreAnalytics.m | 68 +++ RegressionTests/Security.plist | 12 + RegressionTests/bats_utd_plist.h | 5 + RegressionTests/secsecstaticcodeapitest.c | 229 +++++++++ Security.exp-in | 1 + Security.xcodeproj/project.pbxproj | 149 ++++++ keychain/TrustedPeersHelper/Container.swift | 20 +- .../FakeCuttlefish.swift | 12 +- .../MockCuttlefish.swift | 7 + ...ustedPeersHelperUnitTests-BridgingHeader.h | 1 + keychain/ckks/CKKSAnalytics.h | 1 + keychain/ckks/CKKSAnalytics.m | 1 + ...scrowRequestPerformEscrowEnrollOperation.m | 5 + keychain/ot/OTCuttlefishContext.m | 6 + keychain/ot/OTManager.m | 11 + .../ot/tests/octagon/OctagonTests+CKKS.swift | 14 + .../octagon/OctagonTests+EscrowRecords.swift | 116 +++++ keychain/securityd/com.apple.secd.sb | 1 + libsecurity_smime/Security | 1 + libsecurity_smime/security_smime | 1 + .../EvaluationTests/CARevocationTests.m | 198 ++++++++ .../EvaluationTests/CARevocationTests_data.h | 461 ++++++++++++++++++ 57 files changed, 1652 insertions(+), 23 deletions(-) create mode 120000 OSX/Modules create mode 120000 OSX/include/security_asn1 create mode 120000 OSX/include/security_cdsa_client create mode 120000 OSX/include/security_cdsa_plugin create mode 120000 OSX/include/security_cdsa_utilities create mode 120000 OSX/include/security_cdsa_utils create mode 120000 OSX/include/security_codesigning create mode 120000 OSX/include/security_comcryption create mode 120000 OSX/include/security_cryptkit create mode 120000 OSX/include/security_filedb create mode 120000 OSX/include/security_keychain create mode 120000 OSX/include/security_ocspd create mode 120000 OSX/include/security_pkcs12 create mode 120000 OSX/include/security_smime create mode 120000 OSX/include/security_utilities create mode 120000 OSX/include/securityd_client create mode 120000 OSX/libsecurity_asn1/security_asn1 create mode 120000 OSX/libsecurity_keychain/Security create mode 120000 OSX/libsecurity_ssl/Security create mode 120000 OSX/libsecurity_ssl/security_ssl create mode 100644 RegressionTests/secsecstaticcodeapitest.c create mode 120000 libsecurity_smime/Security create mode 120000 libsecurity_smime/security_smime create mode 100644 tests/TrustTests/EvaluationTests/CARevocationTests.m create mode 100644 tests/TrustTests/EvaluationTests/CARevocationTests_data.h diff --git a/Analytics/Clients/LocalKeychainAnalytics.m b/Analytics/Clients/LocalKeychainAnalytics.m index 9eabc0ac..22c40fca 100644 --- a/Analytics/Clients/LocalKeychainAnalytics.m +++ b/Analytics/Clients/LocalKeychainAnalytics.m @@ -155,14 +155,21 @@ NSString* const LKABackupLastSuccessDate = @"backupLastSuccess"; [self logSuccessForEventNamed:LKAEventBackup timestampBucket:SFAnalyticsTimestampBucketHour]; } else { NSInteger daysSinceSuccess = [SFAnalytics fuzzyDaysSinceDate:[self datePropertyForKey:LKABackupLastSuccessDate]]; - [self logResultForEvent:LKAEventBackup - hardFailure:YES - result:error - withAttributes:@{@"daysSinceSuccess" : @(daysSinceSuccess), - @"duration" : @(backupDuration), - @"type" : @(_backupType), - } - timestampBucket:SFAnalyticsTimestampBucketHour]; + + // Backups fail all the time due to devices being locked. If a backup has happened recently, + // let's not even report it, to avoid crowding out more useful data + bool boringError = error.code == errSecInteractionNotAllowed && daysSinceSuccess == 0; + + if(!boringError) { + [self logResultForEvent:LKAEventBackup + hardFailure:YES + result:error + withAttributes:@{@"daysSinceSuccess" : @(daysSinceSuccess), + @"duration" : @(backupDuration), + @"type" : @(_backupType), + } + timestampBucket:SFAnalyticsTimestampBucketHour]; + } } } diff --git a/OSX/Modules b/OSX/Modules new file mode 120000 index 00000000..287aeb42 --- /dev/null +++ b/OSX/Modules @@ -0,0 +1 @@ +./Modules \ No newline at end of file diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index 4236dff6..c3b4ffe9 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -1775,6 +1775,17 @@ See remaining rules for examples. shared + com.apple.system-migration.launch-password + + comment + Used by Migration Assistant. + class + rule + rule + authenticate-admin-nonshared-password + shared + + com.apple.system-migration.cleanup comment @@ -1879,6 +1890,21 @@ See remaining rules for examples. version 1 + authenticate-admin-nonshared-password + + class + user + comment + Authenticate as an administrator with the password. + group + admin + password-only + + timeout + 30 + version + 1 + _mbsetupuser-nonshared class diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 08a4f80e..92648f01 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -1414,10 +1414,10 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en } os_log_debug(AUTHD_LOG, "engine %lld: using rule %{public}s", engine->engine_index, rule_name); + _set_right_hints(engine->hints, key); // set authorization right name for authorizationhost as well // only need the hints & mechanisms if we are going to show ui if (engine->flags & kAuthorizationFlagInteractionAllowed || engine->flags & kAuthorizationFlagSheet) { os_log_debug(AUTHD_LOG, "setting hints for UI authorization"); - _set_right_hints(engine->hints, key); _set_localization_hints(dbconn, engine->hints, rule); if (!engine->authenticateRule) { engine->authenticateRule = rule_create_with_string("authenticate", dbconn); diff --git a/OSX/include/security_asn1 b/OSX/include/security_asn1 new file mode 120000 index 00000000..09ef0802 --- /dev/null +++ b/OSX/include/security_asn1 @@ -0,0 +1 @@ +./libsecurity_asn1/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_client b/OSX/include/security_cdsa_client new file mode 120000 index 00000000..9737c610 --- /dev/null +++ b/OSX/include/security_cdsa_client @@ -0,0 +1 @@ +./libsecurity_cdsa_client/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_plugin b/OSX/include/security_cdsa_plugin new file mode 120000 index 00000000..2be156f8 --- /dev/null +++ b/OSX/include/security_cdsa_plugin @@ -0,0 +1 @@ +./libsecurity_cdsa_plugin/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utilities b/OSX/include/security_cdsa_utilities new file mode 120000 index 00000000..2634481d --- /dev/null +++ b/OSX/include/security_cdsa_utilities @@ -0,0 +1 @@ +./libsecurity_cdsa_utilities/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utils b/OSX/include/security_cdsa_utils new file mode 120000 index 00000000..f3e5247e --- /dev/null +++ b/OSX/include/security_cdsa_utils @@ -0,0 +1 @@ +./libsecurity_cdsa_utils/lib \ No newline at end of file diff --git a/OSX/include/security_codesigning b/OSX/include/security_codesigning new file mode 120000 index 00000000..7c67092b --- /dev/null +++ b/OSX/include/security_codesigning @@ -0,0 +1 @@ +./libsecurity_codesigning/lib \ No newline at end of file diff --git a/OSX/include/security_comcryption b/OSX/include/security_comcryption new file mode 120000 index 00000000..cbcdf214 --- /dev/null +++ b/OSX/include/security_comcryption @@ -0,0 +1 @@ +./libsecurity_comcryption/lib \ No newline at end of file diff --git a/OSX/include/security_cryptkit b/OSX/include/security_cryptkit new file mode 120000 index 00000000..609dcc3b --- /dev/null +++ b/OSX/include/security_cryptkit @@ -0,0 +1 @@ +./libsecurity_cryptkit/lib \ No newline at end of file diff --git a/OSX/include/security_filedb b/OSX/include/security_filedb new file mode 120000 index 00000000..99185cdc --- /dev/null +++ b/OSX/include/security_filedb @@ -0,0 +1 @@ +./libsecurity_filedb/lib \ No newline at end of file diff --git a/OSX/include/security_keychain b/OSX/include/security_keychain new file mode 120000 index 00000000..aac53b6d --- /dev/null +++ b/OSX/include/security_keychain @@ -0,0 +1 @@ +./libsecurity_keychain/lib \ No newline at end of file diff --git a/OSX/include/security_ocspd b/OSX/include/security_ocspd new file mode 120000 index 00000000..449ea98b --- /dev/null +++ b/OSX/include/security_ocspd @@ -0,0 +1 @@ +./libsecurity_ocspd/common \ No newline at end of file diff --git a/OSX/include/security_pkcs12 b/OSX/include/security_pkcs12 new file mode 120000 index 00000000..8fdcb01e --- /dev/null +++ b/OSX/include/security_pkcs12 @@ -0,0 +1 @@ +./libsecurity_pkcs12/lib \ No newline at end of file diff --git a/OSX/include/security_smime b/OSX/include/security_smime new file mode 120000 index 00000000..e1a40bad --- /dev/null +++ b/OSX/include/security_smime @@ -0,0 +1 @@ +./libsecurity_smime/lib \ No newline at end of file diff --git a/OSX/include/security_utilities b/OSX/include/security_utilities new file mode 120000 index 00000000..4d363d11 --- /dev/null +++ b/OSX/include/security_utilities @@ -0,0 +1 @@ +./libsecurity_utilities/lib \ No newline at end of file diff --git a/OSX/include/securityd_client b/OSX/include/securityd_client new file mode 120000 index 00000000..2edb676a --- /dev/null +++ b/OSX/include/securityd_client @@ -0,0 +1 @@ +./libsecurityd/lib \ No newline at end of file diff --git a/OSX/libsecurity_asn1/security_asn1 b/OSX/libsecurity_asn1/security_asn1 new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/OSX/libsecurity_asn1/security_asn1 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/OSX/libsecurity_authorization/lib/Authorization.c b/OSX/libsecurity_authorization/lib/Authorization.c index e88dae1f..17b3ad57 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.c +++ b/OSX/libsecurity_authorization/lib/Authorization.c @@ -380,6 +380,7 @@ OSStatus AuthorizationCopyRights(AuthorizationRef authorization, os_log_debug(AUTH_LOG, "Failed to find sheet support in SecurityInterface"); } // fall back to the standard (windowed) version if sheets are not available + flags &= ~kAuthorizationFlagSheet; } } diff --git a/OSX/libsecurity_codesigning/lib/SecCodePriv.h b/OSX/libsecurity_codesigning/lib/SecCodePriv.h index e2cac5dd..a5b128cd 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecCodePriv.h @@ -233,7 +233,7 @@ CF_ENUM(uint32_t) { // NOTE: These values needs to align with the public definitions for static code validity too. kSecCSStrictValidateStructure = 1 << 13, kSecCSSkipRootVolumeExceptions = 1 << 14, - + kSecCSSkipXattrFiles = 1 << 15, }; #if TARGET_OS_OSX diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index 0fa873e1..13d7b0f7 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -127,6 +127,7 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSSingleThreaded | kSecCSApplyEmbeddedPolicy | kSecCSSkipRootVolumeExceptions + | kSecCSSkipXattrFiles ); if (errors) diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 033ef507..85abf01a 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -1227,7 +1227,6 @@ void SecStaticCode::validateExecutable() MacOSError::throwMe(mExecutableValidResult); } - // // Perform static validation of sealed resources and nested code. // @@ -1257,11 +1256,14 @@ void SecStaticCode::validateResources(SecCSFlags flags) if (doit) { string root = cfStringRelease(copyCanonicalPath()); bool itemIsOnRootFS = isOnRootFilesystem(root.c_str()); - bool requestForcedValidation = (mValidationFlags & kSecCSSkipRootVolumeExceptions); - bool useRootFSPolicy = itemIsOnRootFS && !requestForcedValidation; + bool skipRootVolumeExceptions = (mValidationFlags & kSecCSSkipRootVolumeExceptions); + bool useRootFSPolicy = itemIsOnRootFS && !skipRootVolumeExceptions; + + bool itemMightUseXattrFiles = pathFileSystemUsesXattrFiles(root.c_str()); + bool skipXattrFiles = itemMightUseXattrFiles && (mValidationFlags & kSecCSSkipXattrFiles); - secinfo("staticCode", "performing resource validation for %s (%d, %d, %d)", root.c_str(), - itemIsOnRootFS, requestForcedValidation, useRootFSPolicy); + secinfo("staticCode", "performing resource validation for %s (%d, %d, %d, %d, %d)", root.c_str(), + itemIsOnRootFS, skipRootVolumeExceptions, useRootFSPolicy, itemMightUseXattrFiles, skipXattrFiles); if (mLimitedAsync == NULL) { bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false : @@ -1313,6 +1315,11 @@ void SecStaticCode::validateResources(SecCSFlags flags) void (^validate)() = ^{ bool needsValidation = true; + if (skipXattrFiles && pathIsValidXattrFile(cfString(resourceBase()) + "/" + relpath, "staticCode")) { + secinfo("staticCode", "resource validation on xattr file skipped: %s", relpath.c_str()); + needsValidation = false; + } + if (useRootFSPolicy) { CFRef itemURL = makeCFURL(relpath, false, resourceBase()); string itemPath = cfString(itemURL); diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index efc14c1c..daf77c5d 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -24,6 +24,7 @@ #include "filediskrep.h" #include "dirscanner.h" #include "notarization.h" +#include "csutilities.h" #include #include #include @@ -728,7 +729,7 @@ void BundleDiskRep::strictValidateStructure(const CodeDirectory* cd, const Toler { // scan our metadirectory (_CodeSignature) for unwanted guests if (!(flags & kSecCSQuickCheck)) - validateMetaDirectory(cd); + validateMetaDirectory(cd, flags); // check accumulated strict errors and report them if (!(flags & kSecCSRestrictSidebandData)) // tolerate resource forks etc. @@ -752,7 +753,7 @@ void BundleDiskRep::recordStrictError(OSStatus error) } -void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) +void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd, SecCSFlags flags) { // we know the resource directory will be checked after this call, so we'll give it a pass here if (cd->slotIsPresent(-cdResourceDirSlot)) @@ -771,6 +772,12 @@ void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) break; } } + + bool shouldSkipXattrFiles = false; + if ((flags & kSecCSSkipXattrFiles) && pathFileSystemUsesXattrFiles(mMetaPath.c_str())) { + shouldSkipXattrFiles = true; + } + DirScanner scan(mMetaPath); if (scan.initialized()) { while (struct dirent* ent = scan.getNext()) { @@ -782,6 +789,9 @@ void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) AutoFileDesc fd(metaPath(kSecCS_SIGNATUREFILE)); if (fd.fileSize() == 0) continue; // that's okay, then + } else if (shouldSkipXattrFiles && pathIsValidXattrFile(mMetaPath + "/" + ent->d_name, "bundlediskrep")) { + secinfo("bundlediskrep", "meta directory validation on xattr file skipped: %s", ent->d_name); + continue; } // not on list of needed files; it's a freeloading rogue! recordStrictError(errSecCSUnsealedAppRoot); // funnel through strict set so GKOpaque can override it diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.h b/OSX/libsecurity_codesigning/lib/bundlediskrep.h index af3e40e2..932cb27f 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.h @@ -113,7 +113,7 @@ private: void checkModifiedFile(CFMutableArrayRef files, CodeDirectory::SpecialSlot slot); CFDataRef loadRegularFile(CFURLRef url); void recordStrictError(OSStatus error); - void validateMetaDirectory(const CodeDirectory* cd); + void validateMetaDirectory(const CodeDirectory* cd, SecCSFlags flags); void validateFrameworkRoot(std::string root); void checkPlainFile(UnixPlusPlus::FileDesc fd, const std::string& path); void checkForks(UnixPlusPlus::FileDesc fd); diff --git a/OSX/libsecurity_codesigning/lib/csutilities.cpp b/OSX/libsecurity_codesigning/lib/csutilities.cpp index 2d9c65bf..ff0f15dd 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.cpp +++ b/OSX/libsecurity_codesigning/lib/csutilities.cpp @@ -43,6 +43,10 @@ #include #include #include +#include +#include +#include +#include #include "debugging.h" extern "C" { @@ -335,5 +339,207 @@ bool isOnRootFilesystem(const char *path) return ((sfb.f_flags & MNT_ROOTFS) == MNT_ROOTFS); } +bool pathExists(const char *path) +{ + int rc; + + if (!path) { + secerror("path is NULL"); + return false; + } + + rc = access(path, F_OK); + if (rc != 0) { + if (errno != ENOENT) { + secerror("Unable to check if path exists: %d, %s", errno, path); + } + return false; + } + + return true; +} + +bool pathMatchesXattrFilenameSpec(const char *path) +{ + char *baseName = NULL; + bool ret = false; + + if (!path) { + secerror("path is NULL"); + goto done; + } + + // Extra byte for NULL storage. + baseName = (char *)malloc(strlen(path) + 1); + if (!baseName) { + secerror("Unable to allocate space for storing basename: %d [%s]", errno, strerror(errno)); + goto done; + } + + // basename_r will return a "/" if path is only slashes. It will return + // a "." for a NULL/empty path. Both of these cases are handled by the logic + // later. The only situation where basename_r will return a NULL is when path + // is longer than MAXPATHLEN. + + if (basename_r(path, baseName) == NULL) { + secerror("Could not get basename of %s: %d [%s]", path, errno, strerror(errno)); + goto done; + } + + // The file name must start with "._", followed by the name + // of the file for which it stores the xattrs. Hence, its length + // must be at least three --> 2 for "._" and 1 for a non-empty file + // name. + if (strlen(baseName) < 3) { + goto done; + } + + if (baseName[0] != '.' || baseName[1] != '_') { + goto done; + } + + ret = true; + +done: + if (baseName) { + free(baseName); + } + + return ret; +} + +bool pathIsRegularFile(const char *path) +{ + if (!path) { + secerror("path is NULL"); + return false; + } + + struct stat sb; + if (stat(path, &sb)) { + secerror("Unable to stat %s: %d [%s]", path, errno, strerror(errno)); + return false; + } + + return (sb.st_mode & S_IFREG) == S_IFREG; +} + +bool pathHasXattrs(const char *path) +{ + if (!path) { + secerror("path is NULL"); + return false; + } + + ssize_t xattrSize = listxattr(path, NULL, 0, 0); + if (xattrSize == -1) { + secerror("Unable to acquire the xattr list from %s", path); + return false; + } + + return (xattrSize > 0); +} + +bool pathFileSystemUsesXattrFiles(const char *path) +{ + struct _VolumeCapabilitiesWrapped { + uint32_t length; + vol_capabilities_attr_t volume_capabilities; + } __attribute__((aligned(4), packed)); + + struct attrlist attr_list; + struct _VolumeCapabilitiesWrapped volume_cap_wrapped; + struct statfs sfb; + + if (!path) { + secerror("path is NULL"); + return false; + } + + int ret = statfs(path, &sfb); + if (ret != 0) { + secerror("Unable to convert %s to its filesystem mount [statfs failed]: %d [%s]", path, errno, strerror(errno)); + return false; + } + path = sfb.f_mntonname; + + memset(&attr_list, 0, sizeof(attr_list)); + attr_list.bitmapcount = ATTR_BIT_MAP_COUNT; + attr_list.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES; + + ret = getattrlist(path, &attr_list, &volume_cap_wrapped, sizeof(volume_cap_wrapped), 0); + if (ret) { + secerror("Unable to get volume capabilities from %s: %d [%s]", path, errno, strerror(errno)); + return false; + } + + if (volume_cap_wrapped.length != sizeof(volume_cap_wrapped)) { + secerror("getattrlist return length incorrect, expected %lu, got %u", sizeof(volume_cap_wrapped), volume_cap_wrapped.length); + return false; + } + + // The valid bit tells us whether the corresponding bit in capabilities is valid + // or not. For file systems where the valid bit isn't set, we can safely assume that + // extended attributes aren't supported natively. + + bool xattr_valid = (volume_cap_wrapped.volume_capabilities.valid[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) == VOL_CAP_INT_EXTENDED_ATTR; + if (!xattr_valid) { + return true; + } + + bool xattr_capability = (volume_cap_wrapped.volume_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) == VOL_CAP_INT_EXTENDED_ATTR; + if (!xattr_capability) { + return true; + } + + return false; +} + +bool pathIsValidXattrFile(const string fullPath, const char *scope) +{ + // Confirm that fullPath begins from root. + if (fullPath[0] != '/') { + secinfo(scope, "%s isn't a full path, but a relative path", fullPath.c_str()); + return false; + } + + // Confirm that fullPath is a regular file. + if (!pathIsRegularFile(fullPath.c_str())) { + secinfo(scope, "%s isn't a regular file", fullPath.c_str()); + return false; + } + + // Check that the file name matches the Xattr file spec. + if (!pathMatchesXattrFilenameSpec(fullPath.c_str())) { + secinfo(scope, "%s doesn't match Xattr file path spec", fullPath.c_str()); + return false; + } + + // We are guaranteed to have at least one "/" by virtue of fullPath + // being a path from the root of the filesystem hierarchy. + // + // We construct the real file name by copying everything up to + // the last "/", adding the "/" back in, then skipping + // over the backslash (+1) and the "._" (+2) in the rest of the + // string. + + size_t lastBackSlash = fullPath.find_last_of("/"); + const string realFilePath = fullPath.substr(0, lastBackSlash) + "/" + fullPath.substr(lastBackSlash + 1 + 2); + + if (!pathExists(realFilePath.c_str())) { + secinfo(scope, "%s does not exist, forcing resource validation on %s", realFilePath.c_str(), fullPath.c_str()); + return false; + } + + // Lastly, we need to confirm that the real file contains some xattrs. If not, + // then the file represented by fullPath isn't an xattr file. + if (!pathHasXattrs(realFilePath.c_str())) { + secinfo(scope, "%s does not contain xattrs, forcing resource validation on %s", realFilePath.c_str(), fullPath.c_str()); + return false; + } + + return true; +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index 2c9017f3..6a69749f 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -228,6 +228,24 @@ private: // Check if the path is on the root filesystem, protected by the OS. bool isOnRootFilesystem(const char *path); +// Check if a path exists. +bool pathExists(const char *path); + +// Check if the path name represents an extended attribute file (on file systems which don't support +// them natively). +bool pathMatchesXattrFilenameSpec(const char *path); + +// Check if path is a regular file. +bool pathIsRegularFile(const char *path); + +// Check if a path has any extended attributes. +bool pathHasXattrs(const char *path); + +// Check if the path is on a file system that requires files to store extended attributes. +bool pathFileSystemUsesXattrFiles(const char *path); + +// Check if path is a valid extended attribute file. +bool pathIsValidXattrFile(const string fullPath, const char *scope = "csutilities"); } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_keychain/Security b/OSX/libsecurity_keychain/Security new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/OSX/libsecurity_keychain/Security @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/OSX/libsecurity_ssl/Security b/OSX/libsecurity_ssl/Security new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/OSX/libsecurity_ssl/Security @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/OSX/libsecurity_ssl/security_ssl b/OSX/libsecurity_ssl/security_ssl new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/OSX/libsecurity_ssl/security_ssl @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/OSX/sec/ipc/com.apple.secd.plist b/OSX/sec/ipc/com.apple.secd.plist index f9484f12..3f2b01a0 100644 --- a/OSX/sec/ipc/com.apple.secd.plist +++ b/OSX/sec/ipc/com.apple.secd.plist @@ -55,6 +55,13 @@ Interval 86400 + com.apple.securityd.entropyhealth + + Priority + Utility + Interval + 86400 + com.apple.securityd.prng Priority diff --git a/OSX/sec/ipc/com.apple.securityd.plist b/OSX/sec/ipc/com.apple.securityd.plist index 6be938f5..9fd326fa 100644 --- a/OSX/sec/ipc/com.apple.securityd.plist +++ b/OSX/sec/ipc/com.apple.securityd.plist @@ -67,6 +67,13 @@ NetworkTransferDirection Bidirectional + com.apple.securityd.entropyhealth + + Priority + Utility + Interval + 86400 + com.apple.securityd.prng Priority diff --git a/OSX/sec/ipc/server.c b/OSX/sec/ipc/server.c index 86935cfe..127ac944 100644 --- a/OSX/sec/ipc/server.c +++ b/OSX/sec/ipc/server.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -1548,6 +1549,13 @@ static void securityd_xpc_init(const char *service_name) }); #endif + xpc_activity_register("com.apple.securityd.entropyhealth", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + xpc_activity_state_t activityState = xpc_activity_get_state(activity); + if (activityState == XPC_ACTIVITY_STATE_RUN) { + SecCoreAnalyticsSendKernEntropyHealth(); + } + }); + xpc_activity_register("com.apple.securityd.prng", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { xpc_activity_state_t state = xpc_activity_get_state(activity); if (state == XPC_ACTIVITY_STATE_RUN) { diff --git a/OSX/utilities/SecCoreAnalytics.h b/OSX/utilities/SecCoreAnalytics.h index 2f8dc662..f9608865 100644 --- a/OSX/utilities/SecCoreAnalytics.h +++ b/OSX/utilities/SecCoreAnalytics.h @@ -24,6 +24,7 @@ #include void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value); +void SecCoreAnalyticsSendKernEntropyHealth(void); #if __OBJC__ diff --git a/OSX/utilities/SecCoreAnalytics.m b/OSX/utilities/SecCoreAnalytics.m index e58cea45..e1edc3cc 100644 --- a/OSX/utilities/SecCoreAnalytics.m +++ b/OSX/utilities/SecCoreAnalytics.m @@ -25,6 +25,7 @@ #import #import #import +#import NSString* const SecCoreAnalyticsValue = @"value"; @@ -37,6 +38,73 @@ void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value) }]; } +void SecCoreAnalyticsSendKernEntropyHealth() +{ + size_t sz_int = sizeof(int); + size_t sz_uint = sizeof(unsigned int); + size_t sz_tv = sizeof(struct timeval); + + int startup_done; + unsigned int adaptive_proportion_failure_count = 0; + unsigned int adaptive_proportion_max_observation_count = 0; + unsigned int adaptive_proportion_reset_count = 0; + unsigned int repetition_failure_count = 0; + unsigned int repetition_max_observation_count = 0; + unsigned int repetition_reset_count = 0; + + int rv = sysctlbyname("kern.entropy.health.startup_done", &startup_done, &sz_int, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.failure_count", &adaptive_proportion_failure_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.max_observation_count", &adaptive_proportion_max_observation_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.reset_count", &adaptive_proportion_reset_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_test.failure_count", &repetition_failure_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_test.max_observation_count", &repetition_max_observation_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_test.reset_count", &repetition_reset_count, &sz_uint, NULL, 0); + + // Round up to next power of two. + if (adaptive_proportion_reset_count > 0) { + adaptive_proportion_reset_count = + 1U << (sizeof(unsigned int) * 8 - __builtin_clz(adaptive_proportion_reset_count)); + } + + // Round up to next power of two. + if (repetition_reset_count > 0) { + repetition_reset_count = + 1U << (sizeof(unsigned int) * 8 - __builtin_clz(repetition_reset_count)); + } + + // Default to not submitting uptime, except on failure. + int uptime = -1; + + if (adaptive_proportion_failure_count > 0 || repetition_failure_count > 0) { + time_t now; + time(&now); + + struct timeval boottime; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + rv |= sysctl(mib, 2, &boottime, &sz_tv, NULL, 0); + + // Submit uptime in minutes. + uptime = (int)((now - boottime.tv_sec) / 60); + } + + if (rv) { + return; + } + + [SecCoreAnalytics sendEventLazy:@"com.apple.kern.entropyHealth" builder:^NSDictionary * _Nonnull{ + return @{ + @"uptime" : @(uptime), + @"startup_done" : @(startup_done), + @"adaptive_proportion_failure_count" : @(adaptive_proportion_failure_count), + @"adaptive_proportion_max_observation_count" : @(adaptive_proportion_max_observation_count), + @"adaptive_proportion_reset_count" : @(adaptive_proportion_reset_count), + @"repetition_failure_count" : @(repetition_failure_count), + @"repetition_max_observation_count" : @(repetition_max_observation_count), + @"repetition_reset_count" : @(repetition_reset_count) + }; + }]; +} + @implementation SecCoreAnalytics SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CoreAnalytics); diff --git a/RegressionTests/Security.plist b/RegressionTests/Security.plist index 4bcfade3..c983792d 100644 --- a/RegressionTests/Security.plist +++ b/RegressionTests/Security.plist @@ -178,6 +178,18 @@ ShowSubtestResults + + TestName + SecStaticCodeAPITest + Command + + /AppleInternal/CoreOS/tests/Security/secsecstaticcodeapitest + + Disabled + BATS_UTD_Disabled_SecStaticCodeAPITest + ShowSubtestResults + + diff --git a/RegressionTests/bats_utd_plist.h b/RegressionTests/bats_utd_plist.h index 78aa0fef..cf3d6a8b 100644 --- a/RegressionTests/bats_utd_plist.h +++ b/RegressionTests/bats_utd_plist.h @@ -48,6 +48,7 @@ #define BATS_UTD_Disabled_KeychainSecdXCTests _TRUE_ #define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ #define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ #elif TARGET_OS_OSX /* For MacOS, we disable the iOS only tests. */ @@ -67,6 +68,7 @@ #define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ #define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ #define BATS_UTD_Disabled_SecCodeAPITest _FALSE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _FALSE_ #elif TARGET_OS_WATCH #define BATS_UTD_Disabled_AuthorizationTest _TRUE_ @@ -85,6 +87,7 @@ #define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ #define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ #define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ #elif TARGET_OS_TV #define BATS_UTD_Disabled_AuthorizationTest _TRUE_ @@ -103,6 +106,7 @@ #define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ #define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ #define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ #else /* By default, assume iOS platforms. We disable the MacOS only tests. */ @@ -122,5 +126,6 @@ #define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ #define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ #define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ #endif diff --git a/RegressionTests/secsecstaticcodeapitest.c b/RegressionTests/secsecstaticcodeapitest.c new file mode 100644 index 00000000..3dc2b590 --- /dev/null +++ b/RegressionTests/secsecstaticcodeapitest.c @@ -0,0 +1,229 @@ +// +// secsecstaticcodeapitest.c +// secsecstaticcodeapitest +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BEGIN() \ +({ \ + fprintf(stdout, "[BEGIN] %s\n", __FUNCTION__); \ +}) + +#define INFO(fmt, ...) \ +({ \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__); \ +}) + +#define PASS(fmt, ...) \ +({ \ + fprintf(stdout, "[PASS] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define FAIL(fmt, ...) \ +({ \ + fprintf(stdout, "[FAIL] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define SAFE_RELEASE(x) \ +({ \ + if (x) { \ + CFRelease(x); \ + x = NULL; \ + } \ +}) + +#define kCommandRedirectOutputToDevNULL " >/dev/null 2>&1" +#define BUILD_COMMAND(x) x kCommandRedirectOutputToDevNULL + +#define kFAT32DiskImageFileDirectory "/tmp" +#define kFAT32DiskImageFileName "Security_SecStaticCodeAPITest.dmg" +#define kFAT32DiskImageFilePath kFAT32DiskImageFileDirectory "/" kFAT32DiskImageFileName + +#define kFAT32DiskImageVolumeDirectory "/Volumes" +#define kFAT32DiskImageVolumeName "SEC_TEST" +#define kFAT32DiskImageVolumePath kFAT32DiskImageVolumeDirectory "/" kFAT32DiskImageVolumeName + +#define kApplicationsPath "/Applications" +#define kSafariBundleName "Safari.app" +#define kSafariBundleOnSystemPath kApplicationsPath "/" kSafariBundleName +#define kSafariBundleOnVolumePath kFAT32DiskImageVolumePath "/" kSafariBundleName + +static void +_cleanUpFAT32DiskImage(void) +{ + // Delete disk image. + const char *command = BUILD_COMMAND("rm -rf " kFAT32DiskImageFilePath); + system(command); + + // Detach volume. + command = BUILD_COMMAND("hdiutil detach " kFAT32DiskImageVolumePath); + system(command); +} + +static int +_createFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil create -fs FAT32 -size 256m -volname " kFAT32DiskImageVolumeName " " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_attachFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil attach " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_copySafariBundleToVolume(void) +{ + const char *command = BUILD_COMMAND("cp -R " kSafariBundleOnSystemPath " " kSafariBundleOnVolumePath); + return system(command); +} + +static int +_confirmValidationPolicy(const char *path) +{ + int ret = -1; + SecStaticCodeRef codeRef = NULL; + SecCSFlags createFlags = kSecCSDefaultFlags; + SecCSFlags validateFlags = kSecCSDefaultFlags | kSecCSStrictValidateStructure; + + CFStringRef stringRef = NULL; + CFURLRef pathRef = NULL; + + require(path, done); + + stringRef = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)path, strlen(path), kCFStringEncodingASCII, false); + require(stringRef, done); + + pathRef = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, stringRef, kCFURLPOSIXPathStyle, false); + require(pathRef, done); + + OSStatus status = SecStaticCodeCreateWithPath(pathRef, createFlags, &codeRef); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary without kSecCSSkipXattrFiles. Expectation is this should fail. + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (!status) { + INFO("%s validated without kSecCSSkipXattrFiles flag", path); + goto done; + } + SAFE_RELEASE(codeRef); + + // Create codeRef again to clear state. + status = SecStaticCodeCreateWithPath(pathRef, createFlags, &codeRef); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary with kSecCSSkipXattrFiles. Expectation is this should pass. + validateFlags |= kSecCSSkipXattrFiles; + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (status) { + INFO("%s is not valid even with kSecCSSkipXattrFiles flag", path); + goto done; + } + + // Complete. + ret = 0; + +done: + SAFE_RELEASE(codeRef); + SAFE_RELEASE(stringRef); + SAFE_RELEASE(pathRef); + return ret; +} + +static int +CheckCheckValidity_kSecCSSkipXattrFiles(void) +{ + BEGIN(); + + int ret = -1; + + // Create FAT32 disk image. + if (_createFAT32DiskImage()) { + FAIL("_createFAT32DiskImage error"); + goto done; + } + INFO("Created " kFAT32DiskImageFilePath); + + // Attach disk image to the system. + if (_attachFAT32DiskImage()) { + FAIL("_attachFAT32DiskImage error"); + goto done; + } + INFO("Attached " kFAT32DiskImageFilePath " as " kFAT32DiskImageVolumePath); + + // Copy Safari.app to the attached volume. + if (_copySafariBundleToVolume()) { + FAIL("_copySafariBundleToVolume error"); + goto done; + } + INFO("Copied " kSafariBundleOnSystemPath " to " kSafariBundleOnVolumePath); + + // Write "com.apple.dummy" xattr to Safari. + const char *xattrName = "com.apple.dummy"; + const uint32_t xattrValue = 0; + + const char *safariBinary = kSafariBundleOnVolumePath "/Contents/MacOS/Safari"; + if (setxattr(safariBinary, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariBinary, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariBinary); + + const char *safariCodeResources = kSafariBundleOnVolumePath "/Contents/_CodeSignature/CodeResources"; + if (setxattr(safariCodeResources, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariCodeResources, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariCodeResources); + + // Validate Safari.app with and without kSecCSSkipXattrFiles flag. + if (_confirmValidationPolicy(kSafariBundleOnVolumePath)) { + FAIL("%s _confirmValidationPolicy error", kSafariBundleOnVolumePath); + goto done; + } + INFO("Validation policy on %s confirmed", kSafariBundleOnVolumePath); + + PASS("Completed validation policy check with kSecCSSkipXattrFiles"); + ret = 0; + +done: + _cleanUpFAT32DiskImage(); + return ret; +} + +int main(void) +{ + fprintf(stdout, "[TEST] secsecstaticcodeapitest\n"); + + int i; + int (*testList[])(void) = { + CheckCheckValidity_kSecCSSkipXattrFiles + }; + const int numberOfTests = sizeof(testList) / sizeof(*testList); + int testResults[numberOfTests] = {0}; + + for (i = 0; i < numberOfTests; i++) { + testResults[i] = testList[i](); + } + + fprintf(stdout, "[SUMMARY]\n"); + for (i = 0; i < numberOfTests; i++) { + fprintf(stdout, "%d. %s\n", i+1, testResults[i] == 0 ? "Passed" : "Failed"); + } + + return 0; +} diff --git a/Security.exp-in b/Security.exp-in index 241e9740..9302304a 100644 --- a/Security.exp-in +++ b/Security.exp-in @@ -2087,6 +2087,7 @@ _OBJC_CLASS_$_SFAnalyticsSQLiteStore _OBJC_CLASS_$_SecCoreAnalytics _SecCoreAnalyticsValue _SecCoreAnalyticsSendValue +_SecCoreAnalyticsSendKernEntropyHealth _SFAnalyticsMaxEventsToReport _SFSQLiteJournalSuffixes _SFAnalyticsSamplerIntervalOncePerReport diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 6ccf9ee9..05c36438 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -629,6 +629,7 @@ buildPhases = ( ); dependencies = ( + 3E4D531F2531185D00B124B3 /* PBXTargetDependency */, 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */, 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */, 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */, @@ -1190,6 +1191,9 @@ 3DD2589F20478CF900F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258A020478CFA00F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258AC2051F10300F5DA78 /* STLegacyTests+sni.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE7F201AA50F0086D049 /* STLegacyTests+sni.m */; }; + 3E4D49B72531170600B124B3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + 3E4D49B82531170600B124B3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 3E4D508F253117DD00B124B3 /* secsecstaticcodeapitest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E4D508E253117DD00B124B3 /* secsecstaticcodeapitest.c */; }; 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 3E88361424F0699F00E9F4D6 /* secseccodeapitest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */; }; 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; @@ -2176,6 +2180,9 @@ BECFA44320FD0A4B00B11002 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; BECFA45920FEB90900B11002 /* Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECFA43C20F9493000B11002 /* Policy.swift */; }; BECFA46420FFB87500B11002 /* TPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = BECFA46320FFB87400B11002 /* TPKey.m */; }; + BED079D22542A2C100FED203 /* CARevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BED078F82542A2BF00FED203 /* CARevocationTests.m */; }; + BED07AAC2542A2CC00FED203 /* CARevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BED078F82542A2BF00FED203 /* CARevocationTests.m */; }; + BED07B862542A2CE00FED203 /* CARevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BED078F82542A2BF00FED203 /* CARevocationTests.m */; }; BED208D81EDF950E00753952 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; BED208D91EDF950E00753952 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; BED208E81EDF974500753952 /* manifeststresstest.m in Sources */ = {isa = PBXBuildFile; fileRef = BED208E71EDF971600753952 /* manifeststresstest.m */; }; @@ -6643,6 +6650,13 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 3E4D531E2531185D00B124B3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E4D49B32531170600B124B3; + remoteInfo = secsecstaticcodeapitest; + }; 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -11935,6 +11949,8 @@ 3DD1FFA9201FC5C30086D049 /* libcoretls_cfhelpers.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcoretls_cfhelpers.tbd; path = usr/lib/libcoretls_cfhelpers.tbd; sourceTree = SDKROOT; }; 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureTransport_ios_tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+session.m"; sourceTree = ""; }; + 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secsecstaticcodeapitest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E4D508E253117DD00B124B3 /* secsecstaticcodeapitest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = secsecstaticcodeapitest.c; sourceTree = ""; }; 3E88361124F068EF00E9F4D6 /* secseccodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secseccodeapitest; sourceTree = BUILT_PRODUCTS_DIR; }; 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = secseccodeapitest.c; sourceTree = ""; }; 433E519D1B66D5F600482618 /* AppSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppSupport.framework; path = System/Library/PrivateFrameworks/AppSupport.framework; sourceTree = SDKROOT; }; @@ -12550,6 +12566,8 @@ BECFA43C20F9493000B11002 /* Policy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Policy.swift; sourceTree = ""; }; BECFA46320FFB87400B11002 /* TPKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKey.m; sourceTree = ""; }; BED01530206F050F0027A2B4 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = trust/README.txt; sourceTree = ""; }; + BED0781D2542A2B300FED203 /* CARevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CARevocationTests_data.h; path = tests/TrustTests/EvaluationTests/CARevocationTests_data.h; sourceTree = ""; }; + BED078F82542A2BF00FED203 /* CARevocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CARevocationTests.m; path = tests/TrustTests/EvaluationTests/CARevocationTests.m; sourceTree = ""; }; BED208DD1EDF950E00753952 /* manifeststresstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = manifeststresstest; sourceTree = BUILT_PRODUCTS_DIR; }; BED208E61EDF971600753952 /* manifeststresstest.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; name = manifeststresstest.entitlements; path = manifeststresstest/manifeststresstest.entitlements; sourceTree = ""; }; BED208E71EDF971600753952 /* manifeststresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = manifeststresstest.m; path = manifeststresstest/manifeststresstest.m; sourceTree = ""; }; @@ -16203,6 +16221,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E4D49B62531170600B124B3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E4D49B72531170600B124B3 /* Security.framework in Frameworks */, + 3E4D49B82531170600B124B3 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 3E88360B24F068EF00E9F4D6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -18552,6 +18579,14 @@ path = SecureTransportTests; sourceTree = ""; }; + 3E4D4DFF2531174400B124B3 /* secsecstaticcodeapitest */ = { + isa = PBXGroup; + children = ( + 3E4D508E253117DD00B124B3 /* secsecstaticcodeapitest.c */, + ); + name = secsecstaticcodeapitest; + sourceTree = ""; + }; 3E88361224F0693200E9F4D6 /* secseccodeapitest */ = { isa = PBXGroup; children = ( @@ -18952,6 +18987,7 @@ 6C2045EA2424BA7E00F9461D /* KeychainStasher */, 6C963281242A279B00C53CE2 /* stashtester */, 3E88361124F068EF00E9F4D6 /* secseccodeapitest */, + 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */, ); name = Products; sourceTree = ""; @@ -19918,6 +19954,8 @@ D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */, D458C4AA214E198D0043D982 /* CTTests.m */, D4EF3222215F102F000A31A5 /* CTTests_data.h */, + BED078F82542A2BF00FED203 /* CARevocationTests.m */, + BED0781D2542A2B300FED203 /* CARevocationTests_data.h */, D4AC5766214E195300A32C01 /* ECTests.m */, D4AC5767214E195300A32C01 /* ECTests_data.h */, D458C4AE214E198E0043D982 /* EvaluationBasicTests_data.h */, @@ -25744,6 +25782,7 @@ EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = { isa = PBXGroup; children = ( + 3E4D4DFF2531174400B124B3 /* secsecstaticcodeapitest */, 3E88361224F0693200E9F4D6 /* secseccodeapitest */, 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */, 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */, @@ -28305,6 +28344,22 @@ productReference = 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E4D49B92531170600B124B3 /* Build configuration list for PBXNativeTarget "secsecstaticcodeapitest" */; + buildPhases = ( + 3E4D49B42531170600B124B3 /* Sources */, + 3E4D49B62531170600B124B3 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secsecstaticcodeapitest; + productName = secbackupntest; + productReference = 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */; + productType = "com.apple.product-type.tool"; + }; 3E88360824F068EF00E9F4D6 /* secseccodeapitest */ = { isa = PBXNativeTarget; buildConfigurationList = 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */; @@ -32015,6 +32070,7 @@ EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */, DAE40BC520CF3E46002D5674 /* secitemcanarytest */, 3E88360824F068EF00E9F4D6 /* secseccodeapitest */, + 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */, DCE4E7CB1D7A4AED00AFB96E /* sectests_macos */, 470415CE1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */, 47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */, @@ -33368,6 +33424,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E4D49B42531170600B124B3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E4D508F253117DD00B124B3 /* secsecstaticcodeapitest.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 3E88360924F068EF00E9F4D6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -34274,6 +34338,7 @@ D458C4C2214E19FC0043D982 /* TrustSettingsInterfaceTests.m in Sources */, D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */, D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */, + BED07B862542A2CE00FED203 /* CARevocationTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -34328,6 +34393,7 @@ D477CB8F237F975500C02355 /* ValidTests.m in Sources */, D458C4B2214E198F0043D982 /* EvaluationBasicTests.m in Sources */, D477CB82237F692400C02355 /* RevocationTests.m in Sources */, + BED07AAC2542A2CC00FED203 /* CARevocationTests.m in Sources */, D458C4BA214E19AF0043D982 /* iAPTests.m in Sources */, D458C4B8214E19AF0043D982 /* PathParseTests.m in Sources */, D458C525214E33440043D982 /* VerifyDateTests.m in Sources */, @@ -36488,6 +36554,7 @@ DCF216E121ADD6060029CCC1 /* TPPBVoucher.proto in Sources */, DCF216E021ADD5FD0029CCC1 /* OTAccountMetadataClassC.proto in Sources */, DCE0774721ADD63A002662FD /* TPPBDispositionEntry.proto in Sources */, + BED079D22542A2C100FED203 /* CARevocationTests.m in Sources */, DCE0774621ADD638002662FD /* TPPBDisposition.proto in Sources */, DCE0774921ADD63E002662FD /* TPPBPolicyProhibits.proto in Sources */, DCE0774A21ADD640002662FD /* TPPBUnknownMachineID.proto in Sources */, @@ -37223,6 +37290,11 @@ target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 3DD258A1204B7DA800F5DA78 /* PBXContainerItemProxy */; }; + 3E4D531F2531185D00B124B3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */; + targetProxy = 3E4D531E2531185D00B124B3 /* PBXContainerItemProxy */; + }; 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 3E88360824F068EF00E9F4D6 /* secseccodeapitest */; @@ -40984,6 +41056,74 @@ }; name = Release; }; + 3E4D49BA2531170600B124B3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + }; + name = Debug; + }; + 3E4D49BB2531170600B124B3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 3E88360F24F068EF00E9F4D6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -52448,6 +52588,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3E4D49B92531170600B124B3 /* Build configuration list for PBXNativeTarget "secsecstaticcodeapitest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E4D49BA2531170600B124B3 /* Debug */, + 3E4D49BB2531170600B124B3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/keychain/TrustedPeersHelper/Container.swift b/keychain/TrustedPeersHelper/Container.swift index cd3b61e7..86f29eec 100644 --- a/keychain/TrustedPeersHelper/Container.swift +++ b/keychain/TrustedPeersHelper/Container.swift @@ -2558,8 +2558,15 @@ class Container: NSObject { reply(cachedBottles.viableBottles, cachedBottles.partialBottles, nil) return } - - self.cuttlefish.fetchViableBottles { response, error in + + let request = FetchViableBottlesRequest.with { + $0.filterRequest = OctagonPlatformSupportsSOS() ? .unknown : .byOctagonOnly + } + if request.filterRequest == .byOctagonOnly { + os_log("Requesting Cuttlefish sort records by Octagon Only", log: tplogDebug, type: .default) + } + + self.cuttlefish.fetchViableBottles(request) { response, error in guard error == nil else { os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, nil, error) @@ -2662,7 +2669,14 @@ class Container: NSObject { return } - self.cuttlefish.fetchViableBottles { response, error in + let request = FetchViableBottlesRequest.with { + $0.filterRequest = OctagonPlatformSupportsSOS() ? .unknown : .byOctagonOnly + } + if request.filterRequest == .byOctagonOnly { + os_log("Requesting Cuttlefish sort records by Octagon Only", log: tplogDebug, type: .default) + } + + self.cuttlefish.fetchViableBottles(request) { response, error in guard error == nil else { os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error) diff --git a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift index 4236b8c3..caf3d460 100644 --- a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift @@ -164,6 +164,7 @@ extension TLKShare { } class FakeCuttlefishServer: CuttlefishAPIAsync { + struct State { var peersByID: [String: Peer] = [:] var recoverySigningPubKey: Data? @@ -205,7 +206,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { var returnRepairErrorResponse: Error? var fetchChangesCalledCount: Int = 0 var fetchChangesReturnEmptyResponse: Bool = false - + var fetchViableBottlesEscrowRecordCacheTimeout: TimeInterval = 2.0 var nextEstablishReturnsMoreChanges: Bool = false @@ -705,7 +706,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func fetchViableBottles(_ request: FetchViableBottlesRequest, completion: @escaping (FetchViableBottlesResponse?, Error?) -> Void) { print("FakeCuttlefish: fetchViableBottles called") - + if let fetchViableBottlesListener = self.fetchViableBottlesListener { let possibleError = fetchViableBottlesListener(request) guard possibleError == nil else { @@ -846,6 +847,13 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { completion(FetchSOSiCloudIdentityResponse(), nil) } + + func addCustodianRecoveryKey(_: AddCustodianRecoveryKeyRequest, completion: @escaping (AddCustodianRecoveryKeyResponse?, Error?) -> Void) { + completion(AddCustodianRecoveryKeyResponse(), nil) + } + func resetAccountCdpcontents(_: ResetAccountCDPContentsRequest, completion: @escaping (ResetAccountCDPContentsResponse?, Error?) -> Void) { + completion(ResetAccountCDPContentsResponse(), nil) + } } extension FakeCuttlefishServer: CloudKitCode.Invocable { diff --git a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift index 083d98be..580b6034 100644 --- a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift @@ -21,6 +21,7 @@ enum Handler { } class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { + var handlers: [Handler] = [] var index: Int = 0 @@ -173,4 +174,10 @@ class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { completion(FetchSOSiCloudIdentityResponse(), nil) } + func addCustodianRecoveryKey(_: AddCustodianRecoveryKeyRequest, completion: @escaping (AddCustodianRecoveryKeyResponse?, Error?) -> Void) { + completion(AddCustodianRecoveryKeyResponse(), nil) + } + func resetAccountCdpcontents(_: ResetAccountCDPContentsRequest, completion: @escaping (ResetAccountCDPContentsResponse?, Error?) -> Void) { + completion(ResetAccountCDPContentsResponse(), nil) + } } diff --git a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h index 9753ef8d..1ab6328e 100644 --- a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h +++ b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h @@ -22,3 +22,4 @@ #import "keychain/securityd/SecItemDataSource.h" #import "keychain/ckks/tests/MockCloudKit.h" +#import diff --git a/keychain/ckks/CKKSAnalytics.h b/keychain/ckks/CKKSAnalytics.h index 357a032c..6454637d 100644 --- a/keychain/ckks/CKKSAnalytics.h +++ b/keychain/ckks/CKKSAnalytics.h @@ -67,6 +67,7 @@ extern NSString* const OctagonAnalyticsKeychainSyncProvisioned; extern NSString* const OctagonAnalyticsKeychainSyncEnabled; extern NSString* const OctagonAnalyticsCloudKitProvisioned; extern NSString* const OctagonAnalyticsCloudKitEnabled; +extern NSString* const OctagonAnalyticsSecureBackupTermsAccepted; extern NSString* const OctagonAnalyticsBottledUniqueTLKsRecovered; extern NSString* const OctagonAnalyticsBottledTotalTLKShares; diff --git a/keychain/ckks/CKKSAnalytics.m b/keychain/ckks/CKKSAnalytics.m index dcc6b61c..9300420d 100644 --- a/keychain/ckks/CKKSAnalytics.m +++ b/keychain/ckks/CKKSAnalytics.m @@ -84,6 +84,7 @@ NSString* const OctagonAnalyticsKeychainSyncProvisioned = @"OADCKCSProvisioned"; NSString* const OctagonAnalyticsKeychainSyncEnabled = @"OADCKCSEnabled"; NSString* const OctagonAnalyticsCloudKitProvisioned = @"OADCCKProvisioned"; NSString* const OctagonAnalyticsCloudKitEnabled = @"OADCCKEnabled"; +NSString* const OctagonAnalyticsSecureBackupTermsAccepted = @"OASecureBackupTermsAccepted"; static NSString* const CKKSAnalyticsAttributeRecoverableError = @"recoverableError"; static NSString* const CKKSAnalyticsAttributeZoneName = @"zone"; diff --git a/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m b/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m index 758884c0..d8f5d535 100644 --- a/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m +++ b/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m @@ -83,6 +83,11 @@ SecEscrowPendingRecord* record = nil; for(SecEscrowPendingRecord* existingRecord in records) { + if(existingRecord.uploadCompleted) { + secnotice("escrowrequest", "Skipping completed escrow request (%@)", existingRecord); + continue; + } + if(self.enforceRateLimiting && [existingRecord escrowAttemptedWithinLastSeconds:5*60]) { secnotice("escrowrequest", "Skipping pending escrow request (%@); it's rate limited", existingRecord); continue; diff --git a/keychain/ot/OTCuttlefishContext.m b/keychain/ot/OTCuttlefishContext.m index a5e52ed4..6f9b7907 100644 --- a/keychain/ot/OTCuttlefishContext.m +++ b/keychain/ot/OTCuttlefishContext.m @@ -2889,6 +2889,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply { + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon-ckks", "No cloudkit account present"); + reply(NO, [self errorNoiCloudAccount]); + return; + } + if(self.viewManager.policy) { BOOL syncing = self.viewManager.policy.syncUserControllableViewsAsBoolean; diff --git a/keychain/ot/OTManager.m b/keychain/ot/OTManager.m index 20359984..028b573f 100644 --- a/keychain/ot/OTManager.m +++ b/keychain/ot/OTManager.m @@ -78,6 +78,9 @@ #import +#import +#import + #import "keychain/TrustedPeersHelper/TPHObjcTranslation.h" #import "keychain/SecureObjectSync/SOSAccountTransaction.h" #pragma clang diagnostic push @@ -87,6 +90,9 @@ #import "utilities/SecTapToRadar.h" +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); +SOFT_LINK_CLASS(CloudServices, SecureBackup); + static NSString* const kOTRampForEnrollmentRecordName = @"metadata_rampstate_enroll"; static NSString* const kOTRampForRestoreRecordName = @"metadata_rampstate_restore"; static NSString* const kOTRampForCFURecordName = @"metadata_rampstate_cfu"; @@ -1113,6 +1119,11 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; values[OctagonAnalyticsKeychainSyncEnabled] = @([primaryAccount isEnabledForDataclass:ACAccountDataclassKeychainSync]); values[OctagonAnalyticsCloudKitProvisioned] = @([primaryAccount isProvisionedForDataclass:ACAccountDataclassCKDatabaseService]); values[OctagonAnalyticsCloudKitEnabled] = @([primaryAccount isEnabledForDataclass:ACAccountDataclassCKDatabaseService]); + + NSString *altDSID = primaryAccount.aa_altDSID; + if(altDSID) { + values[OctagonAnalyticsSecureBackupTermsAccepted] = @([getSecureBackupClass() getAcceptedTermsForAltDSID:altDSID withError:nil] != nil); + } } } diff --git a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift index 96b15016..0aa2cb09 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift @@ -469,6 +469,20 @@ class OctagonCKKSTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 100 * NSEC_PER_SEC) } + + func testFetchUserControllableViewsSyncingStatusNoAccount() throws { + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) + + let fetchExpectation = self.expectation(description: "fetch user controllable views syncing status returns") + self.cuttlefishContext.rpcFetchUserControllableViewsSyncingStatus { isSyncing, error in + XCTAssertNotNil(error, "error should not be nil") + XCTAssertFalse(isSyncing, "should not be syncing with no account") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 10) + } } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift index 5f9a4f50..91aadb9c 100644 --- a/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift @@ -46,6 +46,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + OctagonSetPlatformSupportsSOS(true) do { let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) @@ -135,12 +136,15 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + OctagonSetPlatformSupportsSOS(true) //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchUnCachedViableBottlesExpectation.fulfill() return nil } @@ -178,6 +182,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchViableBottlesExpectation.fulfill() return nil } @@ -270,11 +275,14 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + OctagonSetPlatformSupportsSOS(true) + //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchUnCachedViableBottlesExpectation.fulfill() return nil } @@ -309,6 +317,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchViableBottlesExpectation.fulfill() return nil } @@ -337,6 +346,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchBottlesFromCuttlefishFetchExpectation.fulfill() return nil } @@ -419,11 +429,14 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + OctagonSetPlatformSupportsSOS(true) + //now call fetchviablebottles, we should get records from cuttlefish let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchUnCachedViableBottlesExpectation.fulfill() return nil } @@ -449,6 +462,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchViableBottlesExpectation.fulfill() return nil } @@ -473,6 +487,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { let containerName = OTCKContainerName OctagonSetOptimizationEnabled(true) OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(true) // Tell SOS that it is absent, so we don't enable CDP on bringup self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) @@ -481,6 +496,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchViableBottlesExpectation.fulfill() return nil } @@ -549,6 +565,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.injectLegacyEscrowRecords = true self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") fetchUnCachedViableBottlesExpectation.fulfill() return nil } @@ -574,6 +591,8 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + let legacy = container.containerMO.legacyEscrowRecords as! Set let partial = container.containerMO.partiallyViableEscrowRecords as! Set let full = container.containerMO.fullyViableEscrowRecords as! Set @@ -607,6 +626,8 @@ class OctagonEscrowRecordTests: OctagonTestsBase { let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") @@ -669,10 +690,14 @@ class OctagonEscrowRecordTests: OctagonTestsBase { let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + OctagonSetPlatformSupportsSOS(true) + let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + container.moc.performAndWait { XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") @@ -737,6 +762,8 @@ class OctagonEscrowRecordTests: OctagonTestsBase { self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + OctagonSetPlatformSupportsSOS(true) + do { let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } @@ -761,6 +788,7 @@ class OctagonEscrowRecordTests: OctagonTestsBase { let fetchViableBottlesAfterCacheRemovalExpectation = self.expectation(description: "fetchViableBottles expectation after cache removal") self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") @@ -781,7 +809,95 @@ class OctagonEscrowRecordTests: OctagonTestsBase { throw error } self.wait(for: [fetchViableBottlesAfterCacheRemovalExpectation], timeout: 10) + } + + func testFetchViableBottlesFilteringOctagonOnly() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(false) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + let removeExpectation = self.expectation(description: "remove expectation") + self.manager.invalidateEscrowCache(OTCKContainerName, contextID: initiatorContextID) { error in + XCTAssertNil(error, "error should not be nil") + removeExpectation.fulfill() + } + self.wait(for: [removeExpectation], timeout: 10) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + let fetchViableBottlesAfterCacheRemovalExpectation = self.expectation(description: "fetchViableBottles expectation after cache removal") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .byOctagonOnly, "request filtering should be unknown") + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterCacheRemovalExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterCacheRemovalExpectation], timeout: 10) } } diff --git a/keychain/securityd/com.apple.secd.sb b/keychain/securityd/com.apple.secd.sb index 48c79e59..eb7ab1f7 100644 --- a/keychain/securityd/com.apple.secd.sb +++ b/keychain/securityd/com.apple.secd.sb @@ -64,6 +64,7 @@ (global-name "com.apple.windowserver.active") (global-name "com.apple.powerlog.plxpclogger.xpc") (global-name "com.apple.SecureBackupDaemon") + (global-name "com.apple.SecureBackupDaemon.concurrent") ) ;; Used to send logs for MoiC. diff --git a/libsecurity_smime/Security b/libsecurity_smime/Security new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_smime/Security @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/libsecurity_smime/security_smime b/libsecurity_smime/security_smime new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_smime/security_smime @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/tests/TrustTests/EvaluationTests/CARevocationTests.m b/tests/TrustTests/EvaluationTests/CARevocationTests.m new file mode 100644 index 00000000..d839cee7 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CARevocationTests.m @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#include +#import +#include +#include +#include +#include "OSX/utilities/SecCFWrappers.h" +#include +#include +#include +#include "trust/trustd/OTATrustUtilities.h" +#include "trust/trustd/SecOCSPCache.h" + +#import "TrustEvaluationTestCase.h" +#import "CARevocationTests_data.h" +#include "../TestMacroConversions.h" + +@interface CARevocationTests : TrustEvaluationTestCase + +@end + +@implementation CARevocationTests + ++ (id) CF_RETURNS_RETAINED SecCertificateCreateFromData:(uint8_t *)data length:(size_t)length +{ + if (!data || !length) { return NULL; } + SecCertificateRef cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, data, length); + return (__bridge id)cert; +} + +static NSArray *s_anchors = nil; +static NSDate *s_date_20201020 = nil; + +- (void)setUp +{ + // Delete the OCSP cache between each test + [super setUp]; + SecOCSPCacheDeleteContent(nil); + + SecCertificateRef root = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acrootca length:sizeof(_acrootca)]; + s_anchors = @[ (__bridge id)root ]; + CFReleaseNull(root); + s_date_20201020 = [NSDate dateWithTimeIntervalSinceReferenceDate:624900000.0]; +} + +/* Evaluate the given chain for SSL and return the trust results dictionary. */ +- (NSDictionary *)eval_ca_trust:(NSArray *)certs + anchors:(NSArray *)anchors + hostname:(NSString *)hostname + verifyDate:(NSDate *)date +{ + /* Create the trust wrapper object */ + TestTrustEvaluation *trust = nil; + SecPolicyRef policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)hostname); + XCTAssertNotNil(trust = [[TestTrustEvaluation alloc] initWithCertificates:certs policies:@[(__bridge id)policy]], "create trust failed"); + CFReleaseNull(policy); + if (!trust) { return nil; } + + /* Set the optional properties */ + if (anchors) { trust.anchors = anchors; } + if (date) { trust.verifyDate = date; } + + /* Evaluate */ + NSError *error = nil; + XCTAssert([trust evaluate:&error], "failed trust evaluation: %@", error); + return trust.resultDictionary; +} + +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE +/* watchOS and bridgeOS don't support networking in trustd */ +- (void)testCARevocationAdditions +{ + /* Verify that the revocation server is potentially reachable */ + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + + const CFStringRef TrustTestsAppID = CFSTR("com.apple.trusttests"); + //%%% TBD: add namespace tests using AnotherAppID + //const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one"); + CFDictionaryRef copiedAdditions = NULL; + CFErrorRef error = NULL; + + /* Verify no additions set initially */ + is(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(NULL, NULL), NULL, "no revocation additions set"); + if (copiedAdditions) { + CFReleaseNull(copiedAdditions); + return; + } + + NSDictionary *results = nil; + SecCertificateRef leaf = NULL, ca = NULL; + + leaf = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acleaf length:sizeof(_acleaf)]; + XCTAssertNotNil((__bridge id)leaf, "create leaf"); + ca = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acserverca1 length:sizeof(_acserverca1)]; + XCTAssertNotNil((__bridge id)ca, "create ca"); + + /* We do not expect a revocation check for this CA until explicitly set up */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + XCTAssertNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation checked when not expected"); + + /* Set addition for intermediate CA with implied AppID */ + CFDataRef caSPKIHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(ca); + NSDictionary *caAddition = @{ + (__bridge NSString*)kSecCARevocationHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey : (__bridge NSData*)caSPKIHash, + }; + NSDictionary *additions1 = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[ caAddition ] + }; + ok(SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)additions1, &error), "failed to set ca addition for this app: %@", error); + CFReleaseNull(caSPKIHash); + + /* Check that the additions were saved and can be retrieved */ + ok(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), "failed to copy ca additions for TrustTests app id: %@", error); + /* Same as what we saved? */ + ok([additions1 isEqualToDictionary:(__bridge NSDictionary*)copiedAdditions], "got wrong additions back"); + CFReleaseNull(copiedAdditions); + + /* This time, the revocation check should take place on the leaf. */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + // %%% This check should be replaced with a different key: rdar://70669949 + XCTAssertNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation not checked"); + + /* Set empty array to clear the previously-set additions */ + NSDictionary *emptyAdditions = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[] + }; + ok(SecTrustStoreSetCARevocationAdditions(TrustTestsAppID, (__bridge CFDictionaryRef)emptyAdditions, &error), "failed to set empty additions"); + /* Did the additions get cleared? */ + is(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), NULL, "additions still present after being cleared"); + CFReleaseNull(copiedAdditions); + + /* Set addition for root CA with implied AppID */ + CFDataRef rootSPKIHash = SecSHA256DigestCreate(NULL, _acrootca_spki, sizeof(_acrootca_spki)); + NSDictionary *rootAddition = @{ + (__bridge NSString*)kSecCARevocationHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey : (__bridge NSData*)rootSPKIHash, + }; + NSDictionary *additions2 = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[ rootAddition ] + }; + ok(SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)additions2, &error), "failed to set root addition for this app: %@", error); + + /* Check that the additions were saved and can be retrieved */ + ok(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), "failed to copy root additions for TrustTests app id: %@", error); + /* Same as what we saved? */ + ok([additions2 isEqualToDictionary:(__bridge NSDictionary*)copiedAdditions], "got wrong additions back"); + CFReleaseNull(copiedAdditions); + + /* Clear OCSP cache so we know whether next evaluation attempts to check */ + SecOCSPCacheDeleteContent(nil); + + /* Revocation check should take place with a CA addition set for the root. */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + // %%% This check should be replaced with a different key: rdar://70669949 + XCTAssertNotNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation not checked"); + + CFReleaseNull(leaf); + CFReleaseNull(ca); +} + +#else // TARGET_OS_BRIDGE || TARGET_OS_WATCH +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif // TARGET_OS_BRIDGE || TARGET_OS_WATCH +@end + diff --git a/tests/TrustTests/EvaluationTests/CARevocationTests_data.h b/tests/TrustTests/EvaluationTests/CARevocationTests_data.h new file mode 100644 index 00000000..7bac453b --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CARevocationTests_data.h @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ +#ifndef _TRUSTTESTS_CA_REVOCATION_TESTS_H_ +#define _TRUSTTESTS_CA_REVOCATION_TESTS_H_ + +uint8_t _acleaf[] = { + 0x30,0x82,0x06,0x18,0x30,0x82,0x05,0x00,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x5A,0xB9,0xC3,0x64,0xE1, + 0xC2,0x69,0xF3,0x2C,0x5A,0x20,0x36,0x31,0x3B,0x73, + 0x74,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6A,0x31,0x24, + 0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F, + 0x72,0x61,0x74,0x65,0x20,0x53,0x65,0x72,0x76,0x65, + 0x72,0x20,0x43,0x41,0x20,0x31,0x31,0x20,0x30,0x1E, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30, + 0x30,0x36,0x31,0x35,0x32,0x32,0x35,0x32,0x31,0x34, + 0x5A,0x17,0x0D,0x32,0x32,0x30,0x37,0x31,0x35,0x32, + 0x32,0x35,0x32,0x31,0x34,0x5A,0x30,0x79,0x31,0x18, + 0x30,0x16,0x06,0x03,0x55,0x04,0x03,0x0C,0x0F,0x72, + 0x61,0x64,0x61,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65, + 0x2E,0x63,0x6F,0x6D,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x6D,0x61,0x6E,0x61,0x67, + 0x65,0x6D,0x65,0x6E,0x74,0x3A,0x69,0x64,0x6D,0x73, + 0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x30,0x34, + 0x32,0x39,0x33,0x36,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01, + 0x01,0x00,0xE4,0xFD,0xE1,0xE3,0x80,0x9A,0xC6,0xC4, + 0x77,0xA9,0x7F,0xC5,0xBA,0xA4,0xA9,0x46,0x46,0x89, + 0x3E,0x74,0x6E,0x50,0x06,0xA5,0x36,0x02,0x24,0xED, + 0xAF,0x4A,0xAC,0xBD,0x7C,0x1F,0x01,0x3B,0xF5,0xD5, + 0xCF,0xC2,0xDB,0xC3,0x13,0xF0,0xB3,0x71,0x0B,0xC1, + 0x99,0xB3,0xF8,0xAE,0x29,0xD0,0x8D,0xCD,0x4C,0x09, + 0x4E,0x04,0x9A,0x43,0x0D,0x96,0x06,0x3F,0xF2,0xC3, + 0xD8,0xC8,0xAB,0x54,0xC1,0x82,0x64,0xEF,0xB2,0x14, + 0x77,0xB9,0xA8,0xE6,0x29,0xE9,0x0A,0xF2,0xB1,0x44, + 0x1A,0x93,0xA3,0x3E,0xAB,0xF2,0xC0,0x78,0x0A,0xF9, + 0x9C,0x1D,0xB5,0xB6,0x86,0x33,0x0C,0xB3,0x62,0xD1, + 0x6B,0x18,0xB1,0xD1,0x3C,0x84,0x9A,0x2D,0xB3,0x6C, + 0x91,0x09,0x19,0x60,0xCF,0xEA,0x63,0x8B,0xAC,0xF4, + 0xCB,0x79,0xB4,0x10,0x42,0xD4,0x7B,0xCB,0x8D,0x86, + 0xD2,0x13,0xB9,0xE5,0x21,0x8B,0xDE,0x0D,0x20,0x5F, + 0x99,0x1A,0xD1,0x57,0xF9,0xBF,0xF6,0x90,0x25,0x97, + 0x84,0xCF,0x64,0xC1,0x3A,0x6D,0x50,0x2C,0xFD,0x02, + 0x51,0x47,0x0F,0xE6,0xE5,0x4D,0x19,0x10,0xB9,0xA5, + 0xDA,0x53,0x69,0x09,0xE2,0x51,0x31,0xAF,0x41,0x23, + 0x80,0x3B,0x65,0xDE,0x9C,0x9B,0xBD,0x9B,0xF2,0x69, + 0xDC,0xB9,0x73,0x88,0x16,0x30,0xB2,0x7A,0x0B,0xC2, + 0xDA,0xE6,0x3F,0x9B,0x65,0x9B,0x53,0xE7,0x17,0xCF, + 0x09,0x98,0xA8,0x72,0x49,0xAB,0x59,0x13,0x6E,0x41, + 0x94,0xF1,0xA4,0x4A,0xC8,0x05,0xEA,0x13,0xE5,0x78, + 0x47,0x0D,0xC1,0xD7,0x6D,0xAD,0x39,0x96,0x35,0x82, + 0x76,0xB2,0x8A,0x90,0xFF,0xF3,0xF3,0x4D,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x82,0x02,0xA9,0x30,0x82,0x02, + 0xA5,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB6,0x23, + 0xB5,0x5A,0xEB,0x7E,0xEB,0xB6,0xF3,0x28,0x1E,0x04, + 0xD0,0xAD,0x5C,0x93,0xA9,0xA4,0x9A,0x6D,0x30,0x81, + 0x83,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01, + 0x01,0x04,0x77,0x30,0x75,0x30,0x39,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74, + 0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x63,0x6F,0x72, + 0x70,0x73,0x65,0x72,0x76,0x65,0x72,0x63,0x61,0x31, + 0x2E,0x64,0x65,0x72,0x30,0x38,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x2C,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x63,0x6F,0x72, + 0x70,0x73,0x65,0x72,0x76,0x65,0x72,0x63,0x61,0x31, + 0x30,0x34,0x30,0x4C,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x45,0x30,0x43,0x82,0x0F,0x72,0x61,0x64,0x61,0x72, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x82,0x17,0x72,0x61,0x64,0x61,0x72,0x2D,0x69,0x6E, + 0x74,0x2D,0x72,0x6E,0x6F,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x82,0x17,0x72,0x61,0x64, + 0x61,0x72,0x2D,0x69,0x6E,0x74,0x2D,0x6D,0x64,0x6E, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x82,0x01,0x12,0x06,0x03,0x55,0x1D,0x20,0x04, + 0x82,0x01,0x09,0x30,0x82,0x01,0x05,0x30,0x82,0x01, + 0x01,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x05,0x0F,0x02,0x30,0x81,0xF2,0x30,0x81,0xA4,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30, + 0x81,0x97,0x0C,0x81,0x94,0x52,0x65,0x6C,0x69,0x61, + 0x6E,0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69, + 0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79, + 0x20,0x70,0x61,0x72,0x74,0x79,0x20,0x61,0x73,0x73, + 0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70, + 0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x61, + 0x6E,0x79,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61, + 0x62,0x6C,0x65,0x20,0x74,0x65,0x72,0x6D,0x73,0x20, + 0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74, + 0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73, + 0x65,0x20,0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20,0x63, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63, + 0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E, + 0x74,0x73,0x2E,0x30,0x49,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x3D,0x68,0x74,0x74, + 0x70,0x73,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61, + 0x67,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x2F,0x23,0x68,0x65,0x6C,0x70,0x2F, + 0x70,0x6F,0x6C,0x69,0x63,0x69,0x65,0x73,0x2F,0x63, + 0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x65,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, + 0x3C,0x06,0x03,0x55,0x1D,0x1F,0x04,0x35,0x30,0x33, + 0x30,0x31,0xA0,0x2F,0xA0,0x2D,0x86,0x2B,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61, + 0x70,0x70,0x6C,0x65,0x63,0x6F,0x72,0x70,0x73,0x65, + 0x72,0x76,0x65,0x72,0x63,0x61,0x31,0x2E,0x63,0x72, + 0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x9E,0xD4,0xB9,0x32,0xC7,0x63,0xBA,0xEF, + 0x4B,0x99,0xE4,0x2F,0xDD,0x35,0x8A,0xD1,0x2B,0xF8, + 0xB8,0xF4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0x1C, + 0x08,0xE9,0x55,0x6E,0x60,0xB5,0xC9,0x41,0x5B,0xE9, + 0xC3,0x5E,0xA3,0xE9,0x4C,0xF2,0xCA,0xAB,0x4A,0xB9, + 0xE1,0x83,0xE8,0xFE,0x1B,0xCA,0x9C,0xE0,0xBE,0xE7, + 0xDE,0x37,0xA0,0xE1,0x0B,0xDB,0xAC,0x29,0x13,0x9F, + 0x9B,0x0E,0x3F,0xCA,0x60,0xC4,0x7E,0x95,0x6C,0x41, + 0xA8,0xF5,0x7A,0x7B,0x92,0xB6,0xC9,0xB8,0xAA,0x7D, + 0x7E,0xD5,0xF4,0x6E,0x33,0xFC,0x8F,0xDA,0x2A,0x2B, + 0xEF,0x31,0x9C,0x43,0x5D,0x45,0x25,0x65,0xE3,0x65, + 0x4D,0x14,0x04,0x85,0x72,0x51,0x9B,0x40,0x69,0x41, + 0xCC,0x93,0xE7,0x73,0xC6,0xF3,0x63,0x77,0x91,0x27, + 0x1F,0x2B,0xB2,0x3E,0x15,0x51,0x23,0x49,0x34,0x11, + 0x1D,0xB3,0x7F,0x8B,0x75,0xB2,0xC4,0xA0,0x7A,0x3B, + 0xF7,0x62,0x1C,0x64,0xFA,0x11,0x03,0xE7,0x84,0xAE, + 0xF4,0x8B,0x35,0xA7,0x5D,0x8D,0x11,0x0E,0x0B,0xD7, + 0x36,0x14,0xC4,0xD4,0x3C,0x99,0x5D,0xF2,0x96,0x97, + 0x31,0x32,0xBD,0xF3,0x87,0x56,0xE5,0x9B,0x25,0xCA, + 0x48,0xE9,0x2F,0xF1,0x93,0x98,0x8F,0xDF,0xD3,0x6E, + 0x1A,0x99,0x51,0xF9,0x55,0x52,0xE6,0xBF,0x61,0x8D, + 0xAB,0x26,0xDD,0x5F,0x2A,0x6F,0x61,0x02,0x28,0x0F, + 0x92,0x41,0x76,0xD2,0xFA,0x05,0x79,0xB6,0xBE,0x7B, + 0xB1,0xAE,0xCC,0x89,0xF1,0x5F,0x1F,0x27,0x79,0x30, + 0xAB,0x0F,0x31,0xE0,0x1C,0x40,0x05,0x16,0xAF,0x41, + 0x8C,0x7A,0x4D,0x26,0x5A,0x8C,0x98,0xEC,0x57,0xCF, + 0x94,0xFB,0x3D,0x56,0xB2,0xF5,0x10,0x76,0x4B,0x2D, + 0x77,0x9C,0x4B,0x34,0xC0,0x04,0xAE,0xD0,0xC1,0xAB, + 0x0E,0x61,0xF8,0x74 +}; + +uint8_t _acserverca1[] = { + 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x08,0x0D,0x5D,0xDF,0x69,0x27, + 0x9B,0x23,0x11,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72, + 0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x33, + 0x32,0x36,0x31,0x36,0x35,0x33,0x33,0x37,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x33,0x32,0x36,0x31,0x36,0x35, + 0x33,0x33,0x37,0x5A,0x30,0x6A,0x31,0x24,0x30,0x22, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20, + 0x43,0x41,0x20,0x31,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05, + 0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, + 0x02,0x82,0x01,0x01,0x00,0xE3,0xE9,0x68,0xA1,0xE7, + 0x9B,0xBC,0xF7,0x87,0x48,0x22,0x9B,0x09,0x5F,0xC8, + 0xC9,0xA6,0x9A,0xCC,0xCD,0x40,0x16,0xF8,0xA1,0xD0, + 0xF6,0x27,0x15,0x4C,0xE7,0xD3,0xC1,0x6E,0xDF,0x11, + 0x06,0x9A,0x63,0xC5,0x87,0x55,0xDA,0xDF,0xAF,0x15, + 0x31,0x98,0x45,0xF4,0x8C,0xC2,0x3C,0x93,0xA2,0x1C, + 0xC0,0xF0,0x2A,0x77,0xF4,0x19,0x94,0x96,0xF4,0x7B, + 0x52,0x74,0x84,0x86,0x5A,0x66,0x7D,0x68,0x92,0xA1, + 0x5E,0xE1,0xA9,0x21,0xE0,0x14,0x38,0x84,0x21,0x32, + 0x8B,0x21,0x95,0x47,0x27,0x17,0xA0,0xBA,0x7B,0xD7, + 0xD8,0xD7,0x25,0x20,0x77,0xCB,0x62,0x8B,0xC6,0x0F, + 0xC1,0x49,0xC6,0x2B,0x42,0xE9,0x02,0x70,0x9E,0x99, + 0x44,0x77,0x51,0x05,0x62,0x78,0xBC,0xB0,0xD2,0xA7, + 0xA6,0x91,0x71,0x25,0x58,0x13,0x8D,0x8A,0xC8,0x46, + 0x41,0xDB,0x89,0x41,0xC5,0x23,0x7D,0x84,0xE9,0x02, + 0xB0,0x1A,0xF8,0x5D,0x66,0xD0,0xE1,0xE1,0x72,0xF4, + 0xA4,0x65,0x79,0x97,0x0A,0x7B,0xC0,0xE3,0x24,0x74, + 0x83,0x4A,0x81,0x5E,0xC3,0xA2,0xBF,0x51,0x32,0x96, + 0x8F,0x28,0x32,0x08,0x49,0xFB,0x02,0x43,0x62,0x42, + 0xB3,0x84,0x84,0x30,0x1B,0x28,0xE4,0x05,0xB9,0xBB, + 0xD6,0xB5,0xC4,0xA2,0xAB,0x8E,0x57,0x53,0x29,0xBC, + 0x0B,0x4F,0xD6,0x1E,0xA4,0x52,0xDC,0x16,0x1C,0x95, + 0xC2,0x8D,0x97,0x6B,0xBB,0x3E,0xC8,0x93,0xC7,0x01, + 0x97,0x1E,0x18,0x09,0x59,0x39,0x0F,0x5D,0x73,0x4E, + 0xA9,0x8F,0x49,0xFD,0x49,0x16,0xBD,0x25,0xEC,0xD9, + 0x05,0xEA,0xE3,0xB0,0x04,0x0E,0xD9,0x09,0x9E,0xC0, + 0xB7,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xED,0x30, + 0x81,0xEA,0x30,0x41,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x01,0x01,0x04,0x35,0x30,0x33,0x30,0x31, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, + 0x86,0x25,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, + 0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34, + 0x2D,0x63,0x6F,0x72,0x70,0x72,0x6F,0x6F,0x74,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0xB6,0x23,0xB5,0x5A,0xEB,0x7E,0xEB,0xB6,0xF3,0x28, + 0x1E,0x04,0xD0,0xAD,0x5C,0x93,0xA9,0xA4,0x9A,0x6D, + 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, + 0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x35,0x20,0x26,0xCE,0x85,0xBE,0x49,0x26,0x20,0x01, + 0xDD,0xC8,0xEE,0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5, + 0x30,0x32,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2B,0x30, + 0x29,0x30,0x27,0xA0,0x25,0xA0,0x23,0x86,0x21,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x63,0x6F,0x72,0x70,0x72,0x6F,0x6F,0x74,0x2E,0x63, + 0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10, + 0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x18,0x04,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0x34,0x2F,0xB2, + 0xC2,0xF1,0xF0,0xDC,0xA2,0x9F,0x8F,0x41,0x9C,0x84, + 0xCA,0x66,0xDC,0x90,0x9C,0xC4,0x90,0xC9,0xDA,0xD9, + 0x37,0x4F,0xAE,0xC9,0xD9,0xCF,0xE2,0x4B,0x8E,0x59, + 0x47,0x9A,0x83,0x32,0xDF,0xA7,0x97,0x45,0x9D,0x1E, + 0x46,0x58,0x5D,0xD7,0x1C,0x17,0xC5,0x1C,0x9E,0xA2, + 0x74,0xF6,0x73,0x77,0xF9,0x35,0xAD,0x67,0xC3,0x3C, + 0xD5,0x87,0x1E,0x96,0x16,0x3D,0x8B,0x40,0x51,0xA8, + 0x16,0xA0,0x53,0x1C,0xF5,0xCB,0x32,0xC4,0xA8,0xC5, + 0x2A,0x3A,0x21,0xD9,0xFD,0x51,0x81,0x59,0x6F,0x1B, + 0xF9,0x40,0x86,0x96,0xCF,0xA0,0x73,0xA3,0x5B,0x60, + 0x02,0xB6,0x21,0xAD,0x39,0xF5,0xFA,0xFC,0xA8,0x6E, + 0x34,0x01,0x7C,0x59,0xF3,0x73,0xFC,0xBA,0xBE,0xF4, + 0x4E,0x16,0x36,0x9E,0x51,0x77,0x80,0xF5,0xA1,0xC7, + 0xAE,0xFF,0x04,0x71,0x6B,0xB3,0xBE,0x3E,0xA7,0xD1, + 0x74,0x2B,0x4D,0x58,0x58,0x3B,0x94,0x74,0xA3,0x65, + 0x27,0xC1,0x74,0xA9,0xD2,0xF9,0x8A,0x81,0xB3,0x47, + 0xB3,0x06,0x8E,0x9C,0xE6,0x42,0x86,0x77,0xF8,0x96, + 0x99,0x1F,0xED,0x30,0x8F,0x4B,0xD5,0x0F,0x5E,0x71, + 0x6C,0xAC,0xDB,0x48,0xE3,0x3C,0x58,0x2B,0xE8,0x9B, + 0x9E,0x24,0x8A,0x5D,0xCD,0x56,0x5F,0xA9,0x07,0xEA, + 0xCD,0x2C,0x94,0x3D,0xA7,0x7F,0x1B,0xE8,0x10,0xB8, + 0xD2,0x1E,0x43,0x5A,0x0D,0x13,0xDA,0xF5,0x3F,0x10, + 0x9D,0x2D,0x1F,0xE6,0x94,0x11,0x2F,0x40,0xFF,0x5F, + 0x21,0x96,0x02,0xF0,0x5F,0x54,0x56,0x32,0x90,0xD5, + 0x67,0xAE,0x29,0x0E,0x22,0x70,0xE3,0x2B,0x7A,0x95, + 0xC0,0xC7 +}; + +uint8_t _acrootca[] = { + 0x30,0x82,0x03,0xB1,0x30,0x82,0x02,0x99,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x08,0x14,0x99,0x6B,0x4A,0x6A, + 0xE4,0x40,0xA0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72, + 0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x33,0x30,0x37, + 0x31,0x36,0x31,0x39,0x32,0x30,0x34,0x35,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x37,0x31,0x37,0x31,0x39,0x32, + 0x30,0x34,0x35,0x5A,0x30,0x66,0x31,0x20,0x30,0x1E, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x17,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F, + 0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82, + 0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0xB5,0x3B,0xE3,0x9F,0x6A,0x1D,0x0E,0x46,0x51, + 0x1E,0xD0,0xB5,0x17,0x6B,0x06,0x4B,0x92,0xAF,0x38, + 0x10,0x25,0xA1,0xEE,0x1E,0x4E,0xEF,0x19,0xE0,0x73, + 0xB5,0x37,0x33,0x72,0x21,0x21,0xCB,0x62,0x4A,0x3D, + 0xA9,0x68,0xD8,0x07,0xB4,0xEB,0x8D,0x0A,0xDB,0x30, + 0x33,0x21,0x2F,0x6F,0xD3,0xF7,0x5D,0xCE,0x20,0x0A, + 0x04,0xDB,0xFF,0xBF,0x75,0x08,0x42,0x3F,0x3E,0xD8, + 0xC8,0xEF,0xA4,0xF8,0x56,0x7B,0x13,0x64,0x6B,0xF3, + 0xA2,0x38,0x10,0xFA,0xEE,0x9D,0x83,0x93,0x1D,0xFB, + 0xEF,0x13,0x6C,0x38,0x49,0xDD,0xEB,0x71,0xA6,0x92, + 0x58,0x04,0xDE,0x01,0x41,0x2B,0x99,0x5E,0xBD,0x24, + 0x3F,0x69,0xA8,0x44,0xF2,0xAA,0x01,0x78,0xB9,0x38, + 0x06,0x10,0x77,0x36,0xF8,0xF2,0xA3,0x3E,0xD9,0x5F, + 0xEA,0xF5,0x8B,0x6A,0xA6,0x5F,0xE6,0x51,0xD0,0x9B, + 0x50,0xA0,0x1E,0xF5,0x85,0x9E,0x49,0x50,0x4A,0x61, + 0x78,0xDA,0x29,0xA7,0x33,0x72,0x8B,0x83,0xEE,0x7B, + 0xA7,0x79,0x4E,0x8E,0x02,0x6F,0x9D,0x25,0x97,0x26, + 0x86,0x0C,0x82,0xC5,0x8C,0x16,0x7E,0x49,0x61,0xFD, + 0xFF,0x1A,0xA0,0x0D,0x28,0xE1,0x68,0xF5,0xAE,0x85, + 0x72,0xF3,0xAB,0xE0,0x74,0x75,0xCC,0x57,0x64,0x3C, + 0x2C,0x55,0x05,0xC9,0x8D,0xAA,0xB3,0xEC,0xC8,0x62, + 0x88,0x15,0x2A,0xC4,0x59,0x60,0x37,0xC1,0xED,0x6B, + 0xCE,0xE9,0xCA,0xAF,0xB0,0xA5,0x45,0xBA,0xFF,0x16, + 0x32,0xAA,0x92,0x86,0xD9,0xB9,0xA1,0x13,0x75,0x95, + 0x9B,0x97,0x5C,0x2D,0xB5,0x12,0xCA,0x6B,0x6B,0x39, + 0xD6,0x9B,0x4B,0x34,0x47,0xAB,0x35,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x35,0x20,0x26, + 0xCE,0x85,0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE, + 0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30,0x0F,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, + 0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x35,0x20,0x26, + 0xCE,0x85,0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE, + 0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x01,0x06,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x73,0x02,0x4A,0xA6,0x77,0x02,0xA7, + 0xE1,0xCB,0x52,0x97,0x9D,0x89,0x11,0xA0,0x8F,0xBC, + 0xF3,0x8F,0x14,0x01,0x29,0xF3,0xA5,0x45,0x17,0x06, + 0xF8,0x04,0xF2,0x6D,0xD5,0xC3,0x77,0xB8,0x00,0xC2, + 0x0A,0x1A,0x09,0x32,0x36,0x36,0x69,0xC1,0x2A,0xF0, + 0x44,0x37,0xBC,0x7E,0x5F,0x15,0xF7,0x08,0x9C,0x19, + 0x27,0x1D,0x70,0x4F,0xDC,0x17,0x94,0x3C,0xBB,0x24, + 0xB4,0xE6,0xFC,0x71,0x9A,0xD4,0xCF,0x2C,0x12,0xBA, + 0xF0,0xB6,0x8F,0x78,0x99,0xAA,0x8C,0x17,0x7E,0x94, + 0x0C,0x6A,0x37,0x5B,0x35,0x91,0x52,0xFA,0x64,0xA3, + 0x33,0x34,0x99,0x37,0x00,0x3C,0xB4,0x4E,0x6E,0x63, + 0xED,0xC3,0x1D,0x37,0x5B,0x45,0xB4,0xDF,0x82,0xCD, + 0xFE,0xAA,0x92,0x64,0xC8,0x2F,0xD6,0x2D,0x2E,0xB1, + 0xED,0x6A,0x04,0xF1,0xC2,0x48,0x8D,0x4B,0xB4,0x84, + 0x39,0xA3,0x31,0x4D,0xF6,0x63,0xB4,0xC3,0x6E,0xA1, + 0xA5,0x2F,0xD2,0x1E,0xB0,0xC6,0x0C,0xD1,0x04,0x3A, + 0x31,0xBC,0x87,0x49,0xF8,0x26,0x0B,0xD3,0x0C,0x08, + 0x29,0xBB,0x9F,0x4D,0x08,0xF0,0x9C,0x11,0xD3,0xA5, + 0x2C,0x8D,0x98,0xB1,0x1B,0xB1,0x57,0xD3,0x69,0xAE, + 0x9E,0x2D,0xD5,0x64,0x38,0x58,0xC9,0xB2,0x84,0x04, + 0xAB,0x10,0x1D,0xCA,0x6B,0x29,0xA5,0xAB,0xCC,0xFE, + 0xBB,0x74,0xF4,0x35,0x03,0x8F,0x65,0x2A,0x0B,0xBB, + 0xC7,0x17,0x6A,0x49,0x34,0x83,0x30,0x92,0x8D,0xD7, + 0xAE,0x95,0xD0,0xD7,0x23,0xA7,0xE3,0x29,0x09,0xA1, + 0xB1,0x34,0xC3,0x95,0x49,0xC3,0xA4,0xF1,0x36,0x00, + 0x09,0xD3,0xA4,0x09,0xAD,0xF2,0x5C,0x97,0xB2 +}; + +uint8_t _acserverca1_spki[] = { + 0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00, + 0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xe3,0xe9,0x68, + 0xa1,0xe7,0x9b,0xbc,0xf7,0x87,0x48,0x22,0x9b,0x09,0x5f,0xc8, + 0xc9,0xa6,0x9a,0xcc,0xcd,0x40,0x16,0xf8,0xa1,0xd0,0xf6,0x27, + 0x15,0x4c,0xe7,0xd3,0xc1,0x6e,0xdf,0x11,0x06,0x9a,0x63,0xc5, + 0x87,0x55,0xda,0xdf,0xaf,0x15,0x31,0x98,0x45,0xf4,0x8c,0xc2, + 0x3c,0x93,0xa2,0x1c,0xc0,0xf0,0x2a,0x77,0xf4,0x19,0x94,0x96, + 0xf4,0x7b,0x52,0x74,0x84,0x86,0x5a,0x66,0x7d,0x68,0x92,0xa1, + 0x5e,0xe1,0xa9,0x21,0xe0,0x14,0x38,0x84,0x21,0x32,0x8b,0x21, + 0x95,0x47,0x27,0x17,0xa0,0xba,0x7b,0xd7,0xd8,0xd7,0x25,0x20, + 0x77,0xcb,0x62,0x8b,0xc6,0x0f,0xc1,0x49,0xc6,0x2b,0x42,0xe9, + 0x02,0x70,0x9e,0x99,0x44,0x77,0x51,0x05,0x62,0x78,0xbc,0xb0, + 0xd2,0xa7,0xa6,0x91,0x71,0x25,0x58,0x13,0x8d,0x8a,0xc8,0x46, + 0x41,0xdb,0x89,0x41,0xc5,0x23,0x7d,0x84,0xe9,0x02,0xb0,0x1a, + 0xf8,0x5d,0x66,0xd0,0xe1,0xe1,0x72,0xf4,0xa4,0x65,0x79,0x97, + 0x0a,0x7b,0xc0,0xe3,0x24,0x74,0x83,0x4a,0x81,0x5e,0xc3,0xa2, + 0xbf,0x51,0x32,0x96,0x8f,0x28,0x32,0x08,0x49,0xfb,0x02,0x43, + 0x62,0x42,0xb3,0x84,0x84,0x30,0x1b,0x28,0xe4,0x05,0xb9,0xbb, + 0xd6,0xb5,0xc4,0xa2,0xab,0x8e,0x57,0x53,0x29,0xbc,0x0b,0x4f, + 0xd6,0x1e,0xa4,0x52,0xdc,0x16,0x1c,0x95,0xc2,0x8d,0x97,0x6b, + 0xbb,0x3e,0xc8,0x93,0xc7,0x01,0x97,0x1e,0x18,0x09,0x59,0x39, + 0x0f,0x5d,0x73,0x4e,0xa9,0x8f,0x49,0xfd,0x49,0x16,0xbd,0x25, + 0xec,0xd9,0x05,0xea,0xe3,0xb0,0x04,0x0e,0xd9,0x09,0x9e,0xc0, + 0xb7,0x02,0x03,0x01,0x00,0x01 +}; + +uint8_t _acrootca_spki[] = { + 0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00, + 0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb5,0x3b,0xe3, + 0x9f,0x6a,0x1d,0x0e,0x46,0x51,0x1e,0xd0,0xb5,0x17,0x6b,0x06, + 0x4b,0x92,0xaf,0x38,0x10,0x25,0xa1,0xee,0x1e,0x4e,0xef,0x19, + 0xe0,0x73,0xb5,0x37,0x33,0x72,0x21,0x21,0xcb,0x62,0x4a,0x3d, + 0xa9,0x68,0xd8,0x07,0xb4,0xeb,0x8d,0x0a,0xdb,0x30,0x33,0x21, + 0x2f,0x6f,0xd3,0xf7,0x5d,0xce,0x20,0x0a,0x04,0xdb,0xff,0xbf, + 0x75,0x08,0x42,0x3f,0x3e,0xd8,0xc8,0xef,0xa4,0xf8,0x56,0x7b, + 0x13,0x64,0x6b,0xf3,0xa2,0x38,0x10,0xfa,0xee,0x9d,0x83,0x93, + 0x1d,0xfb,0xef,0x13,0x6c,0x38,0x49,0xdd,0xeb,0x71,0xa6,0x92, + 0x58,0x04,0xde,0x01,0x41,0x2b,0x99,0x5e,0xbd,0x24,0x3f,0x69, + 0xa8,0x44,0xf2,0xaa,0x01,0x78,0xb9,0x38,0x06,0x10,0x77,0x36, + 0xf8,0xf2,0xa3,0x3e,0xd9,0x5f,0xea,0xf5,0x8b,0x6a,0xa6,0x5f, + 0xe6,0x51,0xd0,0x9b,0x50,0xa0,0x1e,0xf5,0x85,0x9e,0x49,0x50, + 0x4a,0x61,0x78,0xda,0x29,0xa7,0x33,0x72,0x8b,0x83,0xee,0x7b, + 0xa7,0x79,0x4e,0x8e,0x02,0x6f,0x9d,0x25,0x97,0x26,0x86,0x0c, + 0x82,0xc5,0x8c,0x16,0x7e,0x49,0x61,0xfd,0xff,0x1a,0xa0,0x0d, + 0x28,0xe1,0x68,0xf5,0xae,0x85,0x72,0xf3,0xab,0xe0,0x74,0x75, + 0xcc,0x57,0x64,0x3c,0x2c,0x55,0x05,0xc9,0x8d,0xaa,0xb3,0xec, + 0xc8,0x62,0x88,0x15,0x2a,0xc4,0x59,0x60,0x37,0xc1,0xed,0x6b, + 0xce,0xe9,0xca,0xaf,0xb0,0xa5,0x45,0xba,0xff,0x16,0x32,0xaa, + 0x92,0x86,0xd9,0xb9,0xa1,0x13,0x75,0x95,0x9b,0x97,0x5c,0x2d, + 0xb5,0x12,0xca,0x6b,0x6b,0x39,0xd6,0x9b,0x4b,0x34,0x47,0xab, + 0x35,0x02,0x03,0x01,0x00,0x01 +}; + +uint8_t _acrootca_hash[] = { + 0x50,0x41,0x69,0xc1,0x76,0xa2,0xc3,0x0d,0xa2,0xe9,0x0e,0xa9, + 0x8a,0x53,0x5d,0x78,0xef,0x42,0xf3,0x1a,0x90,0xfa,0x48,0xb6, + 0xce,0xc2,0x45,0xa4,0x72,0x12,0x7a,0xd3 +}; + + +#endif /* _TRUSTTESTS_EVALUATION_CT_TESTS_H_ */ -- 2.45.2