]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSKeychainView.h
Security-58286.41.2.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/ckks/CKKSAPSReceiver.h"
29 #import "keychain/ckks/CKKSLockStateTracker.h"
30 #import "keychain/ckks/CloudKitDependencies.h"
31
32 #include <securityd/SecDbItem.h>
33 #include <utilities/SecDb.h>
34
35 #import "keychain/ckks/CKKS.h"
36 #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h"
37 #import "keychain/ckks/CKKSGroupOperation.h"
38 #import "keychain/ckks/CKKSIncomingQueueOperation.h"
39 #import "keychain/ckks/CKKSNearFutureScheduler.h"
40 #import "keychain/ckks/CKKSNewTLKOperation.h"
41 #import "keychain/ckks/CKKSNotifier.h"
42 #import "keychain/ckks/CKKSOutgoingQueueOperation.h"
43 #import "keychain/ckks/CKKSPeer.h"
44 #import "keychain/ckks/CKKSProcessReceivedKeysOperation.h"
45 #import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h"
46 #import "keychain/ckks/CKKSScanLocalItemsOperation.h"
47 #import "keychain/ckks/CKKSTLKShare.h"
48 #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h"
49 #import "keychain/ckks/CKKSZone.h"
50 #import "keychain/ckks/CKKSZoneChangeFetcher.h"
51 #import "keychain/ckks/CKKSSynchronizeOperation.h"
52 #import "keychain/ckks/CKKSLocalSynchronizeOperation.h"
53
54 #include "CKKS.h"
55
56 NS_ASSUME_NONNULL_BEGIN
57
58 @class CKKSKey;
59 @class CKKSAESSIVKey;
60 @class CKKSSynchronizeOperation;
61 @class CKKSRateLimiter;
62 @class CKKSManifest;
63 @class CKKSEgoManifest;
64 @class CKKSOutgoingQueueEntry;
65 @class CKKSZoneChangeFetcher;
66
67 @interface CKKSKeychainView : CKKSZone <CKKSZoneUpdateReceiver, CKKSChangeFetcherErrorOracle, CKKSPeerUpdateListener>
68 {
69 CKKSZoneKeyState* _keyHierarchyState;
70 }
71
72 @property CKKSCondition* loggedIn;
73 @property CKKSCondition* loggedOut;
74
75 @property CKKSLockStateTracker* lockStateTracker;
76
77 @property CKKSZoneKeyState* keyHierarchyState;
78 @property (nullable) NSError* keyHierarchyError;
79 @property (nullable) CKOperationGroup* keyHierarchyOperationGroup;
80 @property (nullable) NSOperation* keyStateMachineOperation;
81
82 // If the key hierarchy isn't coming together, it might be because we're out of sync with cloudkit.
83 // Use this to track if we've completed a full refetch, so fix-up operations can be done.
84 @property bool keyStateMachineRefetched;
85 @property (nullable) CKKSEgoManifest* egoManifest;
86 @property (nullable) CKKSManifest* latestManifest;
87 @property (nullable) CKKSResultOperation* keyStateReadyDependency;
88
89 // True if we believe there's any items in the keychain which haven't been brought up in CKKS yet
90 @property bool droppedItems;
91
92 @property (readonly) NSString* lastActiveTLKUUID;
93
94 // Full of condition variables, if you'd like to try to wait until the key hierarchy is in some state
95 @property NSMutableDictionary<CKKSZoneKeyState*, CKKSCondition*>* keyHierarchyConditions;
96
97 @property CKKSZoneChangeFetcher* zoneChangeFetcher;
98
99 @property (weak) CKKSNearFutureScheduler* savedTLKNotifier;
100
101 // Differs from the zonesetupoperation: zoneSetup is only for CK modifications, viewSetup handles local db changes too
102 @property CKKSResultOperation* viewSetupOperation;
103
104 /* Used for debugging: just what happened last time we ran this? */
105 @property CKKSIncomingQueueOperation* lastIncomingQueueOperation;
106 @property CKKSNewTLKOperation* lastNewTLKOperation;
107 @property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation;
108 @property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation;
109 @property CKKSFetchAllRecordZoneChangesOperation* lastRecordZoneChangesOperation;
110 @property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation;
111 @property CKKSScanLocalItemsOperation* lastScanLocalItemsOperation;
112 @property CKKSSynchronizeOperation* lastSynchronizeOperation;
113 @property CKKSResultOperation* lastFixupOperation;
114
115 /* Used for testing: pause operation types by adding operations here */
116 @property NSOperation* holdReencryptOutgoingItemsOperation;
117 @property NSOperation* holdOutgoingQueueOperation;
118 @property NSOperation* holdLocalSynchronizeOperation;
119 @property CKKSResultOperation* holdFixupOperation;
120
121 /* Trigger this to tell the whole machine that this view has changed */
122 @property CKKSNearFutureScheduler* notifyViewChangedScheduler;
123
124 // These are available when you're in a dispatchSyncWithAccountKeys call, but at no other time
125 // These must be pre-fetched before you get on the CKKS queue, otherwise we end up with CKKS<->SQLite<->SOSAccountQueue deadlocks
126 @property (nonatomic, readonly) CKKSSelves* currentSelfPeers;
127 @property (nonatomic, readonly) NSError* currentSelfPeersError;
128 @property (nonatomic, readonly) NSSet<id<CKKSPeer>>* currentTrustedPeers;
129 @property (nonatomic, readonly) NSError* currentTrustedPeersError;
130
131 - (instancetype)initWithContainer:(CKContainer*)container
132 zoneName:(NSString*)zoneName
133 accountTracker:(CKKSCKAccountStateTracker*)accountTracker
134 lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
135 savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier
136 peerProvider:(id<CKKSPeerProvider>)peerProvider
137 fetchRecordZoneChangesOperationClass:(Class<CKKSFetchRecordZoneChangesOperation>)fetchRecordZoneChangesOperationClass
138 fetchRecordsOperationClass:(Class<CKKSFetchRecordsOperation>)fetchRecordsOperationClass
139 queryOperationClass:(Class<CKKSQueryOperation>)queryOperationClass
140 modifySubscriptionsOperationClass:(Class<CKKSModifySubscriptionsOperation>)modifySubscriptionsOperationClass
141 modifyRecordZonesOperationClass:(Class<CKKSModifyRecordZonesOperation>)modifyRecordZonesOperationClass
142 apsConnectionClass:(Class<CKKSAPSConnection>)apsConnectionClass
143 notifierClass:(Class<CKKSNotifier>)notifierClass;
144
145 /* Synchronous operations */
146
147 - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn
148 added:(SecDbItemRef _Nullable)added
149 deleted:(SecDbItemRef _Nullable)deleted
150 rateLimiter:(CKKSRateLimiter*)rateLimiter
151 syncCallback:(SecBoolNSErrorCallback)syncCallback;
152
153 - (void)setCurrentItemForAccessGroup:(SecDbItemRef)newItem
154 hash:(NSData*)newItemSHA1
155 accessGroup:(NSString*)accessGroup
156 identifier:(NSString*)identifier
157 replacing:(SecDbItemRef _Nullable)oldItem
158 hash:(NSData* _Nullable)oldItemSHA1
159 complete:(void (^)(NSError* operror))complete;
160
161 - (void)getCurrentItemForAccessGroup:(NSString*)accessGroup
162 identifier:(NSString*)identifier
163 fetchCloudValue:(bool)fetchCloudValue
164 complete:(void (^)(NSString* uuid, NSError* operror))complete;
165
166 - (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error;
167
168 - (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing;
169 - (void)waitForKeyHierarchyReadiness;
170 - (void)cancelAllOperations;
171
172 - (CKKSKey* _Nullable)keyForItem:(SecDbItemRef)item error:(NSError* __autoreleasing*)error;
173
174 - (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing*)error;
175
176 /* Asynchronous kickoffs */
177
178 - (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup;
179 - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after
180 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
181
182 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA;
183 - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA after:(CKKSResultOperation* _Nullable)after;
184
185 // Schedules a process queueoperation to happen after the next device unlock. This may be Immediately, if the device is unlocked.
186 - (void)processIncomingQueueAfterNextUnlock;
187
188 // Schedules an operation to update this device's state record in CloudKit
189 // If rateLimit is true, the operation will abort if it's updated the record in the past 3 days
190 - (CKKSUpdateDeviceStateOperation*)updateDeviceState:(bool)rateLimit
191 waitForKeyHierarchyInitialization:(uint64_t)timeout
192 ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup;
193
194 - (CKKSSynchronizeOperation*)resyncWithCloud;
195 - (CKKSLocalSynchronizeOperation*)resyncLocal;
196
197 - (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because;
198
199 - (CKKSResultOperation*)resetLocalData;
200 - (CKKSResultOperation*)resetCloudKitZone;
201
202 // Call this to pick and start the next key hierarchy operation for the zone
203 - (void)advanceKeyStateMachine;
204
205 // Call this to tell the key state machine that you think some new data has arrived that it is interested in
206 - (void)keyStateMachineRequestProcess;
207
208 // For our serial queue to work with how handleKeychainEventDbConnection is called from the main thread,
209 // every block on our queue must have a SecDBConnectionRef available to it before it begins on the queue.
210 // Use these helper methods to make sure those exist.
211 - (void)dispatchAsync:(bool (^)(void))block;
212 - (void)dispatchSync:(bool (^)(void))block;
213 - (void)dispatchSyncWithAccountKeys:(bool (^)(void))block;
214
215 /* Synchronous operations which must be called from inside a dispatchAsync or dispatchSync block */
216
217 // Call this to request the key hierarchy state machine to fetch new updates
218 - (void)_onqueueKeyStateMachineRequestFetch;
219
220 // Call this to request the key hierarchy state machine to refetch everything in Cloudkit
221 - (void)_onqueueKeyStateMachineRequestFullRefetch;
222
223 // Call this to request the key hierarchy state machine to reprocess
224 - (void)_onqueueKeyStateMachineRequestProcess;
225
226 // Call this from a key hierarchy operation to move the state machine, and record the results of the last move.
227 - (void)_onqueueAdvanceKeyStateMachineToState:(CKKSZoneKeyState* _Nullable)state withError:(NSError* _Nullable)error;
228
229 // Since we might have people interested in the state transitions of objects, please do those transitions via these methods
230 - (bool)_onqueueChangeOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
231 toState:(NSString*)state
232 error:(NSError* __autoreleasing*)error;
233 - (bool)_onqueueErrorOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe
234 itemError:(NSError*)itemError
235 error:(NSError* __autoreleasing*)error;
236
237 // 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
238 //
239 // Note that you need to tell this function the records you wanted to save, so it can determine which record failed from its CKRecordID.
240 // I don't know why CKRecordIDs don't have record types, either.
241 - (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary<CKRecordID*, CKRecord*>*)savedRecords;
242
243 - (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync;
244 - (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync;
245
246 // For this key, who doesn't yet have a CKKSTLKShare for it?
247 // Note that we really want a record sharing the TLK to ourselves, so this function might return
248 // a non-empty set even if all peers have the TLK: it wants us to make a record for ourself.
249 - (NSSet<id<CKKSPeer>>* _Nullable)_onqueueFindPeersMissingShare:(CKKSKey*)key error:(NSError* __autoreleasing*)error;
250
251 // For this key, share it to all trusted peers who don't have it yet
252 - (NSSet<CKKSTLKShare*>* _Nullable)_onqueueCreateMissingKeyShares:(CKKSKey*)key error:(NSError* __autoreleasing*)error;
253
254 - (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error;
255
256 - (CKKSDeviceStateEntry* _Nullable)_onqueueCurrentDeviceStateEntry:(NSError* __autoreleasing*)error;
257
258 // Called by the CKKSZoneChangeFetcher
259 - (bool)isFatalCKFetchError:(NSError*)error;
260
261 // Please don't use these unless you're an Operation in this package
262 @property NSHashTable<CKKSIncomingQueueOperation*>* incomingQueueOperations;
263 @property NSHashTable<CKKSOutgoingQueueOperation*>* outgoingQueueOperations;
264 @property CKKSScanLocalItemsOperation* initialScanOperation;
265
266 // Returns the current state of this view
267 - (NSDictionary<NSString*, NSString*>*)status;
268 @end
269
270 NS_ASSUME_NONNULL_END
271 #else // !OCTAGON
272 #import <Foundation/Foundation.h>
273 @interface CKKSKeychainView : NSObject
274 {
275 NSString* _containerName;
276 }
277 @end
278 #endif // OCTAGON