3 extension OctagonPairingTests {
5 func assertSOSSuccess() {
6 XCTAssertNotNil(self.fcInitiator?.accountPrivateKey, "no accountPrivateKey in fcInitiator")
7 XCTAssertNotNil(self.fcAcceptor?.accountPrivateKey, "no accountPrivateKey in fcAcceptor")
8 XCTAssert(CFEqualSafe(self.fcInitiator.accountPrivateKey, self.fcAcceptor.accountPrivateKey), "no accountPrivateKey not same in both")
10 XCTAssert(SOSCircleHasPeer(self.circle, self.fcInitiator.peerInfo(), nil), "HasPeer 1")
11 // XCTAssert(SOSCircleHasPeer(self.circle, self.fcAcceptor.peerInfo(), nil), "HasPeer 2") <rdar://problem/54040068>
14 func tlkInPairingChannel(packet: Data) throws -> Bool {
15 let plist = try self.pairingPacketToPlist(packet: packet)
17 guard let arrayOfItems = (plist["d"] as? [[String: Any]]) else {
22 arrayOfItems.forEach { item in
23 guard let agrp = (item["agrp"] as? String) else {
26 guard let cls = (item["class"] as? String) else {
29 if cls == "inet" && agrp == "com.apple.security.ckks" {
37 self.startCKAccountStatusMock()
39 /*Setup acceptor first*/
41 self.getAcceptorInCircle()
43 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
45 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
47 clientStateMachine.startOctagonStateMachine()
48 initiator1Context.startOctagonStateMachine()
50 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
52 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
53 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
54 XCTAssertNil(error, "error should be nil")
55 XCTAssertTrue(epoch == 1, "epoch should be 1")
56 rpcEpochCallbacks.fulfill()
58 self.wait(for: [rpcEpochCallbacks], timeout: 10)
60 let signInCallback = self.expectation(description: "trigger sign in")
61 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
62 XCTAssertNil(error, "error should be nil")
63 signInCallback.fulfill()
65 self.wait(for: [signInCallback], timeout: 10)
67 /* now initiator's turn*/
68 /* calling prepare identity*/
69 let rpcInitiatorPrepareCallback = self.expectation(description: "rpcPrepare callback occurs")
77 initiator1Context.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
78 XCTAssertNil(error, "Should be no error calling 'prepare'")
79 XCTAssertNotNil(peerID, "Prepare should have returned a peerID")
80 XCTAssertNotNil(permanentInfo, "Prepare should have returned a permanentInfo")
81 XCTAssertNotNil(permanentInfoSig, "Prepare should have returned a permanentInfoSig")
82 XCTAssertNotNil(stableInfo, "Prepare should have returned a stableInfo")
83 XCTAssertNotNil(stableInfoSig, "Prepare should have returned a stableInfoSig")
87 pIS = permanentInfoSig!
91 rpcInitiatorPrepareCallback.fulfill()
94 self.wait(for: [rpcInitiatorPrepareCallback], timeout: 10)
96 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateInitiatorAwaitingVoucher, within: 10 * NSEC_PER_SEC)
99 let rpcVoucherCallback = self.expectation(description: "rpcVoucher callback occurs")
101 var v = Data(count: 0)
102 var vS = Data(count: 0)
104 clientStateMachine.rpcVoucher(self.cuttlefishContextForAcceptor, peerID: p, permanentInfo: pI, permanentInfoSig: pIS, stableInfo: sI, stableInfoSig: sIS) { voucher, voucherSig, error in
105 XCTAssertNotNil(v, "Prepare should have returned a voucher")
106 XCTAssertNotNil(vS, "Prepare should have returned a voucherSig")
107 XCTAssertNil(error, "error should be nil")
112 rpcVoucherCallback.fulfill()
114 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
117 self.wait(for: [rpcVoucherCallback], timeout: 10)
119 self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
122 let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs")
124 self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in
125 XCTAssertNil(error, "error should be nil")
126 rpcJoinCallbackOccurs.fulfill()
129 self.wait(for: [rpcJoinCallbackOccurs], timeout: 10)
130 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
132 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
134 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
135 self.assertConsidersSelfTrusted(context: self.cuttlefishContext)
136 self.verifyDatabaseMocks()
138 self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext)
139 self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext)
141 self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
144 func testJoinRetry() {
145 self.startCKAccountStatusMock()
147 /*Setup acceptor first*/
149 self.getAcceptorInCircle()
151 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
153 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
155 clientStateMachine.startOctagonStateMachine()
156 initiator1Context.startOctagonStateMachine()
158 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
160 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
161 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
162 XCTAssertNil(error, "error should be nil")
163 XCTAssertTrue(epoch == 1, "epoch should be 1")
164 rpcEpochCallbacks.fulfill()
166 self.wait(for: [rpcEpochCallbacks], timeout: 10)
168 let signInCallback = self.expectation(description: "trigger sign in")
169 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
170 XCTAssertNil(error, "error should be nil")
171 signInCallback.fulfill()
173 self.wait(for: [signInCallback], timeout: 10)
175 /* now initiator's turn*/
176 /* calling prepare identity*/
177 let rpcInitiatorPrepareCallback = self.expectation(description: "rpcPrepare callback occurs")
185 initiator1Context.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
186 XCTAssertNil(error, "Should be no error calling 'prepare'")
187 XCTAssertNotNil(peerID, "Prepare should have returned a peerID")
188 XCTAssertNotNil(permanentInfo, "Prepare should have returned a permanentInfo")
189 XCTAssertNotNil(permanentInfoSig, "Prepare should have returned a permanentInfoSig")
190 XCTAssertNotNil(stableInfo, "Prepare should have returned a stableInfo")
191 XCTAssertNotNil(stableInfoSig, "Prepare should have returned a stableInfoSig")
195 pIS = permanentInfoSig!
199 rpcInitiatorPrepareCallback.fulfill()
202 self.wait(for: [rpcInitiatorPrepareCallback], timeout: 10)
204 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateInitiatorAwaitingVoucher, within: 10 * NSEC_PER_SEC)
206 /* calling voucher */
207 let rpcVoucherCallback = self.expectation(description: "rpcVoucher callback occurs")
209 var v = Data(count: 0)
210 var vS = Data(count: 0)
212 clientStateMachine.rpcVoucher(self.cuttlefishContextForAcceptor, peerID: p, permanentInfo: pI, permanentInfoSig: pIS, stableInfo: sI, stableInfoSig: sIS) { voucher, voucherSig, error in
213 XCTAssertNotNil(v, "Prepare should have returned a voucher")
214 XCTAssertNotNil(vS, "Prepare should have returned a voucherSig")
215 XCTAssertNil(error, "error should be nil")
220 rpcVoucherCallback.fulfill()
222 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
225 self.wait(for: [rpcVoucherCallback], timeout: 10)
227 self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
230 let ckError = FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .transactionalFailure)
231 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
232 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
233 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
234 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
235 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
237 let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs")
239 self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in
240 XCTAssertNil(error, "error should be nil")
241 rpcJoinCallbackOccurs.fulfill()
244 self.wait(for: [rpcJoinCallbackOccurs], timeout: 64)
245 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
247 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
249 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
250 self.assertConsidersSelfTrusted(context: self.cuttlefishContext)
251 self.verifyDatabaseMocks()
253 self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext)
254 self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext)
256 self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
259 func testJoinRetryFail() {
260 self.startCKAccountStatusMock()
262 /*Setup acceptor first*/
264 self.getAcceptorInCircle()
266 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
268 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
270 clientStateMachine.startOctagonStateMachine()
271 initiator1Context.startOctagonStateMachine()
273 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
275 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
276 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
277 XCTAssertNil(error, "error should be nil")
278 XCTAssertTrue(epoch == 1, "epoch should be 1")
279 rpcEpochCallbacks.fulfill()
281 self.wait(for: [rpcEpochCallbacks], timeout: 10)
283 let signInCallback = self.expectation(description: "trigger sign in")
284 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
285 XCTAssertNil(error, "error should be nil")
286 signInCallback.fulfill()
288 self.wait(for: [signInCallback], timeout: 10)
290 /* now initiator's turn*/
291 /* calling prepare identity*/
292 let rpcInitiatorPrepareCallback = self.expectation(description: "rpcPrepare callback occurs")
300 initiator1Context.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
301 XCTAssertNil(error, "Should be no error calling 'prepare'")
302 XCTAssertNotNil(peerID, "Prepare should have returned a peerID")
303 XCTAssertNotNil(permanentInfo, "Prepare should have returned a permanentInfo")
304 XCTAssertNotNil(permanentInfoSig, "Prepare should have returned a permanentInfoSig")
305 XCTAssertNotNil(stableInfo, "Prepare should have returned a stableInfo")
306 XCTAssertNotNil(stableInfoSig, "Prepare should have returned a stableInfoSig")
310 pIS = permanentInfoSig!
314 rpcInitiatorPrepareCallback.fulfill()
317 self.wait(for: [rpcInitiatorPrepareCallback], timeout: 10)
319 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateInitiatorAwaitingVoucher, within: 10 * NSEC_PER_SEC)
321 /* calling voucher */
322 let rpcVoucherCallback = self.expectation(description: "rpcVoucher callback occurs")
324 var v = Data(count: 0)
325 var vS = Data(count: 0)
327 clientStateMachine.rpcVoucher(self.cuttlefishContextForAcceptor, peerID: p, permanentInfo: pI, permanentInfoSig: pIS, stableInfo: sI, stableInfoSig: sIS) { voucher, voucherSig, error in
328 XCTAssertNotNil(v, "Prepare should have returned a voucher")
329 XCTAssertNotNil(vS, "Prepare should have returned a voucherSig")
330 XCTAssertNil(error, "error should be nil")
335 rpcVoucherCallback.fulfill()
337 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
340 self.wait(for: [rpcVoucherCallback], timeout: 10)
342 self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
345 let ckError = FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .transactionalFailure)
346 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
347 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
348 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
349 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
350 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
351 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
352 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
353 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
354 self.fakeCuttlefishServer.nextJoinErrors.append(ckError)
356 let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs")
358 self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in
359 XCTAssertNotNil(error, "error should be set")
360 rpcJoinCallbackOccurs.fulfill()
362 self.wait(for: [rpcJoinCallbackOccurs], timeout: 35)
365 func testJoinWithCKKSConflict() {
366 self.startCKAccountStatusMock()
368 /*Setup acceptor first*/
370 self.getAcceptorInCircle()
372 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
374 self.silentFetchesAllowed = false
375 self.expectCKFetchAndRun {
376 self.putFakeKeyHierarchiesInCloudKit()
377 self.putFakeDeviceStatusesInCloudKit()
378 self.silentFetchesAllowed = true
381 clientStateMachine.startOctagonStateMachine()
382 self.cuttlefishContext.startOctagonStateMachine()
384 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
386 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
387 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
388 XCTAssertNil(error, "error should be nil")
389 XCTAssertTrue(epoch == 1, "epoch should be 1")
390 rpcEpochCallbacks.fulfill()
392 self.wait(for: [rpcEpochCallbacks], timeout: 10)
394 let signInCallback = self.expectation(description: "trigger sign in")
395 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
396 XCTAssertNil(error, "error should be nil")
397 signInCallback.fulfill()
399 self.wait(for: [signInCallback], timeout: 10)
401 /* now initiator's turn*/
402 /* calling prepare identity*/
403 let rpcInitiatorPrepareCallback = self.expectation(description: "rpcPrepare callback occurs")
411 self.cuttlefishContext.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
412 XCTAssertNil(error, "Should be no error calling 'prepare'")
413 XCTAssertNotNil(peerID, "Prepare should have returned a peerID")
414 XCTAssertNotNil(permanentInfo, "Prepare should have returned a permanentInfo")
415 XCTAssertNotNil(permanentInfoSig, "Prepare should have returned a permanentInfoSig")
416 XCTAssertNotNil(stableInfo, "Prepare should have returned a stableInfo")
417 XCTAssertNotNil(stableInfoSig, "Prepare should have returned a stableInfoSig")
421 pIS = permanentInfoSig!
425 rpcInitiatorPrepareCallback.fulfill()
428 self.wait(for: [rpcInitiatorPrepareCallback], timeout: 10)
430 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateInitiatorAwaitingVoucher, within: 10 * NSEC_PER_SEC)
432 /* calling voucher */
433 let rpcVoucherCallback = self.expectation(description: "rpcVoucher callback occurs")
435 var v = Data(count: 0)
436 var vS = Data(count: 0)
438 clientStateMachine.rpcVoucher(self.cuttlefishContextForAcceptor, peerID: p, permanentInfo: pI, permanentInfoSig: pIS, stableInfo: sI, stableInfoSig: sIS) { voucher, voucherSig, error in
439 XCTAssertNotNil(v, "Prepare should have returned a voucher")
440 XCTAssertNotNil(vS, "Prepare should have returned a voucherSig")
441 XCTAssertNil(error, "error should be nil")
446 rpcVoucherCallback.fulfill()
448 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
451 self.wait(for: [rpcVoucherCallback], timeout: 10)
453 self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
456 let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs")
458 self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in
459 XCTAssertNil(error, "error should be nil")
460 rpcJoinCallbackOccurs.fulfill()
463 self.wait(for: [rpcJoinCallbackOccurs], timeout: 10)
464 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
466 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
468 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
469 self.assertConsidersSelfTrusted(context: self.cuttlefishContext)
471 self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC)
472 self.verifyDatabaseMocks()
475 func testNextJoiningMessageInterface() {
476 self.startCKAccountStatusMock()
478 /*Setup acceptor first*/
479 self.getAcceptorInCircle()
481 let rpcEpochCallbackOccurs = self.expectation(description: "rpcEpoch callback occurs")
483 self.manager.rpcEpoch(with: self.acceptorPairingConfig) { epoch, error in
484 XCTAssertNil(error, "error should be nil")
485 XCTAssertEqual(epoch, 1, "epoch should be nil")
486 rpcEpochCallbackOccurs.fulfill()
488 self.wait(for: [rpcEpochCallbackOccurs], timeout: 10)
490 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
491 initiator1Context.startOctagonStateMachine()
493 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-1")
495 XCTAssertNotNil(acceptor, "acceptor should not be nil")
496 XCTAssertNotNil(initiator, "initiator should not be nil")
498 let signInCallback = self.expectation(description: "trigger sign in")
499 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
500 XCTAssertNil(error, "error should be nil")
501 signInCallback.fulfill()
503 self.wait(for: [signInCallback], timeout: 10)
505 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
507 let rpcSecondInitiatorJoiningMessageCallBack = self.expectation(description: "creating prepare message callback")
509 var permanentInfo = Data(count: 0)
510 var permanentInfoSig = Data(count: 0)
511 var stableInfo = Data(count: 0)
512 var stableInfoSig = Data(count: 0)
514 self.manager.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig) { pID, pI, pISig, sI, sISig, error in
515 XCTAssertNotNil(pID, "peer ID should not be nil")
516 XCTAssertNotNil(pI, "permanentInfo should not be nil")
517 XCTAssertNotNil(pISig, "permanentInfo Signature should not be nil")
518 XCTAssertNotNil(sI, "stable info should not be nil")
519 XCTAssertNotNil(sISig, "stable info signature should not be nil")
523 permanentInfoSig = pISig!
525 stableInfoSig = sISig!
526 XCTAssertNil(error, "error should be nil")
527 rpcSecondInitiatorJoiningMessageCallBack.fulfill()
529 self.wait(for: [rpcSecondInitiatorJoiningMessageCallBack], timeout: 10)
531 var voucher = Data(count: 0)
532 var voucherSig = Data(count: 0)
534 let voucherCallback = self.expectation(description: "creating voucher message callback")
535 self.manager.rpcVoucher(with: self.acceptorPairingConfig, peerID: peerID, permanentInfo: permanentInfo, permanentInfoSig: permanentInfoSig, stableInfo: stableInfo, stableInfoSig: stableInfoSig ) { v, vS, error in
536 XCTAssertNil(error, "error should be nil")
539 voucherCallback.fulfill()
541 self.wait(for: [voucherCallback], timeout: 10)
543 let rpcJoinCallback = self.expectation(description: "joining octagon callback")
544 self.manager.rpcJoin(with: self.initiatorPairingConfig, vouchData: voucher, vouchSig: voucherSig) { error in
545 XCTAssertNil(error, "error should be nil")
546 rpcJoinCallback.fulfill()
548 self.wait(for: [rpcJoinCallback], timeout: 10)
550 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
551 self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
552 self.assertConsidersSelfTrusted(context: self.cuttlefishContext)
553 self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor)
554 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
555 self.verifyDatabaseMocks()
558 func testEpochFetching() {
559 self.startCKAccountStatusMock()
561 /*Setup acceptor first*/
563 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
564 self.getAcceptorInCircle()
566 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
567 clientStateMachine.startOctagonStateMachine()
568 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
569 XCTAssertNil(error, "error should be nil")
570 XCTAssertTrue(epoch == 1, "epoch should be 1")
571 rpcEpochCallbacks.fulfill()
574 self.wait(for: [rpcEpochCallbacks], timeout: 10)
575 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorAwaitingIdentity] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorAwaitingIdentity'")
578 func testVoucherCreation() {
579 self.startCKAccountStatusMock()
581 /*Setup acceptor first*/
583 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
584 self.getAcceptorInCircle()
586 let rpcEpochCallbacks = self.expectation(description: "rpcEpoch callback occurs")
587 clientStateMachine.startOctagonStateMachine()
588 clientStateMachine.rpcEpoch(self.cuttlefishContextForAcceptor) { epoch, error in
589 XCTAssertNil(error, "error should be nil")
590 XCTAssertTrue(epoch == 1, "epoch should be 1")
591 rpcEpochCallbacks.fulfill()
594 self.wait(for: [rpcEpochCallbacks], timeout: 10)
595 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorAwaitingIdentity] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorAwaitingIdentity'")
597 let signInCallback = self.expectation(description: "trigger sign in")
598 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
599 XCTAssertNil(error, "error should be nil")
600 signInCallback.fulfill()
602 self.wait(for: [signInCallback], timeout: 10)
604 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateMachineNotStarted, within: 10 * NSEC_PER_SEC)
606 /* now initiator's turn*/
607 self.manager.startOctagonStateMachine(self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { _ in
610 /* calling prepare identity*/
611 let rpcInitiatorPrepareCallback = self.expectation(description: "rpcPrepare callback occurs")
619 self.cuttlefishContext.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
620 XCTAssertNil(error, "Should be no error calling 'prepare'")
621 XCTAssertNotNil(peerID, "Prepare should have returned a peerID")
622 XCTAssertNotNil(permanentInfo, "Prepare should have returned a permanentInfo")
623 XCTAssertNotNil(permanentInfoSig, "Prepare should have returned a permanentInfoSig")
624 XCTAssertNotNil(stableInfo, "Prepare should have returned a stableInfo")
625 XCTAssertNotNil(stableInfoSig, "Prepare should have returned a stableInfoSig")
629 pIS = permanentInfoSig!
633 rpcInitiatorPrepareCallback.fulfill()
636 self.wait(for: [rpcInitiatorPrepareCallback], timeout: 10)
638 self.assertEnters(context: self.cuttlefishContext, state: OctagonStateInitiatorAwaitingVoucher, within: 10 * NSEC_PER_SEC)
640 /* calling voucher */
641 let rpcVoucherCallback = self.expectation(description: "rpcVoucher callback occurs")
643 var v = Data(count: 0)
644 var vS = Data(count: 0)
646 clientStateMachine.rpcVoucher(self.cuttlefishContextForAcceptor, peerID: p, permanentInfo: pI, permanentInfoSig: pIS, stableInfo: sI, stableInfoSig: sIS) { voucher, voucherSig, error in
647 XCTAssertNotNil(v, "Prepare should have returned a voucher")
648 XCTAssertNotNil(vS, "Prepare should have returned a voucherSIg")
649 XCTAssertNil(error, "error should be nil")
654 rpcVoucherCallback.fulfill()
657 self.wait(for: [rpcVoucherCallback], timeout: 10)
658 XCTAssertEqual(0, (clientStateMachine.stateConditions[OctagonStateAcceptorDone] as! CKKSCondition).wait(10 * NSEC_PER_SEC), "State machine should enter 'OctagonStateAcceptorDone'")
661 func testPrepareTimeoutIfStateMachineUnstarted() {
662 self.startCKAccountStatusMock()
664 let rpcCallbackOccurs = self.expectation(description: "rpcPrepare callback occurs")
665 self.initiatorPairingConfig.timeout = Int64(2 * NSEC_PER_SEC)
667 self.cuttlefishContext.rpcPrepareIdentityAsApplicant(with: self.initiatorPairingConfig, epoch: 1) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in
668 XCTAssertNotNil(error, "Should be an error calling 'prepare'")
669 XCTAssertEqual(error?._domain, CKKSResultErrorDomain, "Error domain should be CKKSResultErrorDomain")
670 XCTAssertEqual(error?._code ?? -1, CKKSResultTimedOut, "Error result should be CKKSResultTimedOut")
672 XCTAssertNil(peerID, "Prepare should not have returned a peerID")
673 XCTAssertNil(permanentInfo, "Prepare should not have returned a permanentInfo")
674 XCTAssertNil(permanentInfoSig, "Prepare should not have returned a permanentInfoSig")
675 XCTAssertNil(stableInfo, "Prepare should not have returned a stableInfo")
676 XCTAssertNil(stableInfoSig, "Prepare should not have returned a stableInfoSig")
678 rpcCallbackOccurs.fulfill()
681 self.wait(for: [rpcCallbackOccurs], timeout: 10)
684 func testProximitySetupUsingCliqueOctagonAndSOS() {
685 self.startCKAccountStatusMock()
687 OctagonSetPlatformSupportsSOS(true)
688 OctagonSetIsEnabled(true)
690 self.getAcceptorInCircle()
692 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
694 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
696 clientStateMachine.startOctagonStateMachine()
697 initiator1Context.startOctagonStateMachine()
699 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
701 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
703 XCTAssertNotNil(acceptor, "acceptor should not be nil")
704 XCTAssertNotNil(initiator, "initiator should not be nil")
706 let signInCallback = self.expectation(description: "trigger sign in")
707 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
708 XCTAssertNil(error, "error should be nil")
709 signInCallback.fulfill()
711 self.wait(for: [signInCallback], timeout: 10)
713 /* INITIATOR FIRST RTT JOINING MESSAGE*/
714 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
716 /* ACCEPTOR FIRST RTT EPOCH*/
717 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
719 /* INITIATOR SECOND RTT PREPARE*/
720 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
722 /* ACCEPTOR SECOND RTT */
723 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
725 /* INITIATOR THIRD STEP*/
726 let initiatorThirdPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet")
728 /* ACCEPTOR THIRD STEP */
729 let acceptorThirdPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorThirdPacket, reason: "acceptor third packet")
730 XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorThirdPacket), "pairing channel should NOT transport TLKs for SOS+Octagon")
732 /* INITIATOR FOURTH STEP*/
733 self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorThirdPacket, reason: "final packet receipt")
735 // pairing completes here
737 assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
739 clientStateMachine.notifyContainerChange()
741 // Initiator should join!
742 self.assertEnters(context: initiator1Context, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
743 self.assertConsidersSelfTrusted(context: initiator1Context)
744 self.verifyDatabaseMocks()
746 let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs")
747 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in
748 XCTAssertNotNil(dump, "dump should not be nil")
749 let egoSelf = dump!["self"] as? [String: AnyObject]
750 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
751 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
752 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
753 let included = dynamicInfo!["included"] as? [String]
754 XCTAssertNotNil(included, "included should not be nil")
755 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
757 initiatorDumpCallback.fulfill()
759 self.wait(for: [initiatorDumpCallback], timeout: 10)
761 let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs")
762 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in
763 XCTAssertNotNil(dump, "dump should not be nil")
764 let egoSelf = dump!["self"] as? [String: AnyObject]
765 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
766 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
767 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
768 let included = dynamicInfo!["included"] as? [String]
769 XCTAssertNotNil(included, "included should not be nil")
770 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
771 acceptorDumpCallback.fulfill()
773 self.wait(for: [acceptorDumpCallback], timeout: 10)
775 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
777 self.assertSOSSuccess()
780 func testProximitySetupUsingCliqueOctagonOnly() throws {
781 OctagonSetPlatformSupportsSOS(false)
782 OctagonSetIsEnabled(true)
783 self.startCKAccountStatusMock()
785 self.getAcceptorInCircle()
787 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
789 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
791 clientStateMachine.startOctagonStateMachine()
792 initiator1Context.startOctagonStateMachine()
794 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
796 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
798 XCTAssertNotNil(acceptor, "acceptor should not be nil")
799 XCTAssertNotNil(initiator, "initiator should not be nil")
801 let signInCallback = self.expectation(description: "trigger sign in")
802 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
803 XCTAssertNil(error, "error should be nil")
804 signInCallback.fulfill()
806 self.wait(for: [signInCallback], timeout: 10)
808 /* INITIATOR FIRST RTT JOINING MESSAGE*/
809 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
811 /* ACCEPTOR FIRST RTT EPOCH*/
812 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
814 /* INITIATOR SECOND RTT PREPARE*/
815 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
817 /* ACCEPTOR SECOND RTT */
818 let acceptorVoucherPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "acceptor third packet")
820 // the tlks are in the 3rd roundtrip, but lets check here too
821 XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorVoucherPacket), "pairing channel should not transport TLKs for octagon")
823 /* INITIATOR THIRD STEP*/
824 self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorVoucherPacket, reason: "final packet receipt")
826 assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
828 clientStateMachine.notifyContainerChange()
830 // Initiator should join!
831 self.assertEnters(context: initiator1Context, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
832 self.assertConsidersSelfTrusted(context: initiator1Context)
833 self.verifyDatabaseMocks()
835 let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs")
836 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in
837 XCTAssertNotNil(dump, "dump should not be nil")
838 let egoSelf = dump!["self"] as? [String: AnyObject]
839 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
840 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
841 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
842 let included = dynamicInfo!["included"] as? [String]
843 XCTAssertNotNil(included, "included should not be nil")
844 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
846 initiatorDumpCallback.fulfill()
848 self.wait(for: [initiatorDumpCallback], timeout: 10)
850 let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs")
851 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in
852 XCTAssertNotNil(dump, "dump should not be nil")
853 let egoSelf = dump!["self"] as? [String: AnyObject]
854 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
855 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
856 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
857 let included = dynamicInfo!["included"] as? [String]
858 XCTAssertNotNil(included, "included should not be nil")
859 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
860 acceptorDumpCallback.fulfill()
862 self.wait(for: [acceptorDumpCallback], timeout: 10)
864 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
867 func testProximitySetupUsingCliqueSOSOnly() {
868 OctagonSetPlatformSupportsSOS(true)
869 OctagonSetIsEnabled(false)
870 self.startCKAccountStatusMock()
872 self.getAcceptorInCircle()
874 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
876 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
878 clientStateMachine.startOctagonStateMachine()
879 initiator1Context.startOctagonStateMachine()
881 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
883 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1",
884 initiatorContextID: OTDefaultContext,
885 acceptorContextID: self.contextForAcceptor,
886 initiatorUniqueID: self.initiatorName,
887 acceptorUniqueID: "acceptor-2")
889 XCTAssertNotNil(acceptor, "acceptor should not be nil")
890 XCTAssertNotNil(initiator, "initiator should not be nil")
892 let signInCallback = self.expectation(description: "trigger sign in")
893 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
894 XCTAssertNil(error, "error should be nil")
895 signInCallback.fulfill()
897 self.wait(for: [signInCallback], timeout: 10)
899 /* INITIATOR FIRST RTT JOINING MESSAGE*/
900 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
902 /* ACCEPTOR FIRST RTT EPOCH*/
903 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
905 /* INITIATOR SECOND RTT PREPARE*/
906 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
908 /* ACCEPTOR SECOND RTT */
909 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
911 // the tlks are in the 3rd roundtrip, but lets check here too
912 XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorVoucherPacket), "pairing channel should transport TLKs for SOS not 2nd step though")
914 /* INITIATOR THIRD STEP*/
915 let initiatorThirdPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet")
917 /* ACCEPTOR THIRD STEP */
918 let acceptorThirdPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorThirdPacket, reason: "acceptor third packet")
920 XCTAssertTrue(try self.tlkInPairingChannel(packet: acceptorThirdPacket), "pairing channel should transport TLKs for SOS")
922 /* INITIATOR FORTH STEP*/
923 self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorThirdPacket, reason: "final packet receipt")
925 self.assertSOSSuccess()
928 func testProximitySetupOctagonAndSOSWithSOSFailure() {
929 //ensure Octagon protocol continues even if SOS fails in some way.
930 OctagonSetPlatformSupportsSOS(true)
931 OctagonSetIsEnabled(true)
932 self.startCKAccountStatusMock()
934 self.getAcceptorInCircle()
936 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
938 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
940 clientStateMachine.startOctagonStateMachine()
941 initiator1Context.startOctagonStateMachine()
943 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
945 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
947 XCTAssertNotNil(acceptor, "acceptor should not be nil")
948 XCTAssertNotNil(initiator, "initiator should not be nil")
950 initiator.setSOSMessageFailForTesting(true)
951 acceptor.setSOSMessageFailForTesting(true)
953 let signInCallback = self.expectation(description: "trigger sign in")
954 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
955 XCTAssertNil(error, "error should be nil")
956 signInCallback.fulfill()
958 self.wait(for: [signInCallback], timeout: 10)
960 /* INITIATOR FIRST RTT JOINING MESSAGE*/
961 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
963 /* ACCEPTOR FIRST RTT EPOCH*/
964 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
966 /* INITIATOR SECOND RTT PREPARE*/
967 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
969 /* ACCEPTOR SECOND RTT */
970 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
972 /* INITIATOR THIRD STEP*/
973 _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet")
975 assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
977 clientStateMachine.notifyContainerChange()
979 // Initiator should join!
980 self.assertEnters(context: initiator1Context, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
981 self.assertConsidersSelfTrusted(context: initiator1Context)
982 self.verifyDatabaseMocks()
984 let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs")
985 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in
986 XCTAssertNotNil(dump, "dump should not be nil")
987 let egoSelf = dump!["self"] as? [String: AnyObject]
988 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
989 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
990 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
991 let included = dynamicInfo!["included"] as? [String]
992 XCTAssertNotNil(included, "included should not be nil")
993 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
995 initiatorDumpCallback.fulfill()
997 self.wait(for: [initiatorDumpCallback], timeout: 10)
999 let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs")
1000 self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in
1001 XCTAssertNotNil(dump, "dump should not be nil")
1002 let egoSelf = dump!["self"] as? [String: AnyObject]
1003 XCTAssertNotNil(egoSelf, "egoSelf should not be nil")
1004 let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject]
1005 XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil")
1006 let included = dynamicInfo!["included"] as? [String]
1007 XCTAssertNotNil(included, "included should not be nil")
1008 XCTAssertEqual(included!.count, 2, "should be 2 peer ids")
1009 acceptorDumpCallback.fulfill()
1011 self.wait(for: [acceptorDumpCallback], timeout: 10)
1013 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles")
1016 func testProximitySetupOctagonAndSOSWithOcatagonInitiatorMessage1Failure() {
1017 //ensure Octagon protocol halts if enabled and encounters a failure
1018 OctagonSetPlatformSupportsSOS(true)
1019 OctagonSetIsEnabled(true)
1020 self.startCKAccountStatusMock()
1022 self.getAcceptorInCircle()
1024 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1026 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1028 clientStateMachine.startOctagonStateMachine()
1029 initiator1Context.startOctagonStateMachine()
1031 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1033 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1035 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1036 XCTAssertNotNil(initiator, "initiator should not be nil")
1038 initiator.setOctagonMessageFailForTesting(true)
1040 let signInCallback = self.expectation(description: "trigger sign in")
1041 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1042 XCTAssertNil(error, "error should be nil")
1043 signInCallback.fulfill()
1045 self.wait(for: [signInCallback], timeout: 10)
1047 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1048 self.sendPairingExpectingCompletion(channel: initiator, packet: nil, reason: "error on first message")
1051 func testProximitySetupOctagonAndSOSWithOctagonAcceptorMessage1Failure() {
1052 //ensure Octagon protocol continues even if SOS fails in some way.
1053 OctagonSetPlatformSupportsSOS(true)
1054 OctagonSetIsEnabled(true)
1055 self.startCKAccountStatusMock()
1057 self.getAcceptorInCircle()
1059 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1061 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1063 clientStateMachine.startOctagonStateMachine()
1064 initiator1Context.startOctagonStateMachine()
1066 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1068 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1070 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1071 XCTAssertNotNil(initiator, "initiator should not be nil")
1073 let signInCallback = self.expectation(description: "trigger sign in")
1074 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1075 XCTAssertNil(error, "error should be nil")
1076 signInCallback.fulfill()
1078 self.wait(for: [signInCallback], timeout: 10)
1080 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1081 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1083 acceptor.setOctagonMessageFailForTesting(true)
1085 /* ACCEPTOR FIRST RTT EPOCH*/
1086 let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs")
1088 acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in
1089 XCTAssertNil(error, "should be no error")
1090 XCTAssertTrue(complete, "should be True")
1091 XCTAssertNil(packet, "packet should be nil")
1092 firstAcceptorCallback.fulfill()
1094 self.wait(for: [firstAcceptorCallback], timeout: 10)
1097 func testProximitySetupOctagonAndSOSWithOctagonInitiatorMessage2Failure() {
1098 OctagonSetPlatformSupportsSOS(true)
1099 OctagonSetIsEnabled(true)
1100 self.startCKAccountStatusMock()
1102 self.getAcceptorInCircle()
1104 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1106 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1108 clientStateMachine.startOctagonStateMachine()
1109 initiator1Context.startOctagonStateMachine()
1111 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1113 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1115 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1116 XCTAssertNotNil(initiator, "initiator should not be nil")
1118 let signInCallback = self.expectation(description: "trigger sign in")
1119 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1120 XCTAssertNil(error, "error should be nil")
1121 signInCallback.fulfill()
1123 self.wait(for: [signInCallback], timeout: 10)
1125 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1126 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1128 /* ACCEPTOR FIRST RTT EPOCH*/
1129 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
1131 /* INITIATOR SECOND RTT PREPARE*/
1132 let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs")
1134 //set up initiator's message 2 to fail
1135 initiator.setOctagonMessageFailForTesting(true)
1137 initiator.exchangePacket(acceptorEpochPacket) { complete, packet, error in
1138 XCTAssertNil(error, "should be no error")
1139 XCTAssertTrue(complete, "should be true")
1140 XCTAssertNil(packet, "packet should not be nil")
1141 secondInitiatorCallback.fulfill()
1144 self.wait(for: [secondInitiatorCallback], timeout: 10)
1147 func testProximitySetupOctagonAndSOSWithOctagonAcceptorMessage2Failure() {
1148 OctagonSetPlatformSupportsSOS(true)
1149 OctagonSetIsEnabled(true)
1150 self.startCKAccountStatusMock()
1152 self.getAcceptorInCircle()
1154 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1156 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1158 clientStateMachine.startOctagonStateMachine()
1159 initiator1Context.startOctagonStateMachine()
1161 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1163 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1165 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1166 XCTAssertNotNil(initiator, "initiator should not be nil")
1168 let signInCallback = self.expectation(description: "trigger sign in")
1169 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1170 XCTAssertNil(error, "error should be nil")
1171 signInCallback.fulfill()
1173 self.wait(for: [signInCallback], timeout: 10)
1175 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1176 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1178 /* ACCEPTOR FIRST RTT EPOCH*/
1179 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
1181 /* INITIATOR SECOND RTT PREPARE*/
1182 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
1184 /* ACCEPTOR SECOND RTT */
1185 let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs")
1187 acceptor.setOctagonMessageFailForTesting(true)
1189 acceptor.exchangePacket(initiatorPreparedIdentityPacket) { complete, packet, error in
1190 XCTAssertNil(error, "should be no error")
1191 XCTAssertTrue(complete, "should be true")
1192 XCTAssertNil(packet, "packet should be nil")
1193 SecondAcceptorCallback.fulfill()
1195 self.wait(for: [SecondAcceptorCallback], timeout: 10)
1198 func testProximitySetupOctagonAndSOSWithOctagonInitiatorMessage3Failure() {
1199 OctagonSetPlatformSupportsSOS(true)
1200 OctagonSetIsEnabled(true)
1201 self.startCKAccountStatusMock()
1203 self.getAcceptorInCircle()
1205 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1207 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1209 clientStateMachine.startOctagonStateMachine()
1210 initiator1Context.startOctagonStateMachine()
1212 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1214 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1216 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1217 XCTAssertNotNil(initiator, "initiator should not be nil")
1219 let signInCallback = self.expectation(description: "trigger sign in")
1220 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1221 XCTAssertNil(error, "error should be nil")
1222 signInCallback.fulfill()
1224 self.wait(for: [signInCallback], timeout: 10)
1226 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1227 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1229 /* ACCEPTOR FIRST RTT EPOCH*/
1230 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
1232 /* INITIATOR SECOND RTT PREPARE*/
1233 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
1235 /* ACCEPTOR SECOND RTT */
1236 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
1238 /* INITIATOR THIRD STEP*/
1239 let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs")
1241 initiator.setOctagonMessageFailForTesting(true)
1243 initiator.exchangePacket(acceptorVoucherPacket) { complete, packet, error in
1244 XCTAssertNil(error, "should be no error")
1245 XCTAssertTrue(complete, "should be true")
1246 XCTAssertNil(packet, "packet should be nil")
1247 thirdInitiatorCallback.fulfill()
1249 self.wait(for: [thirdInitiatorCallback], timeout: 10)
1252 func circleAndSOS() throws {
1253 let peerInfoAcceptor: SOSPeerInfoRef = SOSFullPeerInfoGetPeerInfo(self.fcAcceptor.fullPeerInfo)
1254 let encryptionKeyAcceptor = _SFECKeyPair.init(secKey: self.fcAcceptor.octagonEncryptionKey)
1255 let signingKeyAcceptor = _SFECKeyPair.init(secKey: self.fcAcceptor.octagonSigningKey)
1256 let peerIDAcceptor: NSString = (SOSPeerInfoGetPeerID(peerInfoAcceptor) .takeUnretainedValue() as NSString)
1257 let AcceptorSOSPeer = CKKSSOSSelfPeer(sosPeerID: peerIDAcceptor as String,
1258 encryptionKey: encryptionKeyAcceptor,
1259 signingKey: signingKeyAcceptor,
1260 viewList: self.managedViewList())
1262 self.mockSOSAdapter.trustedPeers.add(AcceptorSOSPeer)
1263 self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle)
1265 let acceptor = self.manager.context(forContainerName: OTCKContainerName,
1266 contextID: self.contextForAcceptor,
1267 sosAdapter: self.mockSOSAdapter,
1268 authKitAdapter: self.mockAuthKit2,
1269 lockStateTracker: self.lockStateTracker,
1270 accountStateTracker: self.accountStateTracker,
1271 deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)"))
1273 acceptor.startOctagonStateMachine()
1275 let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs")
1276 acceptor.rpcResetAndEstablish(.testGenerated) { resetError in
1277 XCTAssertNil(resetError, "Should be no error calling resetAndEstablish")
1278 resetAndEstablishExpectation.fulfill()
1281 self.wait(for: [resetAndEstablishExpectation], timeout: 10)
1282 self.assertEnters(context: acceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
1284 self.assertConsidersSelfTrusted(context: acceptor)
1285 XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 1, "should be 1 bottles")
1288 func testProximitySetupUsingCliqueAcceptorResolvesVersionToSOSOnly() {
1289 self.startCKAccountStatusMock()
1291 OctagonSetPlatformSupportsSOS(true)
1292 OctagonSetIsEnabled(true)
1294 let newSOSPeer = createSOSPeer(peerID: "sos-peer-id")
1295 self.mockSOSAdapter.selfPeer = newSOSPeer
1296 self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle)
1297 self.mockSOSAdapter.trustedPeers.add(newSOSPeer)
1299 self.getAcceptorInCircle()
1301 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1303 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1305 clientStateMachine.startOctagonStateMachine()
1306 initiator1Context.startOctagonStateMachine()
1308 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1310 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1312 acceptor.setSessionSupportsOctagonForTesting(false)
1314 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1315 XCTAssertNotNil(initiator, "initiator should not be nil")
1317 let signInCallback = self.expectation(description: "trigger sign in")
1318 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1319 XCTAssertNil(error, "error should be nil")
1320 signInCallback.fulfill()
1322 self.wait(for: [signInCallback], timeout: 10)
1324 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1325 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1327 /* ACCEPTOR FIRST RTT EPOCH*/
1328 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
1330 /* INITIATOR SECOND RTT PREPARE*/
1331 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
1333 /* ACCEPTOR SECOND RTT */
1334 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
1336 /* INITIATOR THIRD STEP*/
1337 _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet")
1339 need to fix attempting sos upgrade in the tests when pairing/piggybacking and then kicking off an upgrade
1340 let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1342 self.assertEnters(context: initiatorContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
1343 self.assertConsidersSelfTrusted(context: initiatorContext)
1347 func testProximitySetupUsingCliqueInitiatorResolvesVersionToSOSOnly() {
1348 self.startCKAccountStatusMock()
1350 OctagonSetPlatformSupportsSOS(true)
1351 OctagonSetIsEnabled(true)
1353 self.getAcceptorInCircle()
1355 let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1357 let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName)
1359 clientStateMachine.startOctagonStateMachine()
1360 initiator1Context.startOctagonStateMachine()
1362 self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
1364 let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2")
1366 initiator.setSessionSupportsOctagonForTesting(false)
1368 XCTAssertNotNil(acceptor, "acceptor should not be nil")
1369 XCTAssertNotNil(initiator, "initiator should not be nil")
1371 let signInCallback = self.expectation(description: "trigger sign in")
1372 self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in
1373 XCTAssertNil(error, "error should be nil")
1374 signInCallback.fulfill()
1376 self.wait(for: [signInCallback], timeout: 10)
1378 /* INITIATOR FIRST RTT JOINING MESSAGE*/
1379 let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation")
1381 /* ACCEPTOR FIRST RTT EPOCH*/
1382 let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return")
1384 /* INITIATOR SECOND RTT PREPARE*/
1385 let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity")
1387 /* ACCEPTOR SECOND RTT */
1388 let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return")
1390 /* INITIATOR THIRD STEP*/
1391 _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet")
1394 need to fix attempting sos upgrade in the tests when pairing/piggybacking and then kicking off an upgrade
1395 let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext)
1397 self.assertEnters(context: initiatorContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
1398 self.assertConsidersSelfTrusted(context: initiatorContext)