]> git.saurik.com Git - apple/security.git/blob - KeychainCircle/Tests/KCTLKRequestTest.m
Security-59754.80.3.tar.gz
[apple/security.git] / KeychainCircle / Tests / KCTLKRequestTest.m
1 #import <XCTest/XCTest.h>
2
3 #import <Foundation/Foundation.h>
4
5 #import <KeychainCircle/KCJoiningSession.h>
6 #import <KeychainCircle/KCAccountKCCircleDelegate.h>
7 #import <KeychainCircle/KCError.h>
8 #import <KeychainCircle/KCJoiningMessages.h>
9 #import <KeychainCircle/NSError+KCCreationHelpers.h>
10 #import <KeychainCircle/KCAESGCMDuplexSession.h>
11
12 #include <Security/SecBase.h>
13 #include "keychain/SecureObjectSync/SOSFullPeerInfo.h"
14 #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
15
16 #include <CommonCrypto/CommonRandomSPI.h>
17
18 static NSData* createTlkRequestMessage (KCAESGCMDuplexSession* aesSession) {
19 char someData[] = {1,2,3,4,5,6};
20 NSError* error = NULL;
21 NSData* rndPadding = [NSData dataWithBytes:(void*)someData length:sizeof(someData)];
22 KCJoiningMessage* tlkRequestMessage = [KCJoiningMessage messageWithType: kTLKRequest data:rndPadding error:&error];
23 return [tlkRequestMessage der];
24 }
25
26 @interface KCJoiningRequestTestDelegate : NSObject <KCJoiningRequestSecretDelegate, KCJoiningRequestCircleDelegate>
27 @property (readwrite) NSString* sharedSecret;
28
29 @property (readonly) NSString* accountCode;
30 @property (readonly) NSData* circleJoinData;
31
32 @property (readwrite) NSString* incorrectSecret;
33 @property (readwrite) int incorrectTries;
34
35
36 + (id) requestDelegateWithSecret:(NSString*) secret;
37 - (id) init NS_UNAVAILABLE;
38 - (id) initWithSecret: (NSString*) secret
39 incorrectSecret: (NSString*) wrongSecret
40 incorrectTries: (int) retries NS_DESIGNATED_INITIALIZER;
41 - (NSString*) secret;
42 - (NSString*) verificationFailed: (bool) codeChanged;
43 - (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error;
44 - (bool) processCircleJoinData: (NSData*) circleJoinData version:(PiggyBackProtocolVersion)version error: (NSError**)error ;
45 - (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error;
46
47 @end
48
49 @implementation KCJoiningRequestTestDelegate
50
51 + (id) requestDelegateWithSecret:(NSString*) secret {
52 return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret
53 incorrectSecret:@""
54 incorrectTries:0];
55 }
56
57 + (id) requestDelegateWithSecret:(NSString*) secret
58 incorrectSecret:(NSString*) wrongSecret
59 incorrectTries:(int) retries {
60 return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret
61 incorrectSecret:wrongSecret
62 incorrectTries:retries];
63 }
64
65
66 - (id) initWithSecret: (NSString*) secret
67 incorrectSecret: (NSString*) incorrectSecret
68 incorrectTries: (int) retries {
69 if ( self = [super init] ) {
70 self.sharedSecret = secret;
71 self.incorrectSecret = incorrectSecret;
72 self.incorrectTries = retries;
73 }
74 return self;
75 }
76
77 - (NSString*) nextSecret {
78 if (self.incorrectTries > 0) {
79 self.incorrectTries -= 1;
80 return self.incorrectSecret;
81 }
82 return self.sharedSecret;
83 }
84
85 - (NSString*) secret {
86 return [self nextSecret];
87 }
88
89 - (NSString*) verificationFailed: (bool) codeChanged {
90 return [self nextSecret];
91 }
92
93 - (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error {
94 return NULL;
95 }
96
97 - (bool) processCircleJoinData: (NSData*) circleJoinData version:(PiggyBackProtocolVersion)version error: (NSError**)error {
98 self->_circleJoinData = circleJoinData;
99 return true;
100 }
101
102 - (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error {
103 self->_accountCode = accountCode;
104 return true;
105 }
106
107 @end
108
109 @interface KCJoiningAcceptTestDelegate : NSObject <KCJoiningAcceptSecretDelegate, KCJoiningAcceptCircleDelegate>
110 @property (readonly) NSArray<NSString*>* secrets;
111 @property (readwrite) NSUInteger currentSecret;
112 @property (readwrite) int retriesLeft;
113 @property (readwrite) int retriesPerSecret;
114
115 @property (readonly) NSString* codeToUse;
116 @property (readonly) NSData* circleJoinData;
117 @property (readonly) SOSPeerInfoRef peerInfo;
118
119 + (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code;
120 + (id) acceptDelegateWithSecrets: (NSArray<NSString*>*) secrets retries: (int) retries code: (NSString*) code;
121 - (id) initWithSecrets: (NSArray<NSString*>*) secrets retries: (int) retries code: (NSString*) code NS_DESIGNATED_INITIALIZER;
122
123 - (NSString*) secret;
124 - (NSString*) accountCode;
125
126 - (KCRetryOrNot) verificationFailed: (NSError**) error;
127 - (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer
128 error: (NSError**) error;
129
130 - (id) init NS_UNAVAILABLE;
131
132 @end
133
134 @implementation KCJoiningAcceptTestDelegate
135
136 + (id) acceptDelegateWithSecrets: (NSArray<NSString*>*) secrets retries: (int) retries code: (NSString*) code {
137 return [[KCJoiningAcceptTestDelegate alloc] initWithSecrets:secrets retries:retries code:code];
138
139 }
140
141 + (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code {
142 return [[KCJoiningAcceptTestDelegate alloc] initWithSecret:secret code:code];
143 }
144
145 - (id) initWithSecret: (NSString*) secret code: (NSString*) code {
146 return [self initWithSecrets:@[secret] retries:3 code:code];
147 }
148
149 - (id) initWithSecrets: (NSArray<NSString*>*) secrets retries: (int) retries code: (NSString*) code {
150 if ((self = [super init])) {
151 self->_secrets = secrets;
152 self.currentSecret = 0;
153 self->_retriesPerSecret = retries;
154 self->_retriesLeft = self.retriesPerSecret;
155
156 self->_codeToUse = code;
157
158 uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
159 self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ];
160 }
161 return self;
162 }
163
164 - (KCRetryOrNot) advanceSecret {
165 if (self.retriesLeft == 0) {
166 self.currentSecret += 1;
167 if (self.currentSecret >= [self.secrets count]) {
168 self.currentSecret = [self.secrets count] - 1;
169 }
170 self.retriesLeft = self.retriesPerSecret;
171 return kKCRetryWithNewChallenge;
172 } else {
173 self.retriesLeft -= 1;
174 return kKCRetryWithSameChallenge;
175 }
176 }
177
178 - (NSString*) secret {
179 return self.secrets[self.currentSecret];
180 }
181 - (NSString*) accountCode {
182 return self.codeToUse;
183 }
184
185 - (KCRetryOrNot) verificationFailed: (NSError**) error {
186 return [self advanceSecret];
187 }
188
189 - (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer
190 error: (NSError**) error {
191 uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
192
193 self->_peerInfo = peer;
194 return [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ];
195 }
196
197 -(NSData*) circleGetInitialSyncViews:(SOSInitialSyncFlags)flags error:(NSError**) error{
198 char testData[] = {0,1,2,3,4,5,6,7,8,9};
199 return [NSData dataWithBytes:testData length:sizeof(testData)];
200 //return [[KCJoiningAcceptAccountCircleDelegate delegate] circleGetInitialSyncViews:flags error:error]; //Need security entitlements!
201 }
202
203 @end
204
205 @interface KCTLKRequestTest : XCTestCase
206
207 @end
208
209 @implementation KCTLKRequestTest
210
211 - (void)setUp {
212 [super setUp];
213 // Put setup code here. This method is called before the invocation of each test method in the class.
214 }
215
216 - (void)tearDown {
217 // Put teardown code here. This method is called after the invocation of each test method in the class.
218 [super tearDown];
219 }
220
221 - (void)testTLKRequest {
222 NSError* error = nil;
223
224 NSString* secret = @"123456";
225 NSString* code = @"987654";
226
227 uint64_t dsid = 0x1234567887654321;
228
229 KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret];
230 KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate
231 dsid:dsid
232 rng:ccDRBGGetRngState()
233 error:&error];
234
235 NSData* initialMessage = [requestSession initialMessage: &error];
236
237 XCTAssertNotNil(initialMessage, @"No initial message");
238 XCTAssertNil(error, @"Got error %@", error);
239
240 KCJoiningAcceptTestDelegate* acceptDelegate = [KCJoiningAcceptTestDelegate acceptDelegateWithSecret:secret code:code];
241 KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate
242 circleDelegate:acceptDelegate
243 dsid:dsid
244 rng:ccDRBGGetRngState()
245 error:&error];
246
247 error = nil;
248 NSData* challenge = [acceptSession processMessage: initialMessage error: &error];
249
250 XCTAssertNotNil(challenge, @"No initial message");
251 XCTAssertNil(error, @"Got error %@", error);
252
253 error = nil;
254 NSData* response = [requestSession processMessage: challenge error: &error];
255
256 XCTAssertNotNil(response, @"No response message");
257 XCTAssertNil(error, @"Got error %@", error);
258
259 error = nil;
260 NSData* verification = [acceptSession processMessage: response error: &error];
261
262 XCTAssertNotNil(verification, @"No verification message");
263 XCTAssertNil(error, @"Got error %@", error);
264
265 error = nil;
266 NSData* doneMessage = [requestSession processMessage: verification error: &error];
267
268 XCTAssertNotNil(doneMessage, @"No response message");
269 XCTAssertNil(error, @"Got error %@", error);
270
271 XCTAssertTrue([requestSession isDone], @"SecretSession done");
272 XCTAssertFalse([acceptSession isDone], @"Unexpected accept session done");
273
274 KCAESGCMDuplexSession* aesSession = [requestSession session];
275 requestSession = nil;
276
277 KCJoiningRequestCircleSession* requestSecretSession = [KCJoiningRequestCircleSession sessionWithCircleDelegate:requestDelegate session:aesSession error:&error];
278
279 XCTAssertNotNil(requestSecretSession, @"No request secret session");
280 XCTAssertNil(error, @"Got error %@", error);
281
282 NSData* tlkRequestMessage = createTlkRequestMessage(aesSession);
283 XCTAssertNotNil(tlkRequestMessage, @"No TLKRequest message");
284
285 NSData* tlkMessage = [acceptSession processMessage:tlkRequestMessage error:&error];
286 XCTAssertNotNil(tlkMessage, @"No tlkData message");
287 XCTAssertNil(error, @"Got error %@", error);
288
289 KCJoiningMessage* receivedKCJoinMessage = [KCJoiningMessage messageWithDER:tlkMessage error:&error];
290 XCTAssertNotNil(receivedKCJoinMessage, @"No receivedKCJoinMessage message");
291 XCTAssertNil(error, @"Got error %@", error);
292
293 NSData* tlkDecryptedData = [aesSession decryptAndVerify:receivedKCJoinMessage.firstData error:&error];
294 XCTAssertNotNil(tlkDecryptedData, @"No tlkDecryptedData message");
295 XCTAssertNil(error, @"Got error %@", error);
296
297 //check for tlkc content
298 NSData* initialSync = [acceptDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKs error:&error];
299 XCTAssertNotNil(initialSync, @"No initialSync data");
300 XCTAssertNil(error, @"Got error %@", error);
301
302 XCTAssertEqualObjects(initialSync, tlkDecryptedData, @"TLK data is different.");
303 }
304 @end