2 * Copyright (c) 2017 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>
27 #import "TPSigningKey.h"
28 #import "TPDecrypter.h"
32 @
class TPPeerPermanentInfo
;
33 @
class TPPeerStableInfo
;
34 @
class TPPeerDynamicInfo
;
36 @
class TPPolicyDocument
;
39 typedef NS_OPTIONS(NSUInteger
, TPPeerStatus
) {
40 // Set if at least one of the peers I trust trusts me.
41 TPPeerStatusPartiallyReciprocated
= 1 << 0,
43 // Set if all of the peers I trust trust me.
44 TPPeerStatusFullyReciprocated
= 1 << 1,
46 // Set if I have been kicked out of trust.
47 TPPeerStatusExcluded
= 1 << 2,
49 // Set if my epoch is behind the latest epoch.
50 TPPeerStatusOutdatedEpoch
= 1 << 3,
52 // Set if my epoch is two or more epochs behind the latest.
53 TPPeerStatusAncientEpoch
= 1 << 4,
57 NS_ASSUME_NONNULL_BEGIN
60 TPModel implements the Octagon Trust model, as per
61 https://confluence.sd.apple.com/display/KEY/Octagon+Trust
63 It maintains a collection of peers and a collection of circles,
64 to track the peers and circles in CloudKit.
65 (This class does not communicate with CloudKit. The client of this class does that.)
67 Normally there would be just one instance of TPModel, associated with a particular Apple ID.
68 (This class doesn't need to know what the Apple ID is.)
70 This interface does not expose TPPeer* because the caller might mutate the peer object.
71 All the objects exposed by this interface are immutable.
73 @interface TPModel
: NSObject
75 - (instancetype
)initWithDecrypter
:(id
<TPDecrypter
>)decrypter
;
77 - (TPCounter
)latestEpochAmongPeerIDs
:(NSSet
<NSString
*> *)peerIDs
;
79 - (void)registerPolicyDocument
:(TPPolicyDocument
*)policyDoc
;
82 Register a peer with the given permanentInfo.
84 To access this peer invoke other TPModel methods and
85 pass permanentInfo.peerID as the peerID argument.
87 (If a peer with this permanentInfo is already registered then registering it again
88 does nothing, and the existing TPPeer object internal to TPModel retains its state.)
90 - (void)registerPeerWithPermanentInfo
:(TPPeerPermanentInfo
*)permanentInfo
;
92 - (void)deletePeerWithID
:(NSString
*)peerID
;
94 - (BOOL
)hasPeerWithID
:(NSString
*)peerID
;
97 Asserts that peerID is registered.
99 - (TPPeerStatus
)statusOfPeerWithID
:(NSString
*)peerID
;
102 Asserts that peerID is registered.
104 - (TPPeerPermanentInfo
*)getPermanentInfoForPeerWithID
:(NSString
*)peerID
;
107 Asserts that peerID is registered.
109 - (nullable TPPeerStableInfo
*)getStableInfoForPeerWithID
:(NSString
*)peerID
;
112 Asserts that peerID is registered.
114 - (nullable NSData
*)getWrappedPrivateKeysForPeerWithID
:(NSString
*)peerID
;
117 Asserts that peerID is registered.
119 - (void)setWrappedPrivateKeys
:(nullable NSData
*)wrappedPrivateKeys
120 forPeerWithID
:(NSString
*)peerID
;
123 Asserts that peerID is registered.
125 - (nullable TPPeerDynamicInfo
*)getDynamicInfoForPeerWithID
:(NSString
*)peerID
;
128 Asserts that peerID is registered.
130 - (nullable TPCircle
*)getCircleForPeerWithID
:(NSString
*)peerID
;
133 - (void)registerCircle
:(TPCircle
*)circle
;
135 - (void)deleteCircleWithID
:(NSString
*)circleID
;
138 Returns nil if no circle matching circleID is registered.
140 - (nullable TPCircle
*)circleWithID
:(NSString
*)circleID
;
144 An "update" with unchanged data is considered success.
145 Asserts that peerID is registered.
147 - (TPResult
)updateStableInfo
:(TPPeerStableInfo
*)stableInfo
148 forPeerWithID
:(NSString
*)peerID
;
151 Returns nil with error if the peer's trustSigningKey is unable to create
152 a signature because the private key is unavailable, e.g. because the device is locked.
154 Asserts peerID is registered.
156 - (TPPeerStableInfo
*)createStableInfoWithDictionary
:(NSDictionary
*)dict
157 policyVersion
:(TPCounter
)policyVersion
158 policyHash
:(NSString
*)policyHash
159 policySecrets
:(nullable NSDictionary
*)policySecrets
160 forPeerWithID
:(NSString
*)peerID
161 error
:(NSError
**)error
;
165 An "update" with unchanged data is considered success.
166 Asserts peerID is registered.
168 - (TPResult
)updateDynamicInfo
:(TPPeerDynamicInfo
*)dynamicInfo
169 forPeerWithID
:(NSString
*)peerID
;
173 The returned voucher is not registered.
174 Asserts sponsorID is registered.
176 Returns nil with nil error if policy determines that the sponsor
177 is not permitted to introduce this candidate.
179 Returns nil with error if the sponsor's trustSigningKey is unable to create
180 a signature because the private key is unavailable, e.g. because the device is locked.
182 The candidate need not be registered before making this call.
184 - (nullable TPVoucher
*)createVoucherForCandidate
:(TPPeerPermanentInfo
*)candidate
185 withSponsorID
:(NSString
*)sponsorID
186 error
:(NSError
**)error
;
189 Asserts that the sponsor is registered, so that the signature check can be performed.
190 The beneficiary need not be registered.
192 - (TPResult
)registerVoucher
:(TPVoucher
*)voucher
;
195 - (NSSet
<NSString
*> *)calculateUnusedCircleIDs
;
198 Calculates updated dynamic info for a given peer,
199 according to the membership convergence algorithm.
201 This method does not update the model. The calculated circle is not registered
202 and the peer is not updated with the calculated dynamicInfo. It is the caller's
203 responsibility to register/update them once they have been persisted to CloudKit.
205 Peers listed in addingPeerIDs are taken to have been explicitly trusted by the user.
206 When the user adds a member of addingPeerIDs into trust, the peers already trusted
207 by that new peer are also taken to be trusted, even if the new peer is not qualified by
208 policy to *introduce* them into trust. This is neccessary in a scenario where a mid-level
209 device approves a lowly device, and the new lowly device should trust the high-level devices
210 already in the circle. The mid-level device is not *introducing* the high-level devices.
212 Peers listed in removingPeerIDs are excluded from trust.
214 Returns nil with error if the peer's trustSigningKey is unable to create
215 a signature because the private key is unavailable, e.g. because the device is locked.
217 Asserts peerID is registered.
219 - (nullable TPPeerDynamicInfo
*)calculateDynamicInfoForPeerWithID
:(NSString
*)peerID
220 addingPeerIDs
:(nullable NSArray
<NSString
*> *)addingPeerIDs
221 removingPeerIDs
:(nullable NSArray
<NSString
*> *)removingPeerIDs
222 createClique
:(nullable NSString
* (^)())createClique
223 updatedCircle
:(TPCircle
* _Nullable
* _Nullable
)updatedCircle
224 error
:(NSError
**)error
;
227 A convenience method for tests, this calls calculateDynamicInfoForPeerWithID,
228 registers the results and returns the new circle.
230 - (TPCircle
*)advancePeerWithID
:(NSString
*)peerID
231 addingPeerIDs
:(nullable NSArray
<NSString
*> *)addingPeerIDs
232 removingPeerIDs
:(nullable NSArray
<NSString
*> *)removingPeerIDs
233 createClique
:(nullable NSString
* (^)())createClique
;
236 From our trusted peers, return the subset that is allowed
237 to access the given view, according to the current policy.
239 Asserts peerID is registered.
241 - (nullable NSSet
<NSString
*> *)getPeerIDsTrustedByPeerWithID
:(NSString
*)peerID
242 toAccessView
:(NSString
*)view
243 error
:(NSError
**)error
;
246 Returns a dictionary mapping from each peer ID
247 to the most recent clock seen from that peer.
249 - (NSDictionary
<NSString
*,NSNumber
*> *)vectorClock
;
253 NS_ASSUME_NONNULL_END