]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSKeychainView.h
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / ckks / CKKSKeychainView.h
1 /*
2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #if OCTAGON
25 #import <Foundation/Foundation.h>
26 #include <dispatch/dispatch.h>
27
28 #import "keychain/analytics/CKKSLaunchSequence.h"
29 #import "keychain/ckks/OctagonAPSReceiver.h"
30 #import "keychain/ckks/CKKSLockStateTracker.h"
31 #import "keychain/ckks/CKKSReachabilityTracker.h"
32 #import "keychain/ckks/CloudKitDependencies.h"
33
34 #import "keychain/ot/OctagonFlags.h"
35 #import "keychain/ot/OctagonStateMachine.h"
36
37 #include "keychain/securityd/SecDbItem.h"
38 #include <utilities/SecDb.h>
39
40 #import "keychain/ckks/CKKS.h"
41 #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h"
42 #import "keychain/ckks/CKKSGroupOperation.h"
43 #import "keychain/ckks/CKKSIncomingQueueOperation.h"
44 #import "keychain/ckks/CKKSNearFutureScheduler.h"
45 #import "keychain/ckks/CKKSNewTLKOperation.h"
46 #import "keychain/ckks/CKKSNotifier.h"
47 #import "keychain/ckks/CKKSOutgoingQueueOperation.h"
48 #import "keychain/ckks/CKKSPeer.h"
49 #import "keychain/ckks/CKKSPeerProvider.h"
50 #import "keychain/ckks/CKKSProcessReceivedKeysOperation.h"
51 #import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h"
52 #import "keychain/ckks/CKKSScanLocalItemsOperation.h"
53 #import "keychain/ckks/CKKSTLKShareRecord.h"
54 #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h"
55 #import "keychain/ckks/CKKSZoneModifier.h"
56 #import "keychain/ckks/CKKSZoneChangeFetcher.h"
57 #import "keychain/ckks/CKKSSynchronizeOperation.h"
58 #import "keychain/ckks/CKKSLocalSynchronizeOperation.h"
59 #import "keychain/ckks/CKKSProvideKeySetOperation.h"
60 #import "keychain/ckks/CKKSOperationDependencies.h"
61 #import "keychain/trust/TrustedPeers/TPSyncingPolicy.h"
62
63 #include "CKKS.h"
64
65 NS_ASSUME_NONNULL_BEGIN
66
67 @class CKKSKey;
68 @class CKKSAESSIVKey;
69 @class CKKSSynchronizeOperation;
70 @class CKKSRateLimiter;
71 @class CKKSOutgoingQueueEntry;
72 @class CKKSZoneChangeFetcher;
73 @class CKKSCurrentKeySet;
74
75 @interface CKKSKeychainView : NSObject <CKKSCloudKitAccountStateListener,
76 CKKSChangeFetcherClient,
77 CKKSPeerUpdateListener,
78 CKKSDatabaseProviderProtocol,
79 OctagonStateMachineEngine>
80
81 @property (readonly) NSString* zoneName;
82 @property CKKSAccountStatus accountStatus;
83 @property (readonly) CKContainer* container;
84 @property (readonly) CKDatabase* database;
85 @property (weak) CKKSAccountStateTracker* accountTracker;
86 @property (weak) CKKSReachabilityTracker* reachabilityTracker;
87 @property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies;
88 @property (readonly) dispatch_queue_t queue;
89
90 @property (readonly) CKRecordZoneID* zoneID;
91
92 @property CKKSCondition* loggedIn;
93 @property CKKSCondition* loggedOut;
94 @property CKKSCondition* accountStateKnown;
95
96 @property CKKSAccountStatus trustStatus;
97
98 @property (nullable) CKKSLaunchSequence *launch;
99
100 @property CKKSLockStateTracker* lockStateTracker;
101
102 // Is this view currently syncing keychain modifications?
103 @property (readonly) BOOL itemSyncingEnabled;
104
105 @property (readonly) OctagonStateMachine* stateMachine;
106
107 // If the key hierarchy isn't coming together, it might be because we're out of sync with cloudkit.
108 // Use this to track if we've completed a full refetch, so fix-up operations can be done.
109 @property bool keyStateMachineRefetched;
110
111 // Set this to request a key state refetch (tests only)
112 @property bool keyStateFullRefetchRequested;
113
114 @property (nullable) CKKSResultOperation* keyStateReadyDependency;
115
116 // Full of condition variables, if you'd like to try to wait until the key hierarchy is in some state
117 @property (readonly) NSDictionary<CKKSZoneKeyState*, CKKSCondition*>* keyHierarchyConditions;
118
119 @property CKKSZoneChangeFetcher* zoneChangeFetcher;
120
121 @property (nullable) CKKSNearFutureScheduler* suggestTLKUpload;
122 @property (nullable) CKKSNearFutureScheduler* requestPolicyCheck;
123
124 /* Used for debugging: just what happened last time we ran this? */
125 @property CKKSIncomingQueueOperation* lastIncomingQueueOperation;
126 @property CKKSNewTLKOperation* lastNewTLKOperation;
127 @property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation;
128 @property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation;
129 @property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation;
130 @property CKKSSynchronizeOperation* lastSynchronizeOperation;
131 @property CKKSResultOperation* lastFixupOperation;
132
133 /* Used for testing: pause operation types by adding operations here */
134 @property NSOperation* holdReencryptOutgoingItemsOperation;
135 @property NSOperation* holdOutgoingQueueOperation;
136 @property NSOperation* holdIncomingQueueOperation;
137 @property NSOperation* holdLocalSynchronizeOperation;
138 @property CKKSResultOperation* holdFixupOperation;
139
140 /* Used for testing */
141 @property BOOL initiatedLocalScan;
142
143 /* Trigger this to tell the whole machine that this view has changed */
144 @property CKKSNearFutureScheduler* notifyViewChangedScheduler;
145
146 /* Trigger this to tell the whole machine that this view is more ready then before */
147 @property CKKSNearFutureScheduler* notifyViewReadyScheduler;
148
149 @property (readonly) CKKSOperationDependencies* operationDependencies;
150
151 - (instancetype)initWithContainer:(CKContainer*)container
152 zoneName:(NSString*)zoneName
153 accountTracker:(CKKSAccountStateTracker*)accountTracker
154 lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
155 reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker
156 changeFetcher:(CKKSZoneChangeFetcher*)fetcher
157 zoneModifier:(CKKSZoneModifier*)zoneModifier
158 savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier
159 cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies;
160
161 /* Trust state management */
162
163 // suggestTLKUpload and requestPolicyCheck are essentially callbacks to request certain procedures from the view owner.
164 // When suggestTLKUpload is triggered, the CKKS view believes it has some new TLKs that need uploading, and Octagon should take care of them.
165 // When requestPolicyCheck is triggered, the CKKS view would like Octagon to perform a live check on which syncing policy is in effect,
166 // successfully retrieving all peer's opinions, and would like -setCurrentSyncingPolicy to be called with the updated policy (even if it is
167 // unchanged.)
168 - (void)beginTrustedOperation:(NSArray<id<CKKSPeerProvider>>*)peerProviders
169 suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload
170 requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck;
171
172 - (void)endTrustedOperation;
173
174 /* CloudKit account management */
175
176 - (void)beginCloudKitOperation;
177
178 // If this policy indicates that this view should not sync, this view will no longer sync keychain items,
179 // but it will continue to particpate in TLK sharing.
180 // If policyIsFresh is set, any items discovered that do not match this policy will be moved.
181 - (void)setCurrentSyncingPolicy:(TPSyncingPolicy*)syncingPolicy policyIsFresh:(BOOL)policyIsFresh;
182
183 - (void)receivedItemForWrongView;
184
185 /* Synchronous operations */
186
187 - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn
188 source:(SecDbTransactionSource)txionSource
189 added:(SecDbItemRef _Nullable)added
190 deleted:(SecDbItemRef _Nullable)deleted
191 rateLimiter:(CKKSRateLimiter*)rateLimiter;
192
193 - (void)setCurrentItemForAccessGroup:(NSData*)newItemPersistentRef
194 hash:(NSData*)newItemSHA1
195 accessGroup:(NSString*)accessGroup
196 identifier:(NSString*)identifier
197 replacing:(NSData* _Nullable)oldCurrentItemPersistentRef
198 hash:(NSData* _Nullable)oldItemSHA1
199 complete:(void (^)(NSError* operror))complete;
200
201 - (void)getCurrentItemForAccessGroup:(NSString*)accessGroup
202 identifier:(NSString*)identifier
203 fetchCloudValue:(bool)fetchCloudValue
204 complete:(void (^)(NSString* uuid, NSError* operror))complete;
205
206 - (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error;
207
208 - (CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*)findKeySet:(BOOL)refetchBeforeReturningKeySet;
209 - (void)receiveTLKUploadRecords:(NSArray<CKRecord*>*)records;
210
211 // Returns true if this zone would like a new TLK to be uploaded
212 - (BOOL)requiresTLKUpload;
213
214 - (void)waitForKeyHierarchyReadiness;
215 - (void)cancelAllOperations;
216
217 /* Asynchronous kickoffs */
218
219 - (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup;
220 - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after
221 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
222 - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after
223 requiredDelay:(uint64_t)requiredDelay
224 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
225
226 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA;
227 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA after:(CKKSResultOperation* _Nullable)after;
228
229 - (CKKSScanLocalItemsOperation*)scanLocalItems:(NSString*)name;
230
231 // Schedules a process queueoperation to happen after the next device unlock. This may be Immediately, if the device is unlocked.
232 - (void)processIncomingQueueAfterNextUnlock;
233
234 // This operation will complete directly after the next ProcessIncomingQueue, and should supply that IQO's result. Used mainly for testing; otherwise you'd just kick off a IQO directly.
235 - (CKKSResultOperation*)resultsOfNextProcessIncomingQueueOperation;
236
237 // Schedules an operation to update this device's state record in CloudKit
238 // If rateLimit is true, the operation will abort if it's updated the record in the past 3 days
239 - (CKKSUpdateDeviceStateOperation*)updateDeviceState:(bool)rateLimit
240 waitForKeyHierarchyInitialization:(uint64_t)timeout
241 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
242
243 - (CKKSSynchronizeOperation*)resyncWithCloud;
244 - (CKKSLocalSynchronizeOperation*)resyncLocal;
245
246 - (CKKSResultOperation*)resetLocalData;
247 - (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup;
248
249 // Call this to tell the key state machine that you think some new data has arrived that it is interested in
250 - (void)keyStateMachineRequestProcess;
251
252 // For our serial queue to work with how handleKeychainEventDbConnection is called from the main thread,
253 // every block on our queue must have a SecDBConnectionRef available to it before it begins on the queue.
254 // Use these helper methods to make sure those exist.
255 - (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block;
256 - (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block;
257
258 /* Synchronous operations which must be called from inside a dispatchAsyncWithAccountKeys or dispatchSync block */
259
260 // Since we might have people interested in the state transitions of objects, please do those transitions via these methods
261 - (bool)_onqueueChangeOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
262 toState:(NSString*)state
263 error:(NSError* __autoreleasing*)error;
264 - (bool)_onqueueErrorOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
265 itemError:(NSError*)itemError
266 error:(NSError* __autoreleasing*)error;
267
268 // Call this if you've done a write and received an error. It'll pull out any new records returned as CKErrorServerRecordChanged and pretend we received them in a fetch
269 //
270 // Note that you need to tell this function the records you wanted to save, so it can determine which record failed from its CKRecordID.
271 // I don't know why CKRecordIDs don't have record types, either.
272 - (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary<CKRecordID*, CKRecord*>*)savedRecords;
273
274 - (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync;
275 - (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync;
276
277 - (CKKSDeviceStateEntry* _Nullable)_onqueueCurrentDeviceStateEntry:(NSError* __autoreleasing*)error;
278
279 // Please don't use these unless you're an Operation in this package
280 @property NSHashTable<CKKSIncomingQueueOperation*>* incomingQueueOperations;
281 @property NSHashTable<CKKSOutgoingQueueOperation*>* outgoingQueueOperations;
282
283 @property NSHashTable<CKKSScanLocalItemsOperation*>* scanLocalItemsOperations;
284
285 // Returns the current state of this view, fastStatus is the same, but as name promise, no expensive calculations
286 - (NSDictionary<NSString*, NSString*>*)status;
287 - (NSDictionary<NSString*, NSString*>*)fastStatus;
288
289 - (void)xpc24HrNotification;
290
291 // NSOperation Helpers
292 - (void)scheduleOperation:(NSOperation*)op;
293 @end
294
295 @interface CKKSKeychainView (Testing)
296
297 // Call this to just nudge the state machine (without a request)
298 // This is used internally, but you should only call it if you're a test.
299 - (void)_onqueuePokeKeyStateMachine;
300
301 /* NSOperation helpers */
302 - (void)cancelAllOperations;
303 - (void)waitUntilAllOperationsAreFinished;
304 - (void)waitForOperationsOfClass:(Class)operationClass;
305
306 - (void)waitForFetchAndIncomingQueueProcessing;
307
308 - (void)halt;
309
310 - (void)handleCKLogout;
311
312 @end
313
314 NS_ASSUME_NONNULL_END
315 #else // !OCTAGON
316 #import <Foundation/Foundation.h>
317 @interface CKKSKeychainView : NSObject
318 {
319 NSString* _containerName;
320 }
321 @end
322 #endif // OCTAGON