]> git.saurik.com Git - apple/security.git/blob - keychain/ot/tests/OTBottledPeerUpdateBottlesTests.m
bb762dc12c78bdda1ec6f6943b3771bf58aa8635
[apple/security.git] / keychain / ot / tests / OTBottledPeerUpdateBottlesTests.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 <Foundation/Foundation.h>
27
28 #import <XCTest/XCTest.h>
29 #import <OCMock/OCMock.h>
30
31 #import "OTTestsBase.h"
32 #import "keychain/ot/OTConstants.h"
33
34 static NSString* const testContextID = @"Foo";
35 static NSString* const testDSID = @"123456789";
36
37 static NSString* OTCKRecordBottledPeerType = @"OTBottledPeer";
38
39 @interface OTUpdateBottlesTests : OTTestsBase
40
41 @end
42
43 @implementation OTUpdateBottlesTests
44
45 - (void)setUp {
46 [super setUp];
47 self.continueAfterFailure = NO;
48 [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test.
49 }
50
51 - (void)tearDown {
52 [super tearDown];
53 }
54
55 -(void)testUpdatingExistingBottle
56 {
57 __block NSData* localEntropy = nil;
58 __block NSString* localBottleID = nil;
59
60 self.spiBlockExpectation = [self expectationWithDescription:@"preflight SPI should fire"];
61
62 [self setUpRampRecordsInCloudKitWithFeatureOn];
63
64 [self startCKKSSubsystem];
65
66 //create a bottle
67 [self.otControl preflightBottledPeer:testContextID
68 dsid:testDSID
69 reply:^(NSData * _Nullable entropy, NSString * _Nullable bottleID, NSData * _Nullable signingPublicKey, NSError * _Nullable error) {
70 [self.spiBlockExpectation fulfill];
71 localEntropy = entropy;
72 localBottleID = bottleID;
73 XCTAssertNotNil(entropy, "entropy should not be nil");
74 XCTAssertNotNil(bottleID, "bottle id should not be nil");
75 XCTAssertNotNil(signingPublicKey, "signing pub key should not be nil");
76 XCTAssertNil(error, "error should be nil");
77 }];
78
79 [self waitForExpectationsWithTimeout:1.0 handler:nil];
80
81 NSMutableDictionary* recordDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:[[NSNumber alloc] initWithInt:1], OTCKRecordBottledPeerType, nil];
82
83 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
84
85 self.spiBlockExpectation = [self expectationWithDescription:@"launch bottle SPI should fire"];
86
87 //launch it
88 [self.otControl launchBottledPeer:testContextID bottleID:localBottleID reply:^(NSError * _Nullable error) {
89 [self.spiBlockExpectation fulfill];
90 XCTAssertNil(error, "error should be nil");
91 }];
92
93 [self waitForExpectationsWithTimeout:1.0 handler:nil];
94
95 [self waitForCKModifications];
96 OCMVerifyAllWithDelay(self.mockDatabase, 8);
97 [self releaseCloudKitFetchHold];
98
99 [self expectCKFetch];
100
101 SFECKeyPair* newSigningKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
102
103 SFECKeyPair* newEncryptionKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
104
105 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
106
107 self.spiBlockExpectation = [self expectationWithDescription:@"updating identity SPI should fire"];
108
109 //update bottle
110 [self.otControl handleIdentityChangeForSigningKey:newSigningKey
111 ForEncryptionKey:newEncryptionKey
112 ForPeerID:self.sosPeerID
113 reply:^(BOOL result, NSError* _Nullable error){
114 [self.spiBlockExpectation fulfill];
115 XCTAssertTrue(result, "result should be YES");
116 XCTAssertNil(error, "error should be nil");
117 }];
118 [self waitForExpectationsWithTimeout:1.0 handler:nil];
119 }
120
121 -(void)testUpdatingNonExistentBottles
122 {
123 self.spiBlockExpectation = [self expectationWithDescription:@"updating identity SPI should fire"];
124
125 [self setUpRampRecordsInCloudKitWithFeatureOn];
126
127 [self startCKKSSubsystem];
128
129 SFECKeyPair* newSigningKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
130
131 SFECKeyPair* newEncryptionKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
132
133 //update bottle
134 [self.otControl handleIdentityChangeForSigningKey:newSigningKey
135 ForEncryptionKey:newEncryptionKey
136 ForPeerID:self.sosPeerID
137 reply:^(BOOL result, NSError* _Nullable error){
138 [self.spiBlockExpectation fulfill];
139 XCTAssertNotNil(error, "error should not be nil");
140 XCTAssertFalse(result, "result should be NO");
141 }];
142 [self waitForExpectationsWithTimeout:1.0 handler:nil];
143 }
144
145 -(void)testUpdatingBottleMissingKeys
146 {
147 __block NSData* localEntropy = nil;
148 __block NSString* localBottleID = nil;
149 NSError *localError = nil;
150 self.spiBlockExpectation = [self expectationWithDescription:@"preflight SPI should fire"];
151
152 [self setUpRampRecordsInCloudKitWithFeatureOn];
153
154 [self startCKKSSubsystem];
155
156 //create a bottle
157 [self.otControl preflightBottledPeer:testContextID
158 dsid:testDSID
159 reply:^(NSData * _Nullable entropy, NSString * _Nullable bottleID, NSData * _Nullable signingPublicKey, NSError * _Nullable error) {
160 [self.spiBlockExpectation fulfill];
161 localEntropy = entropy;
162 localBottleID = bottleID;
163 XCTAssertNotNil(entropy, "entropy should not be nil");
164 XCTAssertNotNil(bottleID, "bottle id should not be nil");
165 XCTAssertNotNil(signingPublicKey, "signing pub key should not be nil");
166 XCTAssertNil(error, "error should be nil");
167 }];
168
169 [self waitForExpectationsWithTimeout:1.0 handler:nil];
170
171 NSMutableDictionary* recordDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:[[NSNumber alloc] initWithInt:1], OTCKRecordBottledPeerType, nil];
172
173 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
174
175 self.spiBlockExpectation = [self expectationWithDescription:@"launch bottle SPI should fire"];
176
177 //launch it
178 [self.otControl launchBottledPeer:testContextID bottleID:localBottleID reply:^(NSError * _Nullable error) {
179 [self.spiBlockExpectation fulfill];
180 XCTAssertNil(error, "error should be nil");
181 }];
182
183 [self waitForExpectationsWithTimeout:1.0 handler:nil];
184
185 [self waitForCKModifications];
186 OCMVerifyAllWithDelay(self.mockDatabase, 8);
187 [self releaseCloudKitFetchHold];
188
189 [self expectCKFetch];
190
191 //delete escrow keys
192 OTEscrowKeys* keySet = [[OTEscrowKeys alloc] initWithSecret:localEntropy dsid:testDSID error:&localError];
193 XCTAssertNotNil(keySet, "keySet should not be nil");
194 XCTAssertNil(localError, "localError should be nil");
195
196 NSMutableDictionary* query = [@{
197 (id)kSecClass : (id)kSecClassKey,
198 (id)kSecAttrAccessGroup : @"com.apple.security.ckks",
199 (id)kSecReturnAttributes: @YES,
200 (id)kSecAttrSynchronizable : (id)kCFBooleanFalse,
201 } mutableCopy];
202
203 OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
204 XCTAssertEqual(status, 0, @"status should be 0");
205
206 SFECKeyPair* newSigningKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
207
208 SFECKeyPair* newEncryptionKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
209
210 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
211
212 self.spiBlockExpectation = [self expectationWithDescription:@"updating bottle SPI should fire"];
213
214 //update bottle
215 [self.otControl handleIdentityChangeForSigningKey:newSigningKey
216 ForEncryptionKey:newEncryptionKey
217 ForPeerID:self.sosPeerID
218 reply:^(BOOL result, NSError* _Nullable error){
219 [self.spiBlockExpectation fulfill];
220 XCTAssertFalse(result, "result should be NO");
221 XCTAssertNotNil(error, "error should not be nil");
222 }];
223 [self waitForExpectationsWithTimeout:1.0 handler:nil];
224
225 }
226
227 -(void)testUpdatingMultipleBottlesForSamePeer
228 {
229 [self setUpRampRecordsInCloudKitWithFeatureOn];
230
231 [self startCKKSSubsystem];
232
233 __block NSData* localEntropy1 = nil;
234 __block NSString* localBottleID1 = nil;
235
236 self.spiBlockExpectation = [self expectationWithDescription:@"preflight SPI should fire"];
237
238 [self.otControl preflightBottledPeer:testContextID
239 dsid:testDSID
240 reply:^(NSData * _Nullable entropy, NSString * _Nullable bottleID, NSData * _Nullable signingPublicKey, NSError * _Nullable error) {
241 [self.spiBlockExpectation fulfill];
242 localEntropy1 = entropy;
243 localBottleID1 = bottleID;
244 XCTAssertNotNil(entropy, "entropy should not be nil");
245 XCTAssertNotNil(bottleID, "bottle id should not be nil");
246 XCTAssertNotNil(signingPublicKey, "signing pub key should not be nil");
247 XCTAssertNil(error, "error should be nil");
248 }];
249 [self waitForExpectationsWithTimeout:1.0 handler:nil];
250
251 NSMutableDictionary* recordDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:[[NSNumber alloc] initWithInt:1], OTCKRecordBottledPeerType, nil];
252
253 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
254
255 self.spiBlockExpectation = [self expectationWithDescription:@"launching bottle SPI should fire"];
256
257 [self.otControl launchBottledPeer:testContextID bottleID:localBottleID1 reply:^(NSError * _Nullable error) {
258 [self.spiBlockExpectation fulfill];
259 XCTAssertNil(error, "error should be nil");
260 }];
261
262 [self waitForExpectationsWithTimeout:1.0 handler:nil];
263
264 [self waitForCKModifications];
265 OCMVerifyAllWithDelay(self.mockDatabase, 8);
266
267 __block NSData* localEntropy2 = nil;
268 __block NSString* localBottleID2 = nil;
269
270 self.spiBlockExpectation = [self expectationWithDescription:@"preflight SPI should fire"];
271
272 [self.otControl preflightBottledPeer:testContextID
273 dsid:testDSID
274 reply:^(NSData * _Nullable entropy, NSString * _Nullable bottleID, NSData * _Nullable signingPublicKey, NSError * _Nullable error) {
275 [self.spiBlockExpectation fulfill];
276 localEntropy2 = entropy;
277 localBottleID2 = bottleID;
278 XCTAssertNotNil(entropy, "entropy should not be nil");
279 XCTAssertNotNil(bottleID, "bottle id should not be nil");
280 XCTAssertNotNil(signingPublicKey, "signing pub key should not be nil");
281 XCTAssertNil(error, "error should be nil");
282 }];
283 [self waitForExpectationsWithTimeout:1.0 handler:nil];
284
285 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
286
287 self.spiBlockExpectation = [self expectationWithDescription:@"launching bottle SPI should fire"];
288
289 [self.otControl launchBottledPeer:testContextID bottleID:localBottleID2 reply:^(NSError * _Nullable error) {
290 [self.spiBlockExpectation fulfill];
291 XCTAssertNil(error, "error should be nil");
292 }];
293
294 [self waitForCKModifications];
295
296 SFECKeyPair* newSigningKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
297
298 SFECKeyPair* newEncryptionKey = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]];
299
300 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
301 [self expectAddedCKModifyRecords:recordDictionary holdFetch:NO];
302
303 self.spiBlockExpectation = [self expectationWithDescription:@"updating bottle SPI should fire"];
304
305 //update bottle
306 [self.otControl handleIdentityChangeForSigningKey:newSigningKey
307 ForEncryptionKey:newEncryptionKey
308 ForPeerID:self.sosPeerID
309 reply:^(BOOL result, NSError* _Nullable error){
310 [self.spiBlockExpectation fulfill];
311 XCTAssertTrue(result, "result should be YES");
312 XCTAssertNil(error, "error should be nil");
313 }];
314 [self waitForExpectationsWithTimeout:1.0 handler:nil];
315
316 [self waitForCKModifications];
317 OCMVerifyAllWithDelay(self.mockDatabase, 8);
318 }
319
320
321 @end
322
323 #endif
324