2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
26 #include <MobileGestalt.h>
29 #import <os/feature_private.h>
31 #import "keychain/ot/OTConstants.h"
32 #import "utilities/debugging.h"
34 NSErrorDomain const OctagonErrorDomain = @"com.apple.security.octagon";
36 NSString* OTDefaultContext = @"defaultContext";
37 NSString* OTDefaultsDomain = @"com.apple.security.octagon";
38 NSString* OTDefaultsOctagonEnable = @"enable";
40 NSString* OTProtocolPairing = @"OctagonPairing";
41 NSString* OTProtocolPiggybacking = @"OctagonPiggybacking";
43 const char * OTTrustStatusChangeNotification = "com.apple.security.octagon.trust-status-change";
45 NSString* const CuttlefishErrorDomain = @"CuttlefishError";
46 NSString* const CuttlefishErrorRetryAfterKey = @"retryafter";
48 NSString* OTEscrowRecordPrefix = @"com.apple.icdp.record.";
50 // I don't recommend using this command, but it does describe the plist that will enable this feature:
52 // defaults write /System/Library/FeatureFlags/Domain/Security octagon -dict Enabled -bool YES
54 static bool OctagonEnabledOverrideSet = false;
55 static bool OctagonEnabledOverride = false;
57 static bool OctagonRecoveryKeyEnabledOverrideSet = false;
58 static bool OctagonRecoveryKeyEnabledOverride = false;
60 static bool OctagonAuthoritativeTrustEnabledOverrideSet = false;
61 static bool OctagonAuthoritativeTrustEnabledOverride = false;
63 static bool OctagonSOSFeatureIsEnabledOverrideSet = false;
64 static bool OctagonSOSFeatureIsEnabledOverride = false;
66 static bool OctagonOptimizationIsEnabledOverrideSet = false;
67 static bool OctagonOptimizationIsEnabledOverride = false;
69 static bool OctagonEscrowRecordFetchIsEnabledOverrideSet = false;
70 static bool OctagonEscrowRecordFetchIsEnabledOverride = false;
72 static bool SecKVSOnCloudKitIsEnabledOverrideSet = false;
73 static bool SecKVSOnCloudKitIsEnabledOverride = false;
75 static bool SecErrorNestedErrorCappingIsEnabledOverrideSet = false;
76 static bool SecErrorNestedErrorCappingIsEnabledOverride = false;
78 bool OctagonIsEnabled(void)
80 if(OctagonEnabledOverrideSet) {
81 secnotice("octagon", "Octagon is %@ (overridden)", OctagonEnabledOverride ? @"enabled" : @"disabled");
82 return OctagonEnabledOverride;
85 static bool octagonEnabled = false;
86 static dispatch_once_t onceToken;
87 dispatch_once(&onceToken, ^{
88 octagonEnabled = os_feature_enabled(Security, octagon);
89 secnotice("octagon", "Octagon is %@ (via feature flags)", octagonEnabled ? @"enabled" : @"disabled");
92 return octagonEnabled;
95 void OctagonSetIsEnabled(BOOL value)
97 OctagonEnabledOverrideSet = true;
98 OctagonEnabledOverride = value;
101 static bool OctagonOverridePlatformSOS = false;
102 static bool OctagonPlatformSOSOverrideValue = false;
103 static bool OctagonPlatformSOSUpgrade = false;
105 BOOL OctagonPlatformSupportsSOS(void)
107 if(OctagonOverridePlatformSOS) {
108 return OctagonPlatformSOSOverrideValue ? YES : NO;
114 static bool isSOSCapable = false;
116 static dispatch_once_t onceToken;
117 dispatch_once(&onceToken, ^{
118 // Only iPhones, iPads, and iPods support SOS.
119 CFStringRef deviceClass = MGCopyAnswer(kMGQDeviceClass, NULL);
121 isSOSCapable = deviceClass && (CFEqual(deviceClass, kMGDeviceClassiPhone) ||
122 CFEqual(deviceClass, kMGDeviceClassiPad) ||
123 CFEqual(deviceClass, kMGDeviceClassiPod));
126 CFRelease(deviceClass);
128 secerror("octagon: Unable to determine device class. Guessing SOS status as Not Supported");
129 isSOSCapable = false;
132 secnotice("octagon", "SOS is %@ on this platform" , isSOSCapable ? @"supported" : @"not supported");
135 return isSOSCapable ? YES : NO;
141 void OctagonSetPlatformSupportsSOS(BOOL value)
143 OctagonPlatformSOSOverrideValue = value;
144 OctagonOverridePlatformSOS = YES;
147 void OctagonSetSOSUpgrade(BOOL value)
149 OctagonPlatformSOSUpgrade = value;
152 BOOL OctagonPerformSOSUpgrade()
154 if(OctagonPlatformSOSUpgrade){
155 return OctagonPlatformSOSUpgrade;
157 return os_feature_enabled(Security, octagonSOSupgrade);
160 BOOL OctagonRecoveryKeyIsEnabled(void)
162 if(OctagonRecoveryKeyEnabledOverrideSet) {
163 secnotice("octagon", "Octagon RecoveryKey is %@ (overridden)", OctagonRecoveryKeyEnabledOverride ? @"enabled" : @"disabled");
164 return OctagonRecoveryKeyEnabledOverride;
167 static bool octagonRecoveryKeyEnabled = false;
168 static dispatch_once_t onceToken;
169 dispatch_once(&onceToken, ^{
170 octagonRecoveryKeyEnabled = os_feature_enabled(Security, recoverykey);
171 secnotice("octagon", "Octagon is %@ (via feature flags)", octagonRecoveryKeyEnabled ? @"enabled" : @"disabled");
174 return octagonRecoveryKeyEnabled;
177 void OctagonRecoveryKeySetIsEnabled(BOOL value)
179 OctagonRecoveryKeyEnabledOverrideSet = true;
180 OctagonRecoveryKeyEnabledOverride = value;
184 BOOL OctagonAuthoritativeTrustIsEnabled(void)
186 if(OctagonAuthoritativeTrustEnabledOverrideSet) {
187 secnotice("octagon", "Authoritative Octagon Trust is %@ (overridden)", OctagonAuthoritativeTrustEnabledOverride ? @"enabled" : @"disabled");
188 return OctagonAuthoritativeTrustEnabledOverride;
191 static bool octagonAuthoritativeTrustEnabled = false;
192 static dispatch_once_t onceToken;
193 dispatch_once(&onceToken, ^{
194 octagonAuthoritativeTrustEnabled = os_feature_enabled(Security, octagonTrust);
195 secnotice("octagon", "Authoritative Octagon Trust is %@ (via feature flags)", octagonAuthoritativeTrustEnabled ? @"enabled" : @"disabled");
198 return octagonAuthoritativeTrustEnabled;
201 void OctagonAuthoritativeTrustSetIsEnabled(BOOL value)
203 OctagonAuthoritativeTrustEnabledOverrideSet = true;
204 OctagonAuthoritativeTrustEnabledOverride = value;
207 BOOL OctagonIsSOSFeatureEnabled(void)
209 if(OctagonSOSFeatureIsEnabledOverrideSet) {
210 secnotice("octagon", "SOS Feature is %@ (overridden)", OctagonSOSFeatureIsEnabledOverride ? @"enabled" : @"disabled");
211 return OctagonSOSFeatureIsEnabledOverride;
214 static bool sosEnabled = true;
215 static dispatch_once_t onceToken;
216 dispatch_once(&onceToken, ^{
217 sosEnabled = os_feature_enabled(Security, EnableSecureObjectSync);
218 secnotice("octagon", "SOS Feature is %@ (via feature flags)", sosEnabled ? @"enabled" : @"disabled");
224 void OctagonSetSOSFeatureEnabled(BOOL value)
226 OctagonSOSFeatureIsEnabledOverrideSet = true;
227 OctagonSOSFeatureIsEnabledOverride = value;
230 //feature flag for enabling/disabling performance enhancements
231 BOOL OctagonIsOptimizationEnabled(void)
233 if(OctagonOptimizationIsEnabledOverrideSet) {
234 secnotice("octagon", "Octagon Optimization is %@ (overridden)", OctagonOptimizationIsEnabledOverride ? @"enabled" : @"disabled");
235 return OctagonOptimizationIsEnabledOverride;
238 static bool optimizationEnabled = true;
239 static dispatch_once_t onceToken;
240 dispatch_once(&onceToken, ^{
241 optimizationEnabled = os_feature_enabled(Security, OctagonOptimization);
242 secnotice("octagon", "Octagon Optimization is %@ (via feature flags)", optimizationEnabled ? @"enabled" : @"disabled");
245 return optimizationEnabled;
248 void OctagonSetOptimizationEnabled(BOOL value)
250 OctagonOptimizationIsEnabledOverrideSet = true;
251 OctagonOptimizationIsEnabledOverride = value;
255 //feature flag for checking if escrow record fetching is enabled
256 BOOL OctagonIsEscrowRecordFetchEnabled(void)
258 if(OctagonEscrowRecordFetchIsEnabledOverrideSet) {
259 secnotice("octagon", "Octagon Escrow Record Fetching is %@ (overridden)", OctagonEscrowRecordFetchIsEnabledOverride ? @"enabled" : @"disabled");
260 return OctagonEscrowRecordFetchIsEnabledOverride;
263 static bool escrowRecordFetchingEnabled = true;
264 static dispatch_once_t onceToken;
265 dispatch_once(&onceToken, ^{
266 escrowRecordFetchingEnabled = os_feature_enabled(Security, OctagonEscrowRecordFetch);
267 secnotice("octagon", "Octagon Escrow Record Fetching is %@ (via feature flags)", escrowRecordFetchingEnabled ? @"enabled" : @"disabled");
270 return escrowRecordFetchingEnabled;
273 void OctagonSetEscrowRecordFetchEnabled(BOOL value)
275 OctagonEscrowRecordFetchIsEnabledOverrideSet = true;
276 OctagonEscrowRecordFetchIsEnabledOverride = value;
279 //feature flag for checking kvs on cloudkit enablement
280 BOOL SecKVSOnCloudKitIsEnabled(void)
282 if(SecKVSOnCloudKitIsEnabledOverrideSet) {
283 secnotice("octagon", "KVS on CloudKit is %@ (overridden)", SecKVSOnCloudKitIsEnabledOverride ? @"enabled" : @"disabled");
284 return SecKVSOnCloudKitIsEnabledOverride;
287 static bool kvsOnCloudKitEnabled = true;
288 static dispatch_once_t onceToken;
289 dispatch_once(&onceToken, ^{
290 kvsOnCloudKitEnabled = os_feature_enabled(KVS, KVSOnCloudKitForAll);
291 secnotice("octagon", "KVS on CloudKit is %@ (via feature flags)", kvsOnCloudKitEnabled ? @"enabled" : @"disabled");
294 return kvsOnCloudKitEnabled;
297 void SecKVSOnCloudKitSetOverrideIsEnabled(BOOL value)
299 SecKVSOnCloudKitIsEnabledOverrideSet = true;
300 SecKVSOnCloudKitIsEnabledOverride = value;
303 //feature flag for checking whether or not we should cap the number of nested errors
304 bool SecErrorIsNestedErrorCappingEnabled(void)
306 if(SecErrorNestedErrorCappingIsEnabledOverrideSet) {
307 secnotice("octagon", "SecError Nested Error Capping is %@ (overridden)", SecErrorNestedErrorCappingIsEnabledOverride ? @"enabled" : @"disabled");
308 return SecErrorNestedErrorCappingIsEnabledOverride;
311 static bool errorCappingEnabled = true;
312 static dispatch_once_t onceToken;
313 dispatch_once(&onceToken, ^{
314 errorCappingEnabled = os_feature_enabled(Security, SecErrorNestedErrorCapping);
315 secnotice("octagon", "SecError Nested Error Capping is %@ (via feature flags)", errorCappingEnabled ? @"enabled" : @"disabled");
318 return errorCappingEnabled;
321 void SecErrorSetOverrideNestedErrorCappingIsEnabled(BOOL value)
323 SecErrorNestedErrorCappingIsEnabledOverrideSet = true;
324 SecErrorNestedErrorCappingIsEnabledOverride = value;