]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/otr/otr-50-roll.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / otr / otr-50-roll.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/SecOTRSessionPriv.h>
30 #include <Security/SecInternal.h>
31 #include <Security/SecBasePriv.h>
32
33 static void SecMPLogError(CFErrorRef error) {
34 if (error == NULL) {
35 return;
36 }
37 CFDictionaryRef tempDictionary = CFErrorCopyUserInfo(error);
38 CFIndex errorCode = CFErrorGetCode(error);
39 CFStringRef errorDomain = CFErrorGetDomain(error);
40 CFStringRef errorString = CFDictionaryGetValue(tempDictionary, kCFErrorDescriptionKey);
41 CFErrorRef previousError = (CFErrorRef)CFDictionaryGetValue(tempDictionary, kCFErrorUnderlyingErrorKey);
42 if (previousError != NULL) {
43 SecMPLogError(previousError);
44 }
45 char errorDomainStr[1024];
46 char errorStringStr[1024];
47
48 CFStringGetCString(errorDomain, errorDomainStr, 1024, kCFStringEncodingUTF8);
49 CFStringGetCString(errorString, errorStringStr, 1024, kCFStringEncodingUTF8);
50 printf("MessageProtection: %s (%ld) -- %s\n", errorDomainStr, errorCode, errorStringStr);
51 CFReleaseSafe(tempDictionary);
52 }
53
54 static void serializeAndDeserialize(SecOTRSessionRef* thisOne)
55 {
56 CFMutableDataRef serialized = CFDataCreateMutable(kCFAllocatorDefault, 0);
57
58 SecOTRSAppendSerialization(*thisOne, serialized);
59 CFReleaseNull(*thisOne);
60 *thisOne = SecOTRSessionCreateFromData(kCFAllocatorDefault, serialized);
61
62 CFReleaseSafe(serialized);
63 }
64
65
66
67 #define sendMessagesCount(n) ((n) * 14)
68 static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessionRef *aliceSession, bool serialize)
69 {
70 for(int count = howMany; count > 0; --count) {
71 const char* aliceToBob = "aliceToBob";
72 CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
73 CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
74 CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
75
76 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
77 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
78
79
80 if (serialize) {
81 serializeAndDeserialize(bobSession);
82 serializeAndDeserialize(aliceSession);
83 }
84
85 ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
86 && 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
87
88 CFReleaseNull(rawAliceToBob);
89 CFReleaseNull(protectedAliceToBob);
90 CFReleaseNull(bobDecode);
91
92 const char* bobToAlice = "i liked your silly message from me to you";
93 CFDataRef rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
94 CFMutableDataRef protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
95 CFMutableDataRef aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
96
97 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawBobToAlice, protectedBobToAlice), "encode reply");
98 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedBobToAlice, aliceDecode), "decode reply");
99
100 if (serialize) {
101 serializeAndDeserialize(bobSession);
102 serializeAndDeserialize(aliceSession);
103 }
104
105 ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
106 && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
107
108 CFReleaseNull(rawAliceToBob);
109 CFReleaseNull(rawBobToAlice);
110 CFReleaseNull(protectedBobToAlice);
111 CFReleaseNull(protectedAliceToBob);
112 CFReleaseNull(aliceDecode);
113
114 rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
115 protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
116 bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
117
118 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
119 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
120
121 if (serialize) {
122 serializeAndDeserialize(bobSession);
123 serializeAndDeserialize(aliceSession);
124 }
125
126 ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
127 && 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
128
129 CFReleaseNull(rawAliceToBob);
130 CFReleaseNull(protectedAliceToBob);
131 CFReleaseNull(bobDecode);
132
133 bobToAlice = "i liked your silly message from me to you";
134 rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
135 protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
136 aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
137
138 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawBobToAlice, protectedBobToAlice), "encode reply");
139 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedBobToAlice, aliceDecode), "decode reply");
140
141 if (serialize) {
142 serializeAndDeserialize(bobSession);
143 serializeAndDeserialize(aliceSession);
144 }
145
146 ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
147 && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
148
149 CFReleaseNull(rawAliceToBob);
150 CFReleaseNull(rawBobToAlice);
151 CFReleaseNull(protectedBobToAlice);
152 CFReleaseNull(protectedAliceToBob);
153 CFReleaseNull(aliceDecode);
154
155
156
157 CFStringRef stateString = CFCopyDescription(*bobSession);
158 ok(stateString, "getting state from bob");
159 CFReleaseNull(stateString);
160
161 stateString = CFCopyDescription(*aliceSession);
162 ok(stateString, "getting state from alice");
163 CFReleaseNull(stateString);
164 }
165 }
166
167 #define kNegotiateTestCount (19 + sendMessagesCount(5) \
168 + 2 * sendMessagesCount(5))
169 static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serializeNegotiating, bool serializeMessaging, bool textMode, bool compact)
170 {
171 const int kEmptyMessageSize = textMode ? 6 : 0;
172
173 // Step 1: Create a start packet for each side of the transaction
174 CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
175
176 ok_status(SecOTRSAppendStartPacket(*bobSession, bobStartPacket), "Bob start packet");
177
178 if (serializeNegotiating)
179 serializeAndDeserialize(bobSession);
180
181 CFMutableDataRef aliceStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
182
183 ok_status(SecOTRSAppendStartPacket(*aliceSession, aliceStartPacket), "Alice start packet");
184
185 if (serializeNegotiating)
186 serializeAndDeserialize(aliceSession);
187
188 // Step 2: Exchange the start packets, forcing the DH commit messages to collide
189 CFMutableDataRef aliceDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
190
191 ok_status(SecOTRSProcessPacket(*aliceSession, bobStartPacket, aliceDHKeyResponse),
192 "Bob DH packet failed");
193
194 if (serializeNegotiating)
195 serializeAndDeserialize(aliceSession);
196
197 CFReleaseNull(bobStartPacket);
198
199 CFMutableDataRef bobDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
200
201 ok_status(SecOTRSProcessPacket(*bobSession, aliceStartPacket, bobDHKeyResponse),
202 "Alice DH packet failed");
203
204 if (serializeNegotiating)
205 serializeAndDeserialize(bobSession);
206
207 CFReleaseNull(aliceStartPacket);
208
209 // Step 3: With one "real" DH key message, and one replayed DH commit message, try to get a "reveal sig" out of one side
210
211 CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
212
213 ok_status(SecOTRSProcessPacket(*bobSession, aliceDHKeyResponse, bobRevealSigResponse),
214 "Alice DH Key packet failed");
215
216 if (serializeNegotiating)
217 serializeAndDeserialize(bobSession);
218
219 CFReleaseNull(aliceDHKeyResponse);
220
221 CFMutableDataRef aliceRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
222
223 ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyResponse, aliceRevealSigResponse),
224 "Bob DH Key packet failed");
225
226 if (serializeNegotiating)
227 serializeAndDeserialize(aliceSession);
228
229 CFReleaseNull(bobDHKeyResponse);
230
231 // Step 4: Having gotten the reveal signature, now work for the signature
232
233 CFMutableDataRef aliceSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
234
235 ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigResponse),
236 "Bob Reveal sig failed");
237
238 if (serializeNegotiating)
239 serializeAndDeserialize(aliceSession);
240
241 CFReleaseNull(bobRevealSigResponse);
242
243 CFMutableDataRef bobSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
244
245 ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigResponse, bobSigResponse),
246 "Alice Reveal sig failed");
247
248 if (serializeNegotiating)
249 serializeAndDeserialize(bobSession);
250
251 CFReleaseNull(aliceRevealSigResponse);
252
253 // Step 5: All the messages have been sent, now deal with any replays from the collision handling
254 CFMutableDataRef bobFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
255
256 ok_status(SecOTRSProcessPacket(*bobSession, aliceSigResponse, bobFinalResponse),
257 "Alice Final Sig failed");
258
259 if (serializeNegotiating)
260 serializeAndDeserialize(bobSession);
261
262 CFMutableDataRef aliceFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
263
264 ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse),
265 "Bob Final Sig failed");
266
267 is(kEmptyMessageSize, CFDataGetLength(aliceFinalResponse), "Alice had nothing left to say");
268 CFReleaseNull(aliceFinalResponse);
269 CFReleaseNull(bobSigResponse);
270
271 if (serializeNegotiating)
272 serializeAndDeserialize(aliceSession);
273
274 is(kEmptyMessageSize, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say");
275 ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
276 ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
277
278 CFReleaseNull(aliceSigResponse);
279 CFReleaseNull(bobFinalResponse);
280
281 sendMessages(5, bobSession, aliceSession, serializeMessaging);
282
283 for(int i = 0; i < 5; i++){
284 sendMessages(1, aliceSession, bobSession, serializeMessaging);
285 sendMessages(1, bobSession, aliceSession, serializeMessaging);
286
287 ok(SecOTRSGetKeyID(*aliceSession) == SecOTRSGetKeyID(*bobSession));
288 }
289 }
290
291
292 #define kTestTestCount (11 + kNegotiateTestCount * 6)
293
294 static void tests()
295 {
296 CFErrorRef testError = NULL;
297 SecOTRFullIdentityRef aliceID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
298 SecMPLogError(testError);
299 CFReleaseNull(testError);
300 testError = NULL;
301 SecOTRFullIdentityRef bobID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
302 SecMPLogError(testError);
303 CFReleaseNull(testError);
304 testError = NULL;
305
306 ok(aliceID, "create alice ID");
307 ok(bobID, "create bob ID");
308
309 SecOTRPublicIdentityRef alicePublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, aliceID, &testError);
310 SecMPLogError(testError);
311 CFReleaseNull(testError);
312 SecOTRPublicIdentityRef bobPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, bobID, &testError);
313 SecMPLogError(testError);
314 CFReleaseNull(testError);
315
316 ok(alicePublicID, "extract alice public");
317 ok(bobPublicID, "extract bob public");
318
319 SecOTRSessionRef aliceSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRSendTextMessages);
320 SecOTRSessionRef bobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRSendTextMessages);
321
322 ok(aliceSession, "create alice session");
323 ok(bobSession, "create bob session");
324
325 SecOTRSessionRef aliceCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRUseAppleCustomMessageFormat);
326 SecOTRSessionRef bobCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRUseAppleCustomMessageFormat);
327
328 ok(aliceCompactSession, "create alice compact session");
329 ok(bobCompactSession, "create bob compact session");
330
331 SecOTRSessionRef aliceCompactHashesSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRUseAppleCustomMessageFormat|kSecOTRIncludeHashesInMessages);
332 SecOTRSessionRef bobCompactHashesSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRUseAppleCustomMessageFormat|kSecOTRIncludeHashesInMessages);
333
334 ok(aliceCompactHashesSession, "create alice compact session with hashes");
335 ok(bobCompactHashesSession, "create bob compact session with hashes");
336
337 // Release the IDs, sessions shouldn't need us to retain them for them.
338 CFReleaseNull(aliceID);
339 CFReleaseNull(bobID);
340
341 CFReleaseNull(alicePublicID);
342 CFReleaseNull(bobPublicID);
343
344 negotiate(&aliceSession, &bobSession, true, true, true, false);
345
346 negotiate(&aliceSession, &bobSession, true, false, true, false);
347
348 negotiate(&aliceCompactSession, &bobCompactSession, true, true, false, true);
349
350 negotiate(&aliceCompactSession, &bobCompactSession, true, false, false, true);
351
352 negotiate(&aliceCompactHashesSession, &bobCompactHashesSession, true, true, false, true);
353
354 negotiate(&aliceCompactHashesSession, &bobCompactHashesSession, true, false, false, true);
355
356 /* cleanup keychain */
357 ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain");
358 SecMPLogError(testError);
359 CFReleaseNull(testError);
360
361 CFReleaseNull(aliceSession);
362 CFReleaseNull(bobSession);
363
364 CFReleaseNull(aliceCompactSession);
365 CFReleaseNull(bobCompactSession);
366
367 CFReleaseNull(aliceCompactHashesSession);
368 CFReleaseNull(bobCompactHashesSession);
369 }
370
371 int otr_50_roll(int argc, char *const *argv)
372 {
373 plan_tests(kTestTestCount);
374
375 tests();
376
377 return 0;
378 }