]> git.saurik.com Git - apple/security.git/commitdiff
Security-59754.60.13.tar.gz v59754.60.13
authorApple <opensource@apple.com>
Fri, 18 Dec 2020 07:48:56 +0000 (07:48 +0000)
committerApple <opensource@apple.com>
Fri, 18 Dec 2020 07:48:56 +0000 (07:48 +0000)
57 files changed:
Analytics/Clients/LocalKeychainAnalytics.m
OSX/Modules [new symlink]
OSX/authd/authorization.plist
OSX/authd/engine.c
OSX/include/security_asn1 [new symlink]
OSX/include/security_cdsa_client [new symlink]
OSX/include/security_cdsa_plugin [new symlink]
OSX/include/security_cdsa_utilities [new symlink]
OSX/include/security_cdsa_utils [new symlink]
OSX/include/security_codesigning [new symlink]
OSX/include/security_comcryption [new symlink]
OSX/include/security_cryptkit [new symlink]
OSX/include/security_filedb [new symlink]
OSX/include/security_keychain [new symlink]
OSX/include/security_ocspd [new symlink]
OSX/include/security_pkcs12 [new symlink]
OSX/include/security_smime [new symlink]
OSX/include/security_utilities [new symlink]
OSX/include/securityd_client [new symlink]
OSX/libsecurity_asn1/security_asn1 [new symlink]
OSX/libsecurity_authorization/lib/Authorization.c
OSX/libsecurity_codesigning/lib/SecCodePriv.h
OSX/libsecurity_codesigning/lib/SecStaticCode.cpp
OSX/libsecurity_codesigning/lib/StaticCode.cpp
OSX/libsecurity_codesigning/lib/bundlediskrep.cpp
OSX/libsecurity_codesigning/lib/bundlediskrep.h
OSX/libsecurity_codesigning/lib/csutilities.cpp
OSX/libsecurity_codesigning/lib/csutilities.h
OSX/libsecurity_keychain/Security [new symlink]
OSX/libsecurity_ssl/Security [new symlink]
OSX/libsecurity_ssl/security_ssl [new symlink]
OSX/sec/ipc/com.apple.secd.plist
OSX/sec/ipc/com.apple.securityd.plist
OSX/sec/ipc/server.c
OSX/utilities/SecCoreAnalytics.h
OSX/utilities/SecCoreAnalytics.m
RegressionTests/Security.plist
RegressionTests/bats_utd_plist.h
RegressionTests/secsecstaticcodeapitest.c [new file with mode: 0644]
Security.exp-in
Security.xcodeproj/project.pbxproj
keychain/TrustedPeersHelper/Container.swift
keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift
keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift
keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h
keychain/ckks/CKKSAnalytics.h
keychain/ckks/CKKSAnalytics.m
keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m
keychain/ot/OTCuttlefishContext.m
keychain/ot/OTManager.m
keychain/ot/tests/octagon/OctagonTests+CKKS.swift
keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift
keychain/securityd/com.apple.secd.sb
libsecurity_smime/Security [new symlink]
libsecurity_smime/security_smime [new symlink]
tests/TrustTests/EvaluationTests/CARevocationTests.m [new file with mode: 0644]
tests/TrustTests/EvaluationTests/CARevocationTests_data.h [new file with mode: 0644]

index 9eabc0acd70f203dbe8eef627fc6b674e2c1c093..22c40fca94151593ddda9f9bd6ea8e4e6ec219ad 100644 (file)
@@ -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 (symlink)
index 0000000..287aeb4
--- /dev/null
@@ -0,0 +1 @@
+./Modules
\ No newline at end of file
index 4236dff67813d359bddee7ce1b9f75f04b34d1b3..c3b4ffe9042b4c7d018ff7d91bc0d6fac52ce192 100644 (file)
@@ -1775,6 +1775,17 @@ See remaining rules for examples.
             <key>shared</key>
             <false/>
         </dict>
+        <key>com.apple.system-migration.launch-password</key>
+        <dict>
+            <key>comment</key>
+            <string>Used by Migration Assistant.</string>
+            <key>class</key>
+            <string>rule</string>
+            <key>rule</key>
+            <string>authenticate-admin-nonshared-password</string>
+            <key>shared</key>
+            <false/>
+        </dict>
         <key>com.apple.system-migration.cleanup</key>
         <dict>
             <key>comment</key>
@@ -1879,6 +1890,21 @@ See remaining rules for examples.
                        <key>version</key>
                        <integer>1</integer>
                </dict>
+        <key>authenticate-admin-nonshared-password</key>
+        <dict>
+            <key>class</key>
+            <string>user</string>
+            <key>comment</key>
+            <string>Authenticate as an administrator with the password.</string>
+            <key>group</key>
+            <string>admin</string>
+            <key>password-only</key>
+            <true/>
+            <key>timeout</key>
+            <integer>30</integer>
+            <key>version</key>
+            <integer>1</integer>
+        </dict>
         <key>_mbsetupuser-nonshared</key>
         <dict>
             <key>class</key>
index 08a4f80e07c6d45af0961db3de1e32d4ef50b63a..92648f016778dc17df8ce7b632f95a65e23021be 100644 (file)
@@ -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 (symlink)
index 0000000..09ef080
--- /dev/null
@@ -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 (symlink)
index 0000000..9737c61
--- /dev/null
@@ -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 (symlink)
index 0000000..2be156f
--- /dev/null
@@ -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 (symlink)
index 0000000..2634481
--- /dev/null
@@ -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 (symlink)
index 0000000..f3e5247
--- /dev/null
@@ -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 (symlink)
index 0000000..7c67092
--- /dev/null
@@ -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 (symlink)
index 0000000..cbcdf21
--- /dev/null
@@ -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 (symlink)
index 0000000..609dcc3
--- /dev/null
@@ -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 (symlink)
index 0000000..99185cd
--- /dev/null
@@ -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 (symlink)
index 0000000..aac53b6
--- /dev/null
@@ -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 (symlink)
index 0000000..449ea98
--- /dev/null
@@ -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 (symlink)
index 0000000..8fdcb01
--- /dev/null
@@ -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 (symlink)
index 0000000..e1a40ba
--- /dev/null
@@ -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 (symlink)
index 0000000..4d363d1
--- /dev/null
@@ -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 (symlink)
index 0000000..2edb676
--- /dev/null
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -0,0 +1 @@
+.
\ No newline at end of file
index e88dae1fdaf4b0c99daf4ada03236864eeb7a3cc..17b3ad5721f364ef0782164bc28b6ff1d6d22079 100644 (file)
@@ -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;
         }
     }
     
index e2cac5dd1c3d169b1eb8bb73da90edcd296a7375..a5b128cd54cfbd4c3ff78ff7a7e05d98bcfc418c 100644 (file)
@@ -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
index 0fa873e1a24ca54fd75661ea55b2d64e45c6bb17..13d7b0f7c7f3d4b7d62a13c5cd5b956e2cffefa6 100644 (file)
@@ -127,6 +127,7 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se
                | kSecCSSingleThreaded
                | kSecCSApplyEmbeddedPolicy
                | kSecCSSkipRootVolumeExceptions
+               | kSecCSSkipXattrFiles
        );
 
        if (errors)
index 033ef507f861d64fb1bbd79a1f44004b122f84a9..85abf01ac3867e0c71584636d49d4f6a773b0161 100644 (file)
@@ -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<CFURLRef> itemURL = makeCFURL(relpath, false, resourceBase());
                                                string itemPath = cfString(itemURL);
index efc14c1cc34681fbe6000a0671828166a5c3f331..daf77c5d2847219dce6a564826eadbccb951b490 100644 (file)
@@ -24,6 +24,7 @@
 #include "filediskrep.h"
 #include "dirscanner.h"
 #include "notarization.h"
+#include "csutilities.h"
 #include <CoreFoundation/CFBundlePriv.h>
 #include <CoreFoundation/CFURLAccess.h>
 #include <CoreFoundation/CFBundlePriv.h>
@@ -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
index af3e40e2c228a8b230625e5e72ec8776544a1854..932cb27fb3a6843dea354f03e34f773250d12d75 100644 (file)
@@ -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);
index 2d9c65bfd3aa97e2cfeae3313aa0e1d29e3e6805..ff0f15dd6b6a9ae73548fa0f48bbe3398f1a0917 100644 (file)
 #include <security_utilities/errors.h>
 #include <sys/mount.h>
 #include <sys/utsname.h>
+#include <errno.h>
+#include <sys/attr.h>
+#include <sys/xattr.h>
+#include <libgen.h>
 #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
index 2c9017f348f1b58b08c823fb0ce8cca339632ed4..6a69749f1accefafea7c6b78d77839f772d10abc 100644 (file)
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -0,0 +1 @@
+.
\ No newline at end of file
index f9484f12893a46fe1b149231a80b98017016d1da..3f2b01a06ba1e059cb33caabe55ad92362038f4a 100644 (file)
                                <key>Interval</key>
                                <real>86400</real>
                        </dict>
+                       <key>com.apple.securityd.entropyhealth</key>
+                       <dict>
+                               <key>Priority</key>
+                               <string>Utility</string>
+                               <key>Interval</key>
+                               <real>86400</real>
+                       </dict>
                        <key>com.apple.securityd.prng</key>
                        <dict>
                                <key>Priority</key>
index 6be938f59e4d3e8a07d57e9ae207c530d17e0e35..9fd326faf1dcf6f6c005556f1c97a8c87da937d9 100644 (file)
                                <key>NetworkTransferDirection</key>
                                <string>Bidirectional</string>
                        </dict>
+                       <key>com.apple.securityd.entropyhealth</key>
+                       <dict>
+                               <key>Priority</key>
+                               <string>Utility</string>
+                               <key>Interval</key>
+                               <real>86400</real>
+                       </dict>
                        <key>com.apple.securityd.prng</key>
                        <dict>
                                <key>Priority</key>
index 86935cfec588fd319a10d32e02dd2229fe49dd87..127ac94425926ce210dbd67d6e6e5ad96e658b0d 100644 (file)
@@ -62,6 +62,7 @@
 #include <utilities/SecAKSWrappers.h>
 #include <utilities/SecCFError.h>
 #include <utilities/SecCFWrappers.h>
+#include <utilities/SecCoreAnalytics.h>
 #include <utilities/SecDb.h>
 #include <utilities/SecIOFormat.h>
 #include <utilities/SecXPCError.h>
@@ -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) {
index 2f8dc662b5be6a86be3dc20d0be91594cfd57702..f9608865db7ae683ae546f492cacd3d6898e751f 100644 (file)
@@ -24,6 +24,7 @@
 #include <CoreFoundation/CoreFoundation.h>
 
 void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value);
+void SecCoreAnalyticsSendKernEntropyHealth(void);
 
 #if __OBJC__
 
index e58cea450fe65a963e31e0146dd5c9390505ffcb..e1edc3cc4ca97d916de1da1b2b925dd4f60da3f2 100644 (file)
@@ -25,6 +25,7 @@
 #import <CoreAnalytics/CoreAnalytics.h>
 #import <SoftLinking/SoftLinking.h>
 #import <Availability.h>
+#import <sys/sysctl.h>
 
 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<NSString *,NSObject *> * _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);
index 4bcfade31e6f4c11b1f2eae4c6fc6dc46b994202..c983792dd234573fd6931ff416d9e6712aa6fe9f 100644 (file)
                        <key>ShowSubtestResults</key>
                        <true/>
                </dict>
+        <dict>
+            <key>TestName</key>
+            <string>SecStaticCodeAPITest</string>
+            <key>Command</key>
+            <array>
+                <string>/AppleInternal/CoreOS/tests/Security/secsecstaticcodeapitest</string>
+            </array>
+            <key>Disabled</key>
+            <string>BATS_UTD_Disabled_SecStaticCodeAPITest</string>
+            <key>ShowSubtestResults</key>
+            <true/>
+        </dict>
        </array>
 </dict>
 </plist>
index 78aa0fef3fe8b227ff8c9bc703ccf911eacd1d4f..cf3d6a8b15ebdc485861be4de6ec9d1d580b4b93 100644 (file)
@@ -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_
 #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. */
 #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 (file)
index 0000000..3dc2b59
--- /dev/null
@@ -0,0 +1,229 @@
+//
+//  secsecstaticcodeapitest.c
+//  secsecstaticcodeapitest
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <AssertMacros.h>
+#include <sys/xattr.h>
+#include <Security/SecCodePriv.h>
+#include <Security/SecCode.h>
+#include <Security/SecStaticCode.h>
+
+#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;
+}
index 241e9740f5b338535c5b7a98425de39828e9af33..9302304a33885d54010fb5d1d0b8892e6ea85156 100644 (file)
@@ -2087,6 +2087,7 @@ _OBJC_CLASS_$_SFAnalyticsSQLiteStore
 _OBJC_CLASS_$_SecCoreAnalytics
 _SecCoreAnalyticsValue
 _SecCoreAnalyticsSendValue
+_SecCoreAnalyticsSendKernEntropyHealth
 _SFAnalyticsMaxEventsToReport
 _SFSQLiteJournalSuffixes
 _SFAnalyticsSamplerIntervalOncePerReport
index 6ccf9ee997df6aa4be37477d805a5fe41de29e57..05c364386b750e781b20202cbf2eff65e1be9d48 100644 (file)
                        buildPhases = (
                        );
                        dependencies = (
+                               3E4D531F2531185D00B124B3 /* PBXTargetDependency */,
                                0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */,
                                6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */,
                                6CC639002266AE0A00E5DB0B /* PBXTargetDependency */,
                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 */; };
                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 */; };
                        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 */;
                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 = "<group>"; };
+               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 = "<group>"; };
                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 = "<group>"; };
                433E519D1B66D5F600482618 /* AppSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppSupport.framework; path = System/Library/PrivateFrameworks/AppSupport.framework; sourceTree = SDKROOT; };
                BECFA43C20F9493000B11002 /* Policy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Policy.swift; sourceTree = "<group>"; };
                BECFA46320FFB87400B11002 /* TPKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKey.m; sourceTree = "<group>"; };
                BED01530206F050F0027A2B4 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = trust/README.txt; sourceTree = "<group>"; };
+               BED0781D2542A2B300FED203 /* CARevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CARevocationTests_data.h; path = tests/TrustTests/EvaluationTests/CARevocationTests_data.h; sourceTree = "<group>"; };
+               BED078F82542A2BF00FED203 /* CARevocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CARevocationTests.m; path = tests/TrustTests/EvaluationTests/CARevocationTests.m; sourceTree = "<group>"; };
                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 = "<group>"; };
                BED208E71EDF971600753952 /* manifeststresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = manifeststresstest.m; path = manifeststresstest/manifeststresstest.m; sourceTree = "<group>"; };
                        );
                        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;
                        path = SecureTransportTests;
                        sourceTree = "<group>";
                };
+               3E4D4DFF2531174400B124B3 /* secsecstaticcodeapitest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               3E4D508E253117DD00B124B3 /* secsecstaticcodeapitest.c */,
+                       );
+                       name = secsecstaticcodeapitest;
+                       sourceTree = "<group>";
+               };
                3E88361224F0693200E9F4D6 /* secseccodeapitest */ = {
                        isa = PBXGroup;
                        children = (
                                6C2045EA2424BA7E00F9461D /* KeychainStasher */,
                                6C963281242A279B00C53CE2 /* stashtester */,
                                3E88361124F068EF00E9F4D6 /* secseccodeapitest */,
+                               3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                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 */,
                EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = {
                        isa = PBXGroup;
                        children = (
+                               3E4D4DFF2531174400B124B3 /* secsecstaticcodeapitest */,
                                3E88361224F0693200E9F4D6 /* secseccodeapitest */,
                                6CF33CA2238714C900D1E75D /* bats_utd_plist.h */,
                                6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */,
                        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" */;
                                EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */,
                                DAE40BC520CF3E46002D5674 /* secitemcanarytest */,
                                3E88360824F068EF00E9F4D6 /* secseccodeapitest */,
+                               3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */,
                                DCE4E7CB1D7A4AED00AFB96E /* sectests_macos */,
                                470415CE1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */,
                                47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               3E4D49B42531170600B124B3 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               3E4D508F253117DD00B124B3 /* secsecstaticcodeapitest.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                3E88360924F068EF00E9F4D6 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                D458C4C2214E19FC0043D982 /* TrustSettingsInterfaceTests.m in Sources */,
                                D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */,
                                D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */,
+                               BED07B862542A2CE00FED203 /* CARevocationTests.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                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 */,
                                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 */,
                        target = DC0BCC211D8C684F00070CB0 /* utilities */;
                        targetProxy = 3DD258A1204B7DA800F5DA78 /* PBXContainerItemProxy */;
                };
+               3E4D531F2531185D00B124B3 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */;
+                       targetProxy = 3E4D531E2531185D00B124B3 /* PBXContainerItemProxy */;
+               };
                3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 3E88360824F068EF00E9F4D6 /* secseccodeapitest */;
                        };
                        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 = {
                        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 = (
index cd3b61e71dda5a6ff60589706e693ffa148a296a..86f29eecc93ee49e1e864f4a5c8fdbce57a02d25 100644 (file)
@@ -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)
index 4236b8c338712556b596061a9a0ed4cf220973e0..caf3d460ed0274b2a534d259dfcfa8663059ebd8 100644 (file)
@@ -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 {
index 083d98beb694901207df645f12301b1bb29c40f7..580b6034f314625f9b756b72a1b7714183554e33 100644 (file)
@@ -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)
+    }
 }
index 9753ef8dd5ae650e0198a99a008625a62c88a5e0..1ab6328e73316a318fcb747277e2a2d46935aa0c 100644 (file)
@@ -22,3 +22,4 @@
 #import "keychain/securityd/SecItemDataSource.h"
 
 #import "keychain/ckks/tests/MockCloudKit.h"
+#import <Security/OTConstants.h>
index 357a032c96eb1b999211b296dc20a03edf3d1347..6454637dc6eb95bfee26698a392dfbbc5e2dd3ab 100644 (file)
@@ -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;
index dcc6b61c1bbb0a27e4430cf7f1461aea0196d662..9300420d96d3748efe57fb8a8e0c7de8aec1dc62 100644 (file)
@@ -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";
index 758884c0360b5fb833091b909e5e3af0114488dd..d8f5d5356ce56d770226d053abc68414c0fb9fa4 100644 (file)
     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;
index a5e52ed41d2ea8c879df6aa86c7f72e0ed17b3dc..6f9b7907f1af9cd9ac578349b17211dbe2e3eff9 100644 (file)
@@ -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;
 
index 20359984ed5a520f29669825eaf25ffe567e03b7..028b573fa46acef0ce7521d6b4ac9d960ed5efe3 100644 (file)
@@ -78,6 +78,9 @@
 
 #import <CoreCDP/CDPFollowUpController.h>
 
+#import <SoftLinking/SoftLinking.h>
+#import <CloudServices/SecureBackup.h>
+
 #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);
+                }
             }
         }
 
index 96b150165131111d0d692c291c8a8b289c00678d..0aa2cb090ae4d8ceecb84b41e20e4c9b206878bc 100644 (file)
@@ -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
index 5f9a4f503ddd12774b1be660fd0b6deb24138269..91aadb9ccdef1669c43f7ebdf00e4a934b700fa3 100644 (file)
@@ -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<EscrowRecordMO>
             let partial = container.containerMO.partiallyViableEscrowRecords as! Set<EscrowRecordMO>
             let full = container.containerMO.fullyViableEscrowRecords as! Set<EscrowRecordMO>
@@ -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<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
             XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
             XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
                 XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
             XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
             XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
+            XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
+            XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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)
     }
 }
 
index 48c79e591c2cdc1fd47bb1d4447580f2de72d9a2..eb7ab1f715d34e9bd6ecd1f726b9dee239b45479 100644 (file)
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -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 (symlink)
index 0000000..945c9b4
--- /dev/null
@@ -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 (file)
index 0000000..d839cee
--- /dev/null
@@ -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 <AssertMacros.h>
+#import <XCTest/XCTest.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecPolicyPriv.h>
+#include <Security/SecTrustPriv.h>
+#include "OSX/utilities/SecCFWrappers.h"
+#include <Security/SecTrustSettings.h>
+#include <Security/SecTrustSettingsPriv.h>
+#include <Security/SecFramework.h>
+#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 (file)
index 0000000..7bac453
--- /dev/null
@@ -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_ */