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