]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/tests/CKKSMockSOSPresentAdapter.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / ckks / tests / CKKSMockSOSPresentAdapter.m
1 #import "keychain/ckks/CKKSListenerCollection.h"
2 #import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h"
3
4 @interface CKKSMockSOSPresentAdapter()
5 @property CKKSListenerCollection* peerChangeListeners;
6 @end
7
8 @implementation CKKSMockSOSPresentAdapter
9 @synthesize essential = _essential;
10 @synthesize sosEnabled = _sosEnabled;
11
12 - (instancetype)initWithSelfPeer:(CKKSSOSSelfPeer*)selfPeer
13 trustedPeers:(NSSet<CKKSSOSPeer*>*)trustedPeers
14 essential:(BOOL)essential
15 {
16 if((self = [super init])) {
17 _sosEnabled = true;
18 _essential = essential;
19
20 _circleStatus = kSOSCCInCircle;
21 _safariViewEnabled = YES;
22
23 _excludeSelfPeerFromTrustSet = false;
24
25 _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-mock-sos"];
26
27 _ckks4AllStatus = NO;
28 _ckks4AllStatusIsSet = NO;
29
30 _selfPeer = selfPeer;
31 _trustedPeers = [trustedPeers mutableCopy];
32 }
33 return self;
34 }
35
36 - (NSString*)providerID
37 {
38 return [NSString stringWithFormat:@"[CKKSMockSOSPresentAdapter: %@]", self.selfPeer.peerID];
39 }
40
41 - (SOSCCStatus)circleStatus:(NSError * _Nullable __autoreleasing * _Nullable)error
42 {
43 if(!self.sosEnabled || self.circleStatus == kSOSCCError) {
44 if(error && self.circleStatus == kSOSCCError) {
45 // I'm not at all sure that the second error here actually is any error in particular
46 *error = self.circleStatusError ?: [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil];
47 }
48 return kSOSCCError;
49 }
50
51 return self.circleStatus;
52 }
53
54 // I currently don't understand when SOS returns a self or not. I've seen it return a self while not in kSOSCCInCircle,
55 // which seems wrong. So, always return a self, unless we're in an obvious error state.
56 - (id<CKKSSelfPeer> _Nullable)currentSOSSelf:(NSError * _Nullable __autoreleasing * _Nullable)error
57 {
58 if(self.selfPeerError) {
59 if(error) {
60 *error = self.selfPeerError;
61 }
62 return nil;
63 }
64
65 if(self.aksLocked) {
66 if(error) {
67 *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil];
68 }
69 return nil;
70 }
71
72 if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) {
73 return self.selfPeer;
74 } else {
75 if(error) {
76 *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil];
77 }
78 return nil;
79 }
80 }
81
82 - (CKKSSelves * _Nullable)fetchSelfPeers:(NSError *__autoreleasing _Nullable * _Nullable)error
83 {
84 id<CKKSSelfPeer> peer = [self currentSOSSelf:error];
85 if(!peer) {
86 return nil;
87 }
88
89 return [[CKKSSelves alloc] initWithCurrent:peer allSelves:nil];
90 }
91
92 - (NSSet<id<CKKSRemotePeerProtocol>> * _Nullable)fetchTrustedPeers:(NSError * _Nullable __autoreleasing * _Nullable)error
93 {
94 if(self.trustedPeersError) {
95 if(error) {
96 *error = self.trustedPeersError;
97 }
98 return nil;
99 }
100
101 // TODO: I'm actually not entirely sure what SOS does if it's not in circle?
102 if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) {
103 if(self.excludeSelfPeerFromTrustSet) {
104 return self.trustedPeers;
105 } else {
106 return [self allPeers];
107 }
108 } else {
109 if(error) {
110 *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSCCNotInCircle userInfo:nil];
111 }
112 return nil;
113 }
114 }
115
116 - (BOOL)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
117 if(self.updateOctagonKeySetListener) {
118 self.updateOctagonKeySetListener(currentSelfPeer);
119 }
120 return YES;
121 }
122
123 - (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error
124 {
125 self.ckks4AllStatus = status;
126 self.ckks4AllStatusIsSet = YES;
127 return YES;
128 }
129
130 - (void)registerForPeerChangeUpdates:(nonnull id<CKKSPeerUpdateListener>)listener {
131 [self.peerChangeListeners registerListener:listener];
132 }
133
134 - (void)sendSelfPeerChangedUpdate {
135 [self.peerChangeListeners iterateListeners: ^(id<CKKSPeerUpdateListener> listener) {
136 [listener selfPeerChanged:self];
137 }];
138 }
139
140 - (void)sendTrustedPeerSetChangedUpdate {
141 [self.peerChangeListeners iterateListeners: ^(id<CKKSPeerUpdateListener> listener) {
142 [listener trustedPeerSetChanged:self];
143 }];
144 }
145
146 - (nonnull CKKSPeerProviderState *)currentState {
147 return [CKKSPeerProviderState createFromProvider:self];
148 }
149
150 - (NSSet<id<CKKSRemotePeerProtocol>>*)allPeers
151 {
152 // include the self peer, but as a CKKSSOSPeer object instead of a self peer
153 CKKSSOSPeer* s = [[CKKSSOSPeer alloc] initWithSOSPeerID:self.selfPeer.peerID
154 encryptionPublicKey:self.selfPeer.publicEncryptionKey
155 signingPublicKey:self.selfPeer.publicSigningKey
156 viewList:self.selfPeer.viewList];
157
158 return [self.trustedPeers setByAddingObject: s];
159 }
160
161 - (BOOL)safariViewSyncingEnabled:(NSError**)error
162 {
163 // TODO: what happens if you call this when not in circle?
164 return self.safariViewEnabled;
165 }
166
167 - (BOOL)preloadOctagonKeySetOnAccount:(nonnull id<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
168 // No-op
169 return YES;
170 }
171
172 @end