]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSKeychainView.h
Security-59306.11.20.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 #include <securityd/SecDbItem.h>
35 #include <utilities/SecDb.h>
36
37 #import "keychain/ckks/CKKS.h"
38 #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h"
39 #import "keychain/ckks/CKKSGroupOperation.h"
40 #import "keychain/ckks/CKKSIncomingQueueOperation.h"
41 #import "keychain/ckks/CKKSNearFutureScheduler.h"
42 #import "keychain/ckks/CKKSNewTLKOperation.h"
43 #import "keychain/ckks/CKKSNotifier.h"
44 #import "keychain/ckks/CKKSOutgoingQueueOperation.h"
45 #import "keychain/ckks/CKKSPeer.h"
46 #import "keychain/ckks/CKKSProcessReceivedKeysOperation.h"
47 #import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h"
48 #import "keychain/ckks/CKKSScanLocalItemsOperation.h"
49 #import "keychain/ckks/CKKSTLKShareRecord.h"
50 #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h"
51 #import "keychain/ckks/CKKSZone.h"
52 #import "keychain/ckks/CKKSZoneModifier.h"
53 #import "keychain/ckks/CKKSZoneChangeFetcher.h"
54 #import "keychain/ckks/CKKSSynchronizeOperation.h"
55 #import "keychain/ckks/CKKSLocalSynchronizeOperation.h"
56 #import "keychain/ckks/CKKSProvideKeySetOperation.h"
57
58 #include "CKKS.h"
59
60 NS_ASSUME_NONNULL_BEGIN
61
62 @class CKKSKey;
63 @class CKKSAESSIVKey;
64 @class CKKSSynchronizeOperation;
65 @class CKKSRateLimiter;
66 @class CKKSManifest;
67 @class CKKSEgoManifest;
68 @class CKKSOutgoingQueueEntry;
69 @class CKKSZoneChangeFetcher;
70 @class CKKSCurrentKeySet;
71
72 @interface CKKSPeerProviderState : NSObject
73 @property NSString* peerProviderID;
74
75 // The peer provider believes trust in this state is essential. Any subsystem using
76 // a peer provider state should fail and pause if this is YES and there are trust errors.
77 @property BOOL essential;
78
79 @property (nonatomic, readonly, nullable) CKKSSelves* currentSelfPeers;
80 @property (nonatomic, readonly, nullable) NSError* currentSelfPeersError;
81 @property (nonatomic, readonly, nullable) NSSet<id<CKKSRemotePeerProtocol>>* currentTrustedPeers;
82 @property (nonatomic, readonly, nullable) NSSet<NSString*>* currentTrustedPeerIDs;
83 @property (nonatomic, readonly, nullable) NSError* currentTrustedPeersError;
84
85 - (instancetype)initWithPeerProviderID:(NSString*)providerID
86 essential:(BOOL)essential
87 selfPeers:(CKKSSelves* _Nullable)selfPeers
88 selfPeersError:(NSError* _Nullable)selfPeersError
89 trustedPeers:(NSSet<id<CKKSPeer>>* _Nullable)currentTrustedPeers
90 trustedPeersError:(NSError* _Nullable)trustedPeersError;
91
92 + (CKKSPeerProviderState*)noPeersState:(id<CKKSPeerProvider>)provider;
93 @end
94
95 @interface CKKSKeychainView : CKKSZone <CKKSZoneUpdateReceiver,
96 CKKSChangeFetcherClient,
97 CKKSPeerUpdateListener>
98 {
99 CKKSZoneKeyState* _keyHierarchyState;
100 }
101
102 @property CKKSCondition* loggedIn;
103 @property CKKSCondition* loggedOut;
104 @property CKKSCondition* accountStateKnown;
105
106 @property CKKSAccountStatus trustStatus;
107 @property (nullable) CKKSResultOperation* trustDependency;
108
109 @property (nullable) CKKSLaunchSequence *launch;
110
111 @property CKKSLockStateTracker* lockStateTracker;
112
113 @property CKKSZoneKeyState* keyHierarchyState;
114 @property (nullable) NSError* keyHierarchyError;
115 @property (nullable) CKOperationGroup* keyHierarchyOperationGroup;
116 @property (nullable) NSOperation* keyStateMachineOperation;
117
118 // If the key hierarchy isn't coming together, it might be because we're out of sync with cloudkit.
119 // Use this to track if we've completed a full refetch, so fix-up operations can be done.
120 @property bool keyStateMachineRefetched;
121 @property (nullable) CKKSEgoManifest* egoManifest;
122 @property (nullable) CKKSManifest* latestManifest;
123 @property (nullable) CKKSResultOperation* keyStateReadyDependency;
124
125 // Wait for the key state to become 'nontransient': no pending operation is expected to advance it (at least until intervention)
126 @property (nullable) CKKSResultOperation* keyStateNonTransientDependency;
127
128 // True if we believe there's any items in the keychain which haven't been brought up in CKKS yet
129 @property bool droppedItems;
130
131 @property (readonly) NSString* lastActiveTLKUUID;
132
133 // Full of condition variables, if you'd like to try to wait until the key hierarchy is in some state
134 @property NSMutableDictionary<CKKSZoneKeyState*, CKKSCondition*>* keyHierarchyConditions;
135
136 @property CKKSZoneChangeFetcher* zoneChangeFetcher;
137
138 @property (weak) CKKSNearFutureScheduler* savedTLKNotifier;
139
140 @property (nullable) CKKSNearFutureScheduler* suggestTLKUpload;
141
142
143 /* Used for debugging: just what happened last time we ran this? */
144 @property CKKSIncomingQueueOperation* lastIncomingQueueOperation;
145 @property CKKSNewTLKOperation* lastNewTLKOperation;
146 @property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation;
147 @property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation;
148 @property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation;
149 @property CKKSScanLocalItemsOperation* lastScanLocalItemsOperation;
150 @property CKKSSynchronizeOperation* lastSynchronizeOperation;
151 @property CKKSResultOperation* lastFixupOperation;
152
153 /* Used for testing: pause operation types by adding operations here */
154 @property NSOperation* holdReencryptOutgoingItemsOperation;
155 @property NSOperation* holdOutgoingQueueOperation;
156 @property NSOperation* holdIncomingQueueOperation;
157 @property NSOperation* holdLocalSynchronizeOperation;
158 @property CKKSResultOperation* holdFixupOperation;
159
160 /* Trigger this to tell the whole machine that this view has changed */
161 @property CKKSNearFutureScheduler* notifyViewChangedScheduler;
162
163 /* Trigger this to tell the whole machine that this view is more ready then before */
164 @property CKKSNearFutureScheduler* notifyViewReadyScheduler;
165
166 /* trigger this to request key state machine poking */
167 @property CKKSNearFutureScheduler* pokeKeyStateMachineScheduler;
168
169 // The current list of peer providers. If empty, CKKS will consider itself untrusted, and halt operation
170 @property (readonly) NSArray<id<CKKSPeerProvider>>* currentPeerProviders;
171
172 // These are available when you're in a dispatchSyncWithAccountKeys call, but at no other time
173 // These must be pre-fetched before you get on the CKKS queue, otherwise we end up with CKKS<->SQLite<->SOSAccountQueue deadlocks
174
175 // They will be in a parallel array with currentPeerProviders above
176 @property (readonly) NSArray<CKKSPeerProviderState*>* currentTrustStates;
177
178 - (instancetype)initWithContainer:(CKContainer*)container
179 zoneName:(NSString*)zoneName
180 accountTracker:(CKKSAccountStateTracker*)accountTracker
181 lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
182 reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker
183 changeFetcher:(CKKSZoneChangeFetcher*)fetcher
184 zoneModifier:(CKKSZoneModifier*)zoneModifier
185 savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier
186 cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies;
187
188 /* Trust state management */
189 - (void)beginTrustedOperation:(NSArray<id<CKKSPeerProvider>>*)peerProviders
190 suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload;
191 - (void)endTrustedOperation;
192
193 /* Synchronous operations */
194
195 - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn
196 added:(SecDbItemRef _Nullable)added
197 deleted:(SecDbItemRef _Nullable)deleted
198 rateLimiter:(CKKSRateLimiter*)rateLimiter
199 syncCallback:(SecBoolNSErrorCallback)syncCallback;
200
201 - (void)setCurrentItemForAccessGroup:(NSData*)newItemPersistentRef
202 hash:(NSData*)newItemSHA1
203 accessGroup:(NSString*)accessGroup
204 identifier:(NSString*)identifier
205 replacing:(NSData* _Nullable)oldCurrentItemPersistentRef
206 hash:(NSData* _Nullable)oldItemSHA1
207 complete:(void (^)(NSError* operror))complete;
208
209 - (void)getCurrentItemForAccessGroup:(NSString*)accessGroup
210 identifier:(NSString*)identifier
211 fetchCloudValue:(bool)fetchCloudValue
212 complete:(void (^)(NSString* uuid, NSError* operror))complete;
213
214 - (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error;
215
216 - (CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*)findKeySet;
217 - (void)receiveTLKUploadRecords:(NSArray<CKRecord*>*)records;
218
219 - (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing;
220 - (void)waitForKeyHierarchyReadiness;
221 - (void)cancelAllOperations;
222
223 - (CKKSKey* _Nullable)keyForItem:(SecDbItemRef)item error:(NSError* __autoreleasing*)error;
224
225 - (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing*)error;
226
227 - (BOOL)otherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset;
228
229 - (NSSet<NSString*>*)_onqueuePriorityOutgoingQueueUUIDs;
230
231 /* Asynchronous kickoffs */
232
233 - (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup;
234 - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after
235 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
236 - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after
237 requiredDelay:(uint64_t)requiredDelay
238 ckoperationGroup:(CKOperationGroup*)ckoperationGroup;
239
240 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA;
241 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA after:(CKKSResultOperation* _Nullable)after;
242
243 - (CKKSScanLocalItemsOperation*)scanLocalItems:(NSString*)name;
244
245 // Schedules a process queueoperation to happen after the next device unlock. This may be Immediately, if the device is unlocked.
246 - (void)processIncomingQueueAfterNextUnlock;
247
248 // 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.
249 - (CKKSResultOperation*)resultsOfNextProcessIncomingQueueOperation;
250
251 // Schedules an operation to update this device's state record in CloudKit
252 // If rateLimit is true, the operation will abort if it's updated the record in the past 3 days
253 - (CKKSUpdateDeviceStateOperation*)updateDeviceState:(bool)rateLimit
254 waitForKeyHierarchyInitialization:(uint64_t)timeout
255 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
256
257 - (CKKSSynchronizeOperation*)resyncWithCloud;
258 - (CKKSLocalSynchronizeOperation*)resyncLocal;
259
260 - (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because;
261
262 - (CKKSResultOperation*)resetLocalData;
263 - (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup;
264
265 // Call this to tell the key state machine that you think some new data has arrived that it is interested in
266 - (void)keyStateMachineRequestProcess;
267
268 // For our serial queue to work with how handleKeychainEventDbConnection is called from the main thread,
269 // every block on our queue must have a SecDBConnectionRef available to it before it begins on the queue.
270 // Use these helper methods to make sure those exist.
271 - (void)dispatchSync:(bool (^)(void))block;
272 - (void)dispatchSyncWithAccountKeys:(bool (^)(void))block;
273
274 /* Synchronous operations which must be called from inside a dispatchAsyncWithAccountKeys or dispatchSync block */
275
276 // Call this to request the key hierarchy state machine to fetch new updates
277 - (void)_onqueueKeyStateMachineRequestFetch;
278
279 // Call this to request the key hierarchy state machine to reprocess
280 - (void)_onqueueKeyStateMachineRequestProcess;
281
282 // Call this from a key hierarchy operation to move the state machine, and record the results of the last move.
283 - (void)_onqueueAdvanceKeyStateMachineToState:(CKKSZoneKeyState* _Nullable)state withError:(NSError* _Nullable)error;
284
285 // Since we might have people interested in the state transitions of objects, please do those transitions via these methods
286 - (bool)_onqueueChangeOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
287 toState:(NSString*)state
288 error:(NSError* __autoreleasing*)error;
289 - (bool)_onqueueErrorOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
290 itemError:(NSError*)itemError
291 error:(NSError* __autoreleasing*)error;
292
293 // 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
294 //
295 // Note that you need to tell this function the records you wanted to save, so it can determine which record failed from its CKRecordID.
296 // I don't know why CKRecordIDs don't have record types, either.
297 - (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary<CKRecordID*, CKRecord*>*)savedRecords;
298
299 - (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync;
300 - (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync;
301
302 // For this key, who doesn't yet have a CKKSTLKShare for it, shared to their current Octagon keys?
303 // Note that we really want a record sharing the TLK to ourselves, so this function might return
304 // a non-empty set even if all peers have the TLK: it wants us to make a record for ourself.
305 // If you pass in a non-empty set in afterUploading, those records will be included in the calculation.
306 - (NSSet<id<CKKSPeer>>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState
307 missingShare:(CKKSKey*)key
308 afterUploading:(NSSet<CKKSTLKShareRecord*>* _Nullable)newShares
309 error:(NSError* __autoreleasing*)error;
310
311 - (BOOL)_onqueueAreNewSharesSufficient:(NSSet<CKKSTLKShareRecord*>*)newShares
312 currentTLK:(CKKSKey*)key
313 error:(NSError* __autoreleasing*)error;
314
315 // For this key, share it to all trusted peers who don't have it yet
316 - (NSSet<CKKSTLKShareRecord*>* _Nullable)_onqueueCreateMissingKeyShares:(CKKSKey*)key error:(NSError* __autoreleasing*)error;
317
318 - (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error;
319
320 - (CKKSDeviceStateEntry* _Nullable)_onqueueCurrentDeviceStateEntry:(NSError* __autoreleasing*)error;
321
322 // Please don't use these unless you're an Operation in this package
323 @property NSHashTable<CKKSIncomingQueueOperation*>* incomingQueueOperations;
324 @property NSHashTable<CKKSOutgoingQueueOperation*>* outgoingQueueOperations;
325 @property CKKSScanLocalItemsOperation* initialScanOperation;
326
327 // Returns the current state of this view, fastStatus is the same, but as name promise, no expensive calculations
328 - (NSDictionary<NSString*, NSString*>*)status;
329 - (NSDictionary<NSString*, NSString*>*)fastStatus;
330 @end
331
332 NS_ASSUME_NONNULL_END
333 #else // !OCTAGON
334 #import <Foundation/Foundation.h>
335 @interface CKKSKeychainView : NSObject
336 {
337 NSString* _containerName;
338 }
339 @end
340 #endif // OCTAGON