]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/otr/otr-40-edgecases.c
Security-58286.60.28.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / otr / otr-40-edgecases.c
1 /*
2 * Copyright (c) 2011-2014 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
25 #include "Security_regressions.h"
26
27 #include <CoreFoundation/CFData.h>
28 #include <Security/SecOTRSession.h>
29 #include <Security/SecInternal.h>
30 #include <Security/SecBasePriv.h>
31
32 static void SecMPLogError(CFErrorRef error) {
33 if (error == NULL) {
34 return;
35 }
36 CFDictionaryRef tempDictionary = CFErrorCopyUserInfo(error);
37 CFIndex errorCode = CFErrorGetCode(error);
38 CFStringRef errorDomain = CFErrorGetDomain(error);
39 CFStringRef errorString = CFDictionaryGetValue(tempDictionary, kCFErrorDescriptionKey);
40 CFErrorRef previousError = (CFErrorRef)CFDictionaryGetValue(tempDictionary, kCFErrorUnderlyingErrorKey);
41 if (previousError != NULL) {
42 SecMPLogError(previousError);
43 }
44 char errorDomainStr[1024];
45 char errorStringStr[1024];
46
47 CFStringGetCString(errorDomain, errorDomainStr, 1024, kCFStringEncodingUTF8);
48 CFStringGetCString(errorString, errorStringStr, 1024, kCFStringEncodingUTF8);
49 printf("MessageProtection: %s (%ld) -- %s\n", errorDomainStr, errorCode, errorStringStr);
50 CFReleaseSafe(tempDictionary);
51 }
52
53 static void serializeAndDeserialize(SecOTRSessionRef* thisOne)
54 {
55 CFMutableDataRef serialized = CFDataCreateMutable(kCFAllocatorDefault, 0);
56
57 SecOTRSAppendSerialization(*thisOne, serialized);
58 CFReleaseNull(*thisOne);
59 *thisOne = SecOTRSessionCreateFromData(kCFAllocatorDefault, serialized);
60
61 CFReleaseSafe(serialized);
62 }
63
64 #define renegotiateTests 9
65
66 static void renegotiate(SecOTRSessionRef *bobSession, SecOTRSessionRef *aliceSession, bool serializeNegotiating, CFDataRef messageDuringNegotiation){
67
68 CFMutableDataRef aliceRestartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
69 CFMutableDataRef bobDHKeyPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
70
71 CFDataRef empty = CFDataCreate(kCFAllocatorDefault, NULL, 0);
72
73 CFMutableDataRef hopefullyNothing = CFDataCreateMutable(kCFAllocatorDefault, 0);
74
75 //send a restart packet after session has successfully sent messages
76 ok_status(SecOTRSAppendRestartPacket(*aliceSession, aliceRestartPacket), "Alice restart packet");
77
78 if(serializeNegotiating)
79 serializeAndDeserialize(aliceSession);
80
81 SKIP: {
82 skip("No messageDuringNegotiation", 1, messageDuringNegotiation);
83 is(SecOTRSVerifyAndExposeMessage(*aliceSession, messageDuringNegotiation, hopefullyNothing), errSecOTRNotReady, "Message during negotiation");
84 }
85
86 if(serializeNegotiating)
87 serializeAndDeserialize(aliceSession);
88
89 ok_status(SecOTRSProcessPacket(*bobSession, aliceRestartPacket, bobDHKeyPacket),
90 "Bob DH packet failed");
91
92 if (serializeNegotiating)
93 serializeAndDeserialize(bobSession);
94
95 // Step 3: With one "real" DH key message, and one replayed DH commit message, try to get a "reveal sig" out of one side
96
97 CFMutableDataRef aliceRevealSigPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
98
99 ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyPacket, aliceRevealSigPacket),
100 "Alice DH Key packet failed");
101
102 if (serializeNegotiating)
103 serializeAndDeserialize(aliceSession);
104
105 CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
106
107 ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigPacket, bobRevealSigResponse),
108 "Bob DH Key packet failed");
109
110 if (serializeNegotiating)
111 serializeAndDeserialize(bobSession);
112
113 // Step 4: Having gotten the reveal signature, now work for the signature
114
115 CFMutableDataRef aliceSigPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
116
117 ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigPacket),
118 "Bob Reveal sig failed");
119
120 if (serializeNegotiating)
121 serializeAndDeserialize(aliceSession);
122
123
124 ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
125 ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
126
127 CFReleaseNull(aliceRestartPacket);
128 CFReleaseNull(aliceRevealSigPacket);
129 CFReleaseNull(aliceSigPacket);
130
131 CFReleaseNull(bobDHKeyPacket);
132 CFReleaseNull(bobRevealSigResponse);
133
134 CFReleaseNull(hopefullyNothing);
135 CFReleaseNull(empty);
136
137 }
138
139
140 #define sendMessagesCount(n) ((n) * 14)
141 static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessionRef *aliceSession, bool serialize)
142 {
143 for(int count = howMany; count > 0; --count) {
144 const char* aliceToBob = "aliceToBob";
145 CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
146 CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
147 CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
148
149 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
150 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
151
152
153 if (serialize) {
154 serializeAndDeserialize(bobSession);
155 serializeAndDeserialize(aliceSession);
156 }
157
158 ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
159 && 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
160
161 CFReleaseNull(rawAliceToBob);
162 CFReleaseNull(protectedAliceToBob);
163 CFReleaseNull(bobDecode);
164
165 const char* bobToAlice = "i liked your silly message from me to you";
166 CFDataRef rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
167 CFMutableDataRef protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
168 CFMutableDataRef aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
169
170 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawBobToAlice, protectedBobToAlice), "encode reply");
171 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedBobToAlice, aliceDecode), "decode reply");
172
173 if (serialize) {
174 serializeAndDeserialize(bobSession);
175 serializeAndDeserialize(aliceSession);
176 }
177
178 ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
179 && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
180
181 CFReleaseNull(rawAliceToBob);
182 CFReleaseNull(rawBobToAlice);
183 CFReleaseNull(protectedBobToAlice);
184 CFReleaseNull(protectedAliceToBob);
185 CFReleaseNull(aliceDecode);
186
187 rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
188 protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
189 bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
190
191 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
192 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
193
194 if (serialize) {
195 serializeAndDeserialize(bobSession);
196 serializeAndDeserialize(aliceSession);
197 }
198
199 ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
200 && 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
201
202 CFReleaseNull(rawAliceToBob);
203 CFReleaseNull(protectedAliceToBob);
204 CFReleaseNull(bobDecode);
205
206 bobToAlice = "i liked your silly message from me to you";
207 rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
208 protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
209 aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
210
211 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawBobToAlice, protectedBobToAlice), "encode reply");
212 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedBobToAlice, aliceDecode), "decode reply");
213
214 if (serialize) {
215 serializeAndDeserialize(bobSession);
216 serializeAndDeserialize(aliceSession);
217 }
218
219 ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
220 && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
221
222 CFReleaseNull(rawAliceToBob);
223 CFReleaseNull(rawBobToAlice);
224 CFReleaseNull(protectedBobToAlice);
225 CFReleaseNull(protectedAliceToBob);
226 CFReleaseNull(aliceDecode);
227
228
229
230 CFStringRef stateString = CFCopyDescription(*bobSession);
231 ok(stateString, "getting state from bob");
232 CFReleaseNull(stateString);
233
234 stateString = CFCopyDescription(*aliceSession);
235 ok(stateString, "getting state from alice");
236 CFReleaseNull(stateString);
237 }
238 }
239
240 #define kNegotiateTestCount (14 + sendMessagesCount(1) * 4 \
241 + renegotiateTests)
242
243 static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, SecOTRSessionRef *brandNewBobSession, bool serializeNegotiating, bool serializeMessaging, bool textMode, bool compact)
244 {
245 const int kEmptyMessageSize = textMode ? 6 : 0;
246
247 // Step 1: Create a start packet for each side of the transaction
248 CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
249
250 ok_status(SecOTRSAppendStartPacket(*bobSession, bobStartPacket), "Bob start packet");
251
252 if (serializeNegotiating)
253 serializeAndDeserialize(bobSession);
254
255 CFMutableDataRef aliceStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
256
257 ok_status(SecOTRSAppendStartPacket(*aliceSession, aliceStartPacket), "Alice start packet");
258
259 if (serializeNegotiating)
260 serializeAndDeserialize(aliceSession);
261
262 // Step 2: Exchange the start packets, forcing the DH commit messages to collide
263 CFMutableDataRef aliceDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
264
265 ok_status(SecOTRSProcessPacket(*aliceSession, bobStartPacket, aliceDHKeyResponse),
266 "Bob DH packet failed");
267
268 if (serializeNegotiating)
269 serializeAndDeserialize(aliceSession);
270
271 CFReleaseNull(bobStartPacket);
272
273 CFMutableDataRef bobDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
274
275 ok_status(SecOTRSProcessPacket(*bobSession, aliceStartPacket, bobDHKeyResponse),
276 "Alice DH packet failed");
277
278 if (serializeNegotiating)
279 serializeAndDeserialize(bobSession);
280
281 CFReleaseNull(aliceStartPacket);
282
283 // Step 3: With one "real" DH key message, and one replayed DH commit message, try to get a "reveal sig" out of one side
284
285 CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
286
287 ok_status(SecOTRSProcessPacket(*bobSession, aliceDHKeyResponse, bobRevealSigResponse),
288 "Alice DH Key packet failed");
289
290 if (serializeNegotiating)
291 serializeAndDeserialize(bobSession);
292
293 CFReleaseNull(aliceDHKeyResponse);
294
295 CFMutableDataRef aliceRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
296
297 ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyResponse, aliceRevealSigResponse),
298 "Bob DH Key packet failed");
299
300 if (serializeNegotiating)
301 serializeAndDeserialize(aliceSession);
302
303 CFReleaseNull(bobDHKeyResponse);
304
305 // Step 4: Having gotten the reveal signature, now work for the signature
306
307 CFMutableDataRef aliceSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
308
309 ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigResponse),
310 "Bob Reveal sig failed");
311
312 if (serializeNegotiating)
313 serializeAndDeserialize(aliceSession);
314
315 CFReleaseNull(bobRevealSigResponse);
316
317 CFMutableDataRef bobSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
318
319 ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigResponse, bobSigResponse),
320 "Alice Reveal sig failed");
321
322 if (serializeNegotiating)
323 serializeAndDeserialize(bobSession);
324
325 CFReleaseNull(aliceRevealSigResponse);
326
327 // Step 5: All the messages have been sent, now deal with any replays from the collision handling
328 CFMutableDataRef bobFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
329
330 ok_status(SecOTRSProcessPacket(*bobSession, aliceSigResponse, bobFinalResponse),
331 "Alice Final Sig failed");
332
333 if (serializeNegotiating)
334 serializeAndDeserialize(bobSession);
335
336 CFMutableDataRef aliceFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
337
338 ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse),
339 "Bob Final Sig failed");
340
341 is(kEmptyMessageSize, CFDataGetLength(aliceFinalResponse), "Alice had nothing left to say");
342 CFReleaseNull(aliceFinalResponse);
343 CFReleaseNull(bobSigResponse);
344
345 if (serializeNegotiating)
346 serializeAndDeserialize(aliceSession);
347
348 is(kEmptyMessageSize, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say");
349 ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
350 ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
351
352 CFReleaseNull(aliceSigResponse);
353 CFReleaseNull(bobFinalResponse);
354
355 sendMessages(1, bobSession, aliceSession, serializeMessaging);
356 sendMessages(1, aliceSession, bobSession, serializeMessaging);
357 sendMessages(1, bobSession, aliceSession, serializeMessaging);
358 sendMessages(1, aliceSession, bobSession, serializeMessaging);
359
360 const char *bobToAlice = "i liked your silly message from me to you";
361 CFDataRef rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
362 CFMutableDataRef protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
363
364 ok_status(SecOTRSSignAndProtectMessage(*bobSession, rawBobToAlice, protectedBobToAlice), "protected bob to alice message");
365
366 CFReleaseNull(rawBobToAlice);
367
368 renegotiate(brandNewBobSession, aliceSession, serializeNegotiating, protectedBobToAlice);
369
370 CFReleaseNull(protectedBobToAlice);
371
372 }
373
374 #define kEdgeCaseTestCount (10 + kNegotiateTestCount * 2)
375
376 static void tryEdgeCases(uint32_t flags)
377 {
378 CFErrorRef testError = NULL;
379 SecOTRFullIdentityRef aliceID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
380 SecMPLogError(testError);
381 CFReleaseNull(testError);
382 testError = NULL;
383 SecOTRFullIdentityRef bobID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
384 SecMPLogError(testError);
385 CFReleaseNull(testError);
386 testError = NULL;
387
388 ok(aliceID, "create alice ID");
389 ok(bobID, "create bob ID");
390
391 SecOTRPublicIdentityRef alicePublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, aliceID, &testError);
392 SecMPLogError(testError);
393 CFReleaseNull(testError);
394 SecOTRPublicIdentityRef bobPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, bobID, &testError);
395 SecMPLogError(testError);
396 CFReleaseNull(testError);
397
398 ok(alicePublicID, "extract alice public");
399 ok(bobPublicID, "extract bob public");
400
401 SecOTRSessionRef aliceSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, flags);
402 SecOTRSessionRef bobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, flags);
403 SecOTRSessionRef brandNewBobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, flags);
404 SecOTRSessionRef brandNewBobSession2 = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, flags);
405 SecOTRSessionRef brandNewBobSession3 = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, flags);
406
407 ok(aliceSession, "create alice session");
408 ok(bobSession, "create bob session");
409 ok(brandNewBobSession, "create new bob session");
410
411
412 // Release the IDs, sessions shouldn't need us to retain them for them.
413 CFReleaseNull(aliceID);
414 CFReleaseNull(bobID);
415
416 CFReleaseNull(alicePublicID);
417 CFReleaseNull(bobPublicID);
418
419 negotiate(&aliceSession, &bobSession, &brandNewBobSession, true, true, false, flags & kSecOTRUseAppleCustomMessageFormat);
420
421 negotiate(&aliceSession, &bobSession, &brandNewBobSession2, true, false, false, flags & kSecOTRUseAppleCustomMessageFormat);
422
423
424 const char * testMessageString = "i liked your silly message from me to you";
425 CFDataRef testMessage = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)testMessageString, (CFIndex) strlen(testMessageString));
426 CFMutableDataRef protectedTestMessage = CFDataCreateMutable(kCFAllocatorDefault, 0);
427
428 ok_status(SecOTRSSignAndProtectMessage(aliceSession, testMessage, protectedTestMessage), "Make message");
429
430 CFMutableDataRef hopefullyNothing = CFDataCreateMutable(kCFAllocatorDefault, 0);
431
432 is(SecOTRSVerifyAndExposeMessage(brandNewBobSession3, protectedTestMessage, hopefullyNothing), errSecOTRNotReady, "Message Before Negotiating");
433
434 /* cleanup keychain */
435 ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain");
436 SecMPLogError(testError);
437 CFReleaseNull(testError);
438
439 CFReleaseNull(aliceSession);
440 CFReleaseNull(bobSession);
441
442 CFReleaseNull(brandNewBobSession);
443 CFReleaseNull(brandNewBobSession2);
444 CFReleaseNull(brandNewBobSession3);
445 CFReleaseNull(testMessage);
446 CFReleaseNull(protectedTestMessage);
447 CFReleaseNull(hopefullyNothing);
448 }
449
450
451 #define kTestTestCount (2 * kEdgeCaseTestCount)
452
453 static void tests()
454 {
455 tryEdgeCases(0);
456 tryEdgeCases(kSecOTRUseAppleCustomMessageFormat);
457 }
458
459 int otr_40_edgecases(int argc, char *const *argv)
460 {
461 plan_tests(kTestTestCount);
462
463 tests();
464
465 return 0;
466 }