]> git.saurik.com Git - apple/security.git/blob - keychain/ot/tests/OTTestsBase.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / ot / tests / OTTestsBase.m
1 /*
2 * Copyright (c) 2017 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
26 #import "OTTestsBase.h"
27 #import "keychain/ot/OTSOSAdapter.h"
28
29 static NSString* const testContextID = @"Foo";
30 static NSString* const testContextForAcceptor = @"Acceptor";
31
32 static NSString* const testDSID = @"123456789";
33
34 static int _test_num = 0;
35 static NSString* _path;
36 static NSString* _dbPath;
37
38 static NSString* OTCKZoneName = @"OctagonTrust";
39
40 static NSString* const kOTRampZoneName = @"metadata_zone";
41 static NSString* const kOTRampForEnrollmentRecordName = @"metadata_rampstate_enroll";
42 static NSString* const kOTRampForRestoreRecordName = @"metadata_rampstate_restore";
43 static NSString* const kOTRampForCFURecordName = @"metadata_rampstate_cfu";
44
45 static NSString* kFeatureAllowedKey = @"FeatureAllowed";
46 static NSString* kFeaturePromotedKey = @"FeaturePromoted";
47 static NSString* kFeatureVisibleKey = @"FeatureVisible";
48 static NSString* kRetryAfterKey = @"RetryAfter";
49 static NSString* kRampPriorityKey = @"RampPriority";
50
51 static NSString* OTCKRecordBottledPeerType = @"OTBottledPeer";
52
53 @implementation OTTestsBase
54
55 // Override our base class
56 -(NSSet*)managedViewList {
57 return [NSSet setWithObject:@"keychain"];
58 }
59
60 + (void)setUp {
61 SecCKKSEnable();
62 SecCKKSResetSyncing();
63 [super setUp];
64 }
65
66 - (void)setUp
67 {
68 [super setUp];
69
70 self.continueAfterFailure = NO;
71 NSError* error = nil;
72
73 _path = @"/tmp/ottrusttests";
74 _dbPath = [_path stringByAppendingFormat:@"/ottest.db.%d",_test_num++];
75
76 XCTAssertTrue([[NSFileManager defaultManager] createDirectoryAtPath:_path withIntermediateDirectories:YES attributes:nil error:nil], @"directory created!");
77 self.localStore = [[OTLocalStore alloc]initWithContextID:testContextID dsid:testDSID path:_dbPath error:&error];
78 XCTAssertNil(error, "error should be nil");
79
80 self.cloudStore = [[OTCloudStore alloc] initWithContainer:self.mockContainer
81 zoneName:OTCKZoneName
82 accountTracker:self.mockAccountStateTracker
83 reachabilityTracker:self.mockReachabilityTracker
84 localStore:self.localStore
85 contextID:testContextID
86 dsid:testDSID
87 fetchRecordZoneChangesOperationClass:self.mockFakeCKFetchRecordZoneChangesOperation
88 fetchRecordsOperationClass:self.mockFakeCKFetchRecordZoneChangesOperation
89 queryOperationClass:self.mockFakeCKQueryOperation
90 modifySubscriptionsOperationClass:self.mockFakeCKModifySubscriptionsOperation
91 modifyRecordZonesOperationClass:self.mockFakeCKFetchRecordsOperation
92 apsConnectionClass:self.mockFakeCKModifySubscriptionsOperation
93 operationQueue:nil];
94
95 NSString* secretString = @"I'm a secretI'm a secretI'm a secretI'm a secretI'm a secretI'm a secret";
96 self.secret = [[NSData alloc]initWithBytes:[secretString UTF8String] length:[secretString length]];
97
98 self.context = [[OTContext alloc]initWithContextID:testContextID dsid:testDSID localStore:self.localStore cloudStore:self.cloudStore identityProvider:self error:&error];
99 XCTAssertNil(error, "error should be nil");
100
101 self.sosPeerID = @"spID";
102 self.egoPeerID = @"egoPeerID";
103 self.peerSigningKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
104 self.peerEncryptionKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
105 self.escrowKeys = [[OTEscrowKeys alloc]initWithSecret:self.secret dsid:testDSID error:&error];
106
107 XCTAssertNotNil(self.context, @"context not initialized");
108
109 self.otZoneID = [[CKRecordZoneID alloc] initWithZoneName:OTCKZoneName ownerName:CKCurrentUserDefaultName];
110
111 XCTAssertNotNil(self.otZoneID, @"cloudkit record zone id is not initialized");
112
113 self.otFakeZone = [[FakeCKZone alloc] initZone: self.otZoneID];
114 XCTAssertNotNil(self.otFakeZone, @"fake ot zone is not initialized");
115
116 self.zones[self.otZoneID] = self.otFakeZone;
117 XCTAssertNotNil(self.zones, @"ot zones set is not initialized");
118
119 self.rampZoneID = [[CKRecordZoneID alloc] initWithZoneName:kOTRampZoneName ownerName:CKCurrentUserDefaultName];
120 self.rampZone = [[FakeCKZone alloc]initZone:self.rampZoneID];
121 self.zones[self.rampZoneID] = self.rampZone;
122
123 self.cfu = [self fakeRamp:kOTRampForCFURecordName
124 featureName:@"FAKE-cfu"
125 accountTracker:self.accountStateTracker
126 lockStateStracker:self.lockStateTracker
127 reachabilityTracker:self.reachabilityTracker];
128 self.enroll = [self fakeRamp:kOTRampForEnrollmentRecordName
129 featureName:@"FAKE-enroll"
130 accountTracker:self.accountStateTracker
131 lockStateStracker:self.lockStateTracker
132 reachabilityTracker:self.reachabilityTracker];
133 self.restore = [self fakeRamp:kOTRampForRestoreRecordName
134 featureName:@"FAKE-restore"
135 accountTracker:self.accountStateTracker
136 lockStateStracker:self.lockStateTracker
137 reachabilityTracker:self.reachabilityTracker];
138
139 self.scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay:50*NSEC_PER_MSEC keepProcessAlive:true
140 dependencyDescriptionCode:CKKSResultDescriptionNone
141 block:^{
142 [self.expectation fulfill];
143 }];
144 self.manager = [[OTManager alloc] initWithContext:self.context
145 localStore:self.localStore
146 enroll:self.enroll
147 restore:self.restore
148 cfu:self.cfu
149 cfuScheduler:self.scheduler
150 sosAdapter:[[OTSOSActualAdapter alloc] init]
151 authKitAdapter:[[OTAuthKitActualAdapter alloc] init]
152 apsConnectionClass:[FakeAPSConnection class]];
153 [OTManager resetManager:true to:self.manager];
154
155 self.cuttlefishContext = [self.manager contextForContainerName:OTCKContainerName
156 contextID:OTDefaultContext];
157
158 id mockConnection = OCMPartialMock([[NSXPCConnection alloc] init]);
159 OCMStub([mockConnection remoteObjectProxyWithErrorHandler:[OCMArg any]]).andCall(self, @selector(manager));
160 self.otControl = [[OTControl alloc] initWithConnection:mockConnection sync:true];
161 XCTAssertNotNil(self.otControl, "Should have received control object");
162
163 [self.reachabilityTracker setNetworkReachability:true];
164 [self.context.reachabilityTracker recheck];
165 [self.cfu.reachabilityTracker recheck];
166 [self.enroll.reachabilityTracker recheck];
167 [self.restore.reachabilityTracker recheck];
168 }
169
170
171 - (void)tearDown
172 {
173 NSError *error = nil;
174
175 [_localStore removeAllBottledPeerRecords:&error];
176 [_localStore deleteAllContexts:&error];
177
178 _context = nil;
179 _cloudStore = nil;
180 _localStore = nil;
181 _escrowKeys = nil;
182 _peerSigningKey = nil;
183 _peerEncryptionKey = nil;
184 _otFakeZone = nil;
185 _otZoneID = nil;
186
187 _rampZone = nil;
188 _rampZoneID = nil;
189 _cfuRampRecord = nil;
190 _enrollRampRecord = nil;
191 _restoreRampRecord = nil;
192 _scheduler = nil;
193
194 [super tearDown];
195 }
196
197 - (OTRamp*)fakeRamp:(NSString*)recordName
198 featureName:(NSString*)featureName
199 accountTracker:(CKKSAccountStateTracker*)accountTracker
200 lockStateStracker:(CKKSLockStateTracker*)lockStateTracker
201 reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker
202 {
203
204 OTRamp* ramp = [[OTRamp alloc]initWithRecordName:recordName
205 featureName:featureName
206 container:self.mockContainer
207 database:self.mockDatabase
208 zoneID:self.rampZoneID
209 accountTracker:accountTracker
210 lockStateTracker:lockStateTracker
211 reachabilityTracker:reachabilityTracker
212 fetchRecordRecordsOperationClass:self.mockFakeCKFetchRecordsOperation];
213
214 return ramp;
215 }
216
217 -(void) setUpRampRecordsInCloudKitWithFeatureOff
218 {
219 CKRecordID* enrollRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForEnrollmentRecordName zoneID:self.rampZoneID];
220 self.enrollRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForEnrollmentRecordName recordID:enrollRecordID];
221 self.enrollRampRecord[kFeatureAllowedKey] = @NO;
222 self.enrollRampRecord[kFeaturePromotedKey] = @NO; //always false right now
223 self.enrollRampRecord[kFeatureVisibleKey] = @NO;
224 self.enrollRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
225
226 CKRecordID* restoreRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForRestoreRecordName zoneID:self.rampZoneID];
227 self.restoreRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForEnrollmentRecordName recordID:restoreRecordID];
228 self.restoreRampRecord[kFeatureAllowedKey] = @NO;
229 self.restoreRampRecord[kFeaturePromotedKey] = @NO; //always false right now
230 self.restoreRampRecord[kFeatureVisibleKey] = @NO;
231 self.restoreRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
232
233 CKRecordID* cfuRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForCFURecordName zoneID:self.rampZoneID];
234 self.cfuRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForCFURecordName recordID:cfuRecordID];
235 self.cfuRampRecord[kFeatureAllowedKey] = @NO;
236 self.cfuRampRecord[kFeaturePromotedKey] = @NO; //always false right now
237 self.cfuRampRecord[kFeatureVisibleKey] = @NO;
238 self.cfuRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
239
240 [self.rampZone addToZone:self.enrollRampRecord];
241 [self.rampZone addToZone:self.restoreRampRecord];
242 [self.rampZone addToZone:self.cfuRampRecord];
243 }
244
245 -(void) setUpRampRecordsInCloudKitWithFeatureOn
246 {
247 CKRecordID* enrollRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForEnrollmentRecordName zoneID:self.rampZoneID];
248 self.enrollRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForEnrollmentRecordName recordID:enrollRecordID];
249 self.enrollRampRecord[kFeatureAllowedKey] = @YES;
250 self.enrollRampRecord[kFeaturePromotedKey] = @NO; //always false right now
251 self.enrollRampRecord[kFeatureVisibleKey] = @YES;
252 self.enrollRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
253
254 CKRecordID* restoreRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForRestoreRecordName zoneID:self.rampZoneID];
255 self.restoreRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForEnrollmentRecordName recordID:restoreRecordID];
256 self.restoreRampRecord[kFeatureAllowedKey] = @YES;
257 self.restoreRampRecord[kFeaturePromotedKey] = @NO; //always false right now
258 self.restoreRampRecord[kFeatureVisibleKey] = @YES;
259 self.restoreRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
260
261 CKRecordID* cfuRecordID = [[CKRecordID alloc] initWithRecordName:kOTRampForCFURecordName zoneID:self.rampZoneID];
262 self.cfuRampRecord = [[CKRecord alloc] initWithRecordType:kOTRampForCFURecordName recordID:cfuRecordID];
263 self.cfuRampRecord[kFeatureAllowedKey] = @YES;
264 self.cfuRampRecord[kFeaturePromotedKey] = @NO; //always false right now
265 self.cfuRampRecord[kFeatureVisibleKey] = @YES;
266 self.cfuRampRecord[kRetryAfterKey] = [[NSNumber alloc]initWithInt:3600];
267
268 [self.rampZone addToZone:self.enrollRampRecord];
269 [self.rampZone addToZone:self.restoreRampRecord];
270 [self.rampZone addToZone:self.cfuRampRecord];
271 }
272
273
274 -(void)expectAddedCKModifyRecords:(NSDictionary<NSString*, NSNumber*>*)records holdFetch:(BOOL)shouldHoldTheFetch
275 {
276 __weak __typeof(self) weakSelf = self;
277
278 [self expectCKModifyRecords:records
279 deletedRecordTypeCounts:nil
280 zoneID:self.otZoneID
281 checkModifiedRecord:^BOOL (CKRecord* record){
282 if([record.recordType isEqualToString: OTCKRecordBottledPeerType]) {
283 return YES;
284 } else { //not a Bottled Peer Record Type
285 return NO;
286 }
287 }
288 runAfterModification:^{
289 __strong __typeof(self) strongSelf = weakSelf;
290 if(shouldHoldTheFetch){
291 [strongSelf holdCloudKitFetches];
292 }
293
294 }
295 ];
296 }
297
298 -(void)expectDeletedCKModifyRecords:(NSDictionary<NSString*, NSNumber*>*)records holdFetch:(BOOL)shouldHoldTheFetch
299 {
300 __weak __typeof(self) weakSelf = self;
301
302 [self expectCKModifyRecords:[NSMutableDictionary dictionary]
303 deletedRecordTypeCounts:records
304 zoneID:self.otZoneID
305 checkModifiedRecord:^BOOL (CKRecord* record){
306 if([record.recordType isEqualToString: OTCKRecordBottledPeerType]) {
307 return YES;
308 } else { //not a Bottled Peer Record Type
309 return NO;
310 }
311 }
312 runAfterModification:^{
313 __strong __typeof(self) strongSelf = weakSelf;
314 if(shouldHoldTheFetch){
315 [strongSelf holdCloudKitFetches];
316 }
317 }
318 ];
319 }
320
321 - (nullable OTIdentity *)currentIdentity:(NSError * _Nullable __autoreleasing * _Nullable)error {
322 return [[OTIdentity alloc]initWithPeerID:self.egoPeerID spID:self.sosPeerID peerSigningKey:self.peerSigningKey peerEncryptionkey:self.peerEncryptionKey error:error];
323 }
324
325 @end
326 #endif