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