]> git.saurik.com Git - apple/security.git/blob - keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / TrustedPeersHelper / TrustedPeersHelperProtocol.h
1 /*
2 * Copyright (c) 2018 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 #import <Foundation/Foundation.h>
25 #import <TrustedPeers/TrustedPeers.h>
26 #import <objc/runtime.h>
27
28 #import "keychain/ckks/CKKSKeychainBackedKey.h"
29 #import "keychain/ckks/CKKSTLKShare.h"
30
31 #import "keychain/ot/OTConstants.h"
32
33 NS_ASSUME_NONNULL_BEGIN
34
35 // Any client hoping to use the TrustedPeersHelperProtocol should have an entitlement
36 // 'com.apple.private.trustedpeershelper.client' set to boolean YES.
37
38 @interface TrustedPeersHelperPeerState : NSObject <NSSecureCoding>
39 @property (nullable) NSString* peerID;
40 @property BOOL identityIsPreapproved;
41 @property TPPeerStatus peerStatus;
42 @property BOOL memberChanges;
43 @property BOOL unknownMachineIDsPresent;
44 @property (nullable) NSString* osVersion;
45
46 - (instancetype)initWithPeerID:(NSString* _Nullable)peerID
47 isPreapproved:(BOOL)isPreapproved
48 status:(TPPeerStatus)peerStatus
49 memberChanges:(BOOL)memberChanges
50 unknownMachineIDs:(BOOL)unknownMachineIDs
51 osVersion:(NSString * _Nullable)osVersion;
52 @end
53
54 @interface TrustedPeersHelperPeer : NSObject <NSSecureCoding>
55 @property (nullable) NSString* peerID;
56 @property (nullable) NSData* signingSPKI;
57 @property (nullable) NSData* encryptionSPKI;
58 @property (nullable) NSSet<NSString*>* viewList;
59
60 - (instancetype)initWithPeerID:(NSString*)peerID
61 signingSPKI:(NSData*)signingSPKI
62 encryptionSPKI:(NSData*)encryptionSPKI
63 viewList:(NSSet<NSString*>*)viewList;
64 @end
65
66 @interface TrustedPeersHelperEgoPeerStatus : NSObject <NSSecureCoding>
67 @property TPPeerStatus egoStatus;
68 @property NSString* _Nullable egoPeerID;
69 @property (assign) uint64_t numberOfPeersInOctagon;
70
71 // Note: this field does not include untrusted peers
72 @property NSDictionary<NSString*, NSNumber*>* viablePeerCountsByModelID;
73
74 // Note: this field does include untrusted peers
75 @property NSDictionary<NSString*, NSNumber*>* peerCountsByMachineID;
76
77 @property BOOL isExcluded;
78 @property BOOL isLocked;
79
80 - (instancetype)initWithEgoPeerID:(NSString* _Nullable)egoPeerID
81 status:(TPPeerStatus)egoStatus
82 viablePeerCountsByModelID:(NSDictionary<NSString*, NSNumber*>*)viablePeerCountsByModelID
83 peerCountsByMachineID:(NSDictionary<NSString*, NSNumber*>*)peerCountsByMachineID
84 isExcluded:(BOOL)isExcluded
85 isLocked:(BOOL)isLocked;
86
87 @end
88
89 // This protocol describes the interface of the TrustedPeersHelper XPC service.
90 @protocol TrustedPeersHelperProtocol
91
92 // This is used by a unit test which exercises the XPC-service plumbing.
93 - (void)pingWithReply:(void (^)(void))reply;
94
95 - (void)dumpWithContainer:(NSString *)container
96 context:(NSString *)context
97 reply:(void (^)(NSDictionary * _Nullable, NSError * _Nullable))reply;
98
99 - (void)departByDistrustingSelfWithContainer:(NSString *)container
100 context:(NSString *)context
101 reply:(void (^)(NSError * _Nullable))reply;
102
103 - (void)distrustPeerIDsWithContainer:(NSString *)container
104 context:(NSString *)context
105 peerIDs:(NSSet<NSString*>*)peerIDs
106 reply:(void (^)(NSError * _Nullable))reply;
107
108 - (void)trustStatusWithContainer:(NSString *)container
109 context:(NSString *)context
110 reply:(void (^)(TrustedPeersHelperEgoPeerStatus *status,
111 NSError* _Nullable error))reply;
112
113 - (void)resetWithContainer:(NSString *)container
114 context:(NSString *)context
115 resetReason:(CuttlefishResetReason)reason
116 reply:(void (^)(NSError * _Nullable error))reply;
117
118 - (void)localResetWithContainer:(NSString *)container
119 context:(NSString *)context
120 reply:(void (^)(NSError * _Nullable error))reply;
121
122 // The following three machine ID list manipulation functions do not attempt to apply the results to the model
123 // If you'd like that to occur, please call update()
124
125 // TODO: how should we communicate TLK rolling when the update() call will remove a peer?
126 // <rdar://problem/46633449> Octagon: must be able to roll TLKs when a peer departs due to machine ID list
127
128 // listDifferences: False if the allowedMachineIDs list passed in exactly matches the previous state,
129 // True if there were any differences
130 - (void)setAllowedMachineIDsWithContainer:(NSString *)container
131 context:(NSString *)context
132 allowedMachineIDs:(NSSet<NSString*> *)allowedMachineIDs
133 honorIDMSListChanges:(BOOL)honorIDMSListChanges
134 reply:(void (^)(BOOL listDifferences, NSError * _Nullable error))reply;
135
136 - (void)addAllowedMachineIDsWithContainer:(NSString *)container
137 context:(NSString *)context
138 machineIDs:(NSArray<NSString*> *)machineIDs
139 reply:(void (^)(NSError * _Nullable error))reply;
140
141 - (void)removeAllowedMachineIDsWithContainer:(NSString *)container
142 context:(NSString *)context
143 machineIDs:(NSArray<NSString*> *)machineIDs
144 reply:(void (^)(NSError * _Nullable error))reply;
145
146 - (void)fetchAllowedMachineIDsWithContainer:(NSString *)container
147 context:(NSString *)context
148 reply:(void (^)(NSSet<NSString*>* _Nullable machineIDs, NSError* _Nullable error))reply;
149
150 - (void)fetchEgoEpochWithContainer:(NSString *)container
151 context:(NSString *)context
152 reply:(void (^)(unsigned long long epoch,
153 NSError * _Nullable error))reply;
154
155 - (void)prepareWithContainer:(NSString *)container
156 context:(NSString *)context
157 epoch:(unsigned long long)epoch
158 machineID:(NSString *)machineID
159 bottleSalt:(NSString *)bottleSalt
160 bottleID:(NSString *)bottleID
161 modelID:(NSString *)modelID
162 deviceName:(nullable NSString *)deviceName
163 serialNumber:(nullable NSString *)serialNumber
164 osVersion:(NSString *)osVersion
165 policyVersion:(nullable TPPolicyVersion *)policyVersion
166 policySecrets:(nullable NSDictionary<NSString*,NSData*> *)policySecrets
167 syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews
168 signingPrivKeyPersistentRef:(nullable NSData *)spkPr
169 encPrivKeyPersistentRef:(nullable NSData*)epkPr
170 reply:(void (^)(NSString * _Nullable peerID,
171 NSData * _Nullable permanentInfo,
172 NSData * _Nullable permanentInfoSig,
173 NSData * _Nullable stableInfo,
174 NSData * _Nullable stableInfoSig,
175 TPSyncingPolicy* _Nullable syncingPolicy,
176 NSError * _Nullable error))reply;
177
178 // If there already are existing CKKSViews, please pass in their key sets anyway.
179 // This function will create a self TLK Share for those TLKs.
180 - (void)establishWithContainer:(NSString *)container
181 context:(NSString *)context
182 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)viewKeySets
183 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
184 preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
185 reply:(void (^)(NSString * _Nullable peerID,
186 NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
187 TPSyncingPolicy* _Nullable syncingPolicy,
188 NSError * _Nullable error))reply;
189
190 // Returns a voucher for the given peer ID using our own identity
191 // If TLK CKKSViewKeys are given, TLKShares will be created and uploaded for this new peer before this call returns.
192 - (void)vouchWithContainer:(NSString *)container
193 context:(NSString *)context
194 peerID:(NSString *)peerID
195 permanentInfo:(NSData *)permanentInfo
196 permanentInfoSig:(NSData *)permanentInfoSig
197 stableInfo:(NSData *)stableInfo
198 stableInfoSig:(NSData *)stableInfoSig
199 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)viewKeySets
200 reply:(void (^)(NSData * _Nullable voucher,
201 NSData * _Nullable voucherSig,
202 NSError * _Nullable error))reply;
203
204 // Preflighting a vouch will return the peer ID associated with the bottle you will be recovering, as well as
205 // the syncing policy used by that peer, and,
206 // You can then use that peer ID to filter the tlkshares provided to vouchWithBottle.
207 // If TPH had to refetch anything from the network, it will report that fact as refetchNeeded.
208 - (void)preflightVouchWithBottleWithContainer:(NSString *)container
209 context:(NSString *)context
210 bottleID:(NSString*)bottleID
211 reply:(void (^)(NSString* _Nullable peerID,
212 TPSyncingPolicy* _Nullable syncingPolicy,
213 BOOL refetchWasNeeded,
214 NSError * _Nullable error))reply;
215
216 // Returns a voucher for our own identity, created by the identity inside this bottle
217 - (void)vouchWithBottleWithContainer:(NSString *)container
218 context:(NSString *)context
219 bottleID:(NSString*)bottleID
220 entropy:(NSData*)entropy
221 bottleSalt:(NSString*)bottleSalt
222 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
223 reply:(void (^)(NSData * _Nullable voucher,
224 NSData * _Nullable voucherSig,
225 int64_t uniqueTLKsRecovered,
226 int64_t totalTLKSharesRecovered,
227 NSError * _Nullable error))reply;
228
229 // Preflighting a vouch will return the RK ID, view list and policy associated with the RK you will be recovering.
230 // You can then use that peer ID to filter the tlkshares provided to vouchWithRecoveryKey.
231 - (void)preflightVouchWithRecoveryKeyWithContainer:(NSString*)container
232 context:(NSString*)context
233 recoveryKey:(NSString*)recoveryKey
234 salt:(NSString*)salt
235 reply:(void (^)(NSString* _Nullable recoveryKeyID,
236 TPSyncingPolicy* _Nullable syncingPolicy,
237 NSError * _Nullable error))reply;
238
239 // Returns a voucher for our own identity, using recovery key
240 - (void)vouchWithRecoveryKeyWithContainer:(NSString *)container
241 context:(NSString *)context
242 recoveryKey:(NSString*)recoveryKey
243 salt:(NSString*)salt
244 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
245 reply:(void (^)(NSData * _Nullable voucher,
246 NSData * _Nullable voucherSig,
247 NSError * _Nullable error))reply;
248
249 // As of right now, join and attemptPreapprovedJoin will upload TLKShares for any TLKs that this peer already has.
250 // Note that in The Future, a device might decide to join an existing Octagon set while introducing a new view.
251 // These interfaces will have to change...
252 - (void)joinWithContainer:(NSString *)container
253 context:(NSString *)context
254 voucherData:(NSData *)voucherData
255 voucherSig:(NSData *)voucherSig
256 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)viewKeySets
257 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
258 preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
259 reply:(void (^)(NSString * _Nullable peerID,
260 NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
261 TPSyncingPolicy* _Nullable syncingPolicy,
262 NSError * _Nullable error))reply;
263
264 // Preflighting a preapproved join suggests whether or not you expect to succeed in an immediate preapprovedJoin() call
265 // This only inspects the Octagon model, and ignores the trusted device list, so that you can preflight the preapprovedJoin()
266 // before fetching that list.
267 // This will return YES if there are no existing peers, or if the existing peers preapprove your prepared identity, and
268 // you are intending to trust at least one preapproving peer (so that you don't stomp all over everyone else at join time).
269 // This will return NO otherwise.
270 - (void)preflightPreapprovedJoinWithContainer:(NSString *)container
271 context:(NSString *)context
272 preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
273 reply:(void (^)(BOOL launchOkay,
274 NSError * _Nullable error))reply;
275
276 // A preapproved join might do a join, but it also might do an establish.
277 // Therefore, it needs all the TLKs and TLKShares as establish does
278 - (void)attemptPreapprovedJoinWithContainer:(NSString *)container
279 context:(NSString *)context
280 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
281 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
282 preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
283 reply:(void (^)(NSString * _Nullable peerID,
284 NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
285 TPSyncingPolicy* _Nullable syncingPolicy,
286 NSError * _Nullable error))reply;
287
288 // TODO: if the new policy causes someone to lose access to a view, how should this API work?
289 // syncUserControllableViews should contain the raw value of the TPPBPeerStableInfo_UserControllableViewStatus enum, or be nil
290 - (void)updateWithContainer:(NSString *)container
291 context:(NSString *)context
292 deviceName:(nullable NSString *)deviceName
293 serialNumber:(nullable NSString *)serialNumber
294 osVersion:(nullable NSString *)osVersion
295 policyVersion:(nullable NSNumber *)policyVersion
296 policySecrets:(nullable NSDictionary<NSString*,NSData*> *)policySecrets
297 syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews
298 reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState,
299 TPSyncingPolicy* _Nullable syncingPolicy,
300 NSError * _Nullable error))reply;
301
302 - (void)setPreapprovedKeysWithContainer:(NSString *)container
303 context:(NSString *)context
304 preapprovedKeys:(NSArray<NSData*> *)preapprovedKeys
305 reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply;
306
307 /* Rather thin pass-through for uploading new TLKs (for zones which may have disappeared) */
308 - (void)updateTLKsWithContainer:(NSString *)container
309 context:(NSString *)context
310 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
311 tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
312 reply:(void (^)(NSArray<CKRecord*>* _Nullable keyHierarchyRecords, NSError * _Nullable error))reply;
313
314 - (void)fetchViableBottlesWithContainer:(NSString *)container
315 context:(NSString *)context
316 reply:(void (^)(NSArray<NSString*>* _Nullable sortedBottleIDs, NSArray<NSString*>* _Nullable sortedPartialBottleIDs, NSError* _Nullable error))reply;
317
318 - (void)fetchViableEscrowRecordsWithContainer:(NSString *)container
319 context:(NSString *)context
320 forceFetch:(BOOL)forceFetch
321 reply:(void (^)(NSArray<NSData*>* _Nullable records, NSError* _Nullable error))reply;
322
323 - (void)fetchEscrowContentsWithContainer:(NSString *)container
324 context:(NSString *)context
325 reply:(void (^)(NSData* _Nullable entropy,
326 NSString* _Nullable bottleID,
327 NSData* _Nullable signingPublicKey,
328 NSError* _Nullable error))reply;
329
330 - (void)fetchPolicyDocumentsWithContainer:(NSString*)container
331 context:(NSString*)context
332 versions:(NSSet<TPPolicyVersion*>*)versions
333 reply:(void (^)(NSDictionary<TPPolicyVersion*, NSData*>* _Nullable entries,
334 NSError * _Nullable error))reply;
335
336 // Fetch the policy and view list for current peer.
337 // Note: userControllableViewStatusOfPeers is not our current peer's view of the world, but rather what
338 // our peers believe.
339 // If there is no prepared ego peer, the returned policy will be for a device with modelIDOverride
340 - (void)fetchCurrentPolicyWithContainer:(NSString*)container
341 context:(NSString*)context
342 modelIDOverride:(NSString* _Nullable)modelID
343 reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy,
344 TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers,
345 NSError * _Nullable error))reply;
346
347 - (void)validatePeersWithContainer:(NSString *)container
348 context:(NSString *)context
349 reply:(void (^)(NSDictionary * _Nullable, NSError * _Nullable))reply;
350
351
352 // TODO: merge this and trustStatusWithContainer
353 - (void)fetchTrustStateWithContainer:(NSString *)container
354 context:(NSString *)context
355 reply:(void (^)(TrustedPeersHelperPeerState* _Nullable selfPeerState,
356 NSArray<TrustedPeersHelperPeer*>* _Nullable trustedPeers,
357 NSError* _Nullable error))reply;
358
359 - (void)setRecoveryKeyWithContainer:(NSString *)container
360 context:(NSString *)context
361 recoveryKey:(NSString *)recoveryKey
362 salt:(NSString *)salt
363 ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
364 reply:(void (^)(NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
365 NSError* _Nullable error))reply;
366
367 - (void)reportHealthWithContainer:(NSString *)container
368 context:(NSString *)context
369 stateMachineState:(NSString *)state
370 trustState:(NSString *)trustState
371 reply:(void (^)(NSError* _Nullable error))reply;
372
373 - (void)pushHealthInquiryWithContainer:(NSString *)container
374 context:(NSString *)context
375 reply:(void (^)(NSError* _Nullable error))reply;
376
377 - (void)requestHealthCheckWithContainer:(NSString *)container
378 context:(NSString *)context
379 requiresEscrowCheck:(BOOL)requiresEscrowCheck
380 reply:(void (^)(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, BOOL leaveTrust, NSError* _Nullable))reply;
381
382 - (void)getSupportAppInfoWithContainer:(NSString *)container
383 context:(NSString *)context
384 reply:(void (^)(NSData * _Nullable, NSError * _Nullable))reply;
385
386 - (void)removeEscrowCacheWithContainer:(NSString *)container
387 context:(NSString *)context
388 reply:(void (^)(NSError * _Nullable))reply;
389
390 @end
391
392 /*
393 To use the service from an application or other process, use NSXPCConnection to establish a connection to the service by doing something like this:
394
395 _connectionToService = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.TrustedPeersHelper"];
396 _connectionToService.remoteObjectInterface = TrustedPeersHelperSetupProtocol([NSXPCInterface interfaceWithProtocol:@protocol(TrustedPeersHelperProtocol)]);
397 [_connectionToService resume];
398
399 Once you have a connection to the service, you can use it like this:
400
401 [[_connectionToService remoteObjectProxy] upperCaseString:@"hello" withReply:^(NSString *aString) {
402 // We have received a response. Update our text field, but do it on the main thread.
403 NSLog(@"Result string was: %@", aString);
404 }];
405
406 And, when you are finished with the service, clean up the connection like this:
407
408 [_connectionToService invalidate];
409 */
410
411
412 // Use this at protocol creation time to tell NSXPC to do its job
413 NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface);
414
415 NS_ASSUME_NONNULL_END