]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/otr/otr-60-slowroll.c
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / otr / otr-60-slowroll.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) * 5)
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 CFStringRef stateString = CFCopyDescription(*bobSession);
93 ok(stateString, "getting state from bob");
94 CFReleaseNull(stateString);
95
96 stateString = CFCopyDescription(*aliceSession);
97 ok(stateString, "getting state from alice");
98 CFReleaseNull(stateString);
99 }
100 }
101
102 #define kNegotiateTestCount (14 \
103 + 60 + (69 * sendMessagesCount(1)))
104 static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serializeNegotiating, bool serializeMessaging, bool textMode, bool compact)
105 {
106 const int kEmptyMessageSize = textMode ? 6 : 0;
107
108 // Step 1: Create a start packet for each side of the transaction
109 CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
110
111 ok_status(SecOTRSAppendStartPacket(*bobSession, bobStartPacket), "Bob start packet");
112
113 if (serializeNegotiating)
114 serializeAndDeserialize(bobSession);
115
116 CFMutableDataRef aliceStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
117
118 ok_status(SecOTRSAppendStartPacket(*aliceSession, aliceStartPacket), "Alice start packet");
119
120 if (serializeNegotiating)
121 serializeAndDeserialize(aliceSession);
122
123 // Step 2: Exchange the start packets, forcing the DH commit messages to collide
124 CFMutableDataRef aliceDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
125
126 ok_status(SecOTRSProcessPacket(*aliceSession, bobStartPacket, aliceDHKeyResponse),
127 "Bob DH packet failed");
128
129 if (serializeNegotiating)
130 serializeAndDeserialize(aliceSession);
131
132 CFReleaseNull(bobStartPacket);
133
134 CFMutableDataRef bobDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
135
136 ok_status(SecOTRSProcessPacket(*bobSession, aliceStartPacket, bobDHKeyResponse),
137 "Alice DH packet failed");
138
139 if (serializeNegotiating)
140 serializeAndDeserialize(bobSession);
141
142 CFReleaseNull(aliceStartPacket);
143
144 // Step 3: With one "real" DH key message, and one replayed DH commit message, try to get a "reveal sig" out of one side
145
146 CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
147
148 ok_status(SecOTRSProcessPacket(*bobSession, aliceDHKeyResponse, bobRevealSigResponse),
149 "Alice DH Key packet failed");
150
151 if (serializeNegotiating)
152 serializeAndDeserialize(bobSession);
153
154 CFReleaseNull(aliceDHKeyResponse);
155
156 CFMutableDataRef aliceRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
157
158 ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyResponse, aliceRevealSigResponse),
159 "Bob DH Key packet failed");
160
161 if (serializeNegotiating)
162 serializeAndDeserialize(aliceSession);
163
164 CFReleaseNull(bobDHKeyResponse);
165
166 // Step 4: Having gotten the reveal signature, now work for the signature
167
168 CFMutableDataRef aliceSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
169
170 ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigResponse),
171 "Bob Reveal sig failed");
172
173 if (serializeNegotiating)
174 serializeAndDeserialize(aliceSession);
175
176 CFReleaseNull(bobRevealSigResponse);
177
178 CFMutableDataRef bobSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
179
180 ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigResponse, bobSigResponse),
181 "Alice Reveal sig failed");
182
183 if (serializeNegotiating)
184 serializeAndDeserialize(bobSession);
185
186 CFReleaseNull(aliceRevealSigResponse);
187
188 // Step 5: All the messages have been sent, now deal with any replays from the collision handling
189 CFMutableDataRef bobFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
190
191 ok_status(SecOTRSProcessPacket(*bobSession, aliceSigResponse, bobFinalResponse),
192 "Alice Final Sig failed");
193
194 if (serializeNegotiating)
195 serializeAndDeserialize(bobSession);
196
197 CFMutableDataRef aliceFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
198
199 ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse),
200 "Bob Final Sig failed");
201
202 is(kEmptyMessageSize, CFDataGetLength(aliceFinalResponse), "Alice had nothing left to say");
203 CFReleaseNull(aliceFinalResponse);
204 CFReleaseNull(bobSigResponse);
205
206 if (serializeNegotiating)
207 serializeAndDeserialize(aliceSession);
208
209 is(kEmptyMessageSize, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say");
210 ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
211 ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
212
213 CFReleaseNull(aliceSigResponse);
214 CFReleaseNull(bobFinalResponse);
215
216 //////
217 //both sessions are kicked to roll
218 //////
219 SecOTRSKickTimeToRoll(*aliceSession);
220 SecOTRSKickTimeToRoll(*bobSession);
221
222 sendMessages(1, aliceSession, bobSession, serializeMessaging);
223 sendMessages(1, bobSession, aliceSession, serializeMessaging);
224 sendMessages(1, aliceSession, bobSession, serializeMessaging);
225
226 //now we make sure keys do not roll for 10 iterations
227 int aliceKeyID = SecOTRSGetKeyID(*aliceSession);
228 int bobKeyID = SecOTRSGetKeyID(*bobSession);
229
230 for(int i = 0; i< 10; i++){
231 sendMessages(1, bobSession, aliceSession, serializeMessaging);
232 sendMessages(1, aliceSession, bobSession, serializeMessaging);
233
234 ok(SecOTRSGetKeyID(*aliceSession) == aliceKeyID);
235 ok(SecOTRSGetKeyID(*bobSession) == bobKeyID);
236 }
237
238 //////
239 //kicking sending side
240 ///////
241
242 SecOTRSKickTimeToRoll(*aliceSession);
243 sendMessages(1, aliceSession, bobSession, serializeMessaging);
244
245 sendMessages(1, bobSession, aliceSession, serializeMessaging);
246 sendMessages(1, aliceSession, bobSession, serializeMessaging);
247
248 //now we make sure keys do not roll for 10 iterations
249 aliceKeyID = SecOTRSGetKeyID(*aliceSession);
250 bobKeyID = SecOTRSGetKeyID(*bobSession);
251
252 for(int i = 0; i< 10; i++){
253 sendMessages(1, aliceSession, bobSession, serializeMessaging);
254 sendMessages(1, bobSession, aliceSession, serializeMessaging);
255
256 ok(SecOTRSGetKeyID(*aliceSession) == aliceKeyID);
257 ok(SecOTRSGetKeyID(*bobSession) == bobKeyID);
258 }
259 //////
260 //kicking receiving side
261 //////
262 SecOTRSKickTimeToRoll(*bobSession);
263 sendMessages(1, bobSession, aliceSession, serializeMessaging);
264
265 sendMessages(1, aliceSession, bobSession, serializeMessaging);
266 sendMessages(1, bobSession, aliceSession, serializeMessaging);
267
268 aliceKeyID = SecOTRSGetKeyID(*aliceSession);
269 bobKeyID = SecOTRSGetKeyID(*bobSession);
270
271 for(int i = 0; i< 10; i++){
272 sendMessages(1, aliceSession, bobSession, serializeMessaging);
273 sendMessages(1, bobSession, aliceSession, serializeMessaging);
274
275 ok(SecOTRSGetKeyID(*aliceSession) == aliceKeyID);
276 ok(SecOTRSGetKeyID(*bobSession) == bobKeyID);
277 }
278
279 }
280
281
282 #define kTestTestCount (11 + kNegotiateTestCount * 6)
283
284 static void tests()
285 {
286 CFErrorRef testError = NULL;
287 SecOTRFullIdentityRef aliceID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
288 SecMPLogError(testError);
289 CFReleaseNull(testError);
290 testError = NULL;
291 SecOTRFullIdentityRef bobID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
292 SecMPLogError(testError);
293 CFReleaseNull(testError);
294 testError = NULL;
295
296 ok(aliceID, "create alice ID");
297 ok(bobID, "create bob ID");
298
299 SecOTRPublicIdentityRef alicePublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, aliceID, &testError);
300 SecMPLogError(testError);
301 CFReleaseNull(testError);
302 SecOTRPublicIdentityRef bobPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, bobID, &testError);
303 SecMPLogError(testError);
304 CFReleaseNull(testError);
305
306 ok(alicePublicID, "extract alice public");
307 ok(bobPublicID, "extract bob public");
308
309 SecOTRSessionRef aliceSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRSendTextMessages | kSecOTRSlowRoll);
310 SecOTRSessionRef bobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRSendTextMessages | kSecOTRSlowRoll);
311
312 ok(aliceSession, "create alice session");
313 ok(bobSession, "create bob session");
314
315 SecOTRSessionRef aliceCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRUseAppleCustomMessageFormat | kSecOTRSlowRoll);
316 SecOTRSessionRef bobCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRUseAppleCustomMessageFormat | kSecOTRSlowRoll);
317
318 ok(aliceCompactSession, "create alice compact session");
319 ok(bobCompactSession, "create bob compact session");
320
321 SecOTRSessionRef aliceCompactHashesSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRUseAppleCustomMessageFormat|kSecOTRIncludeHashesInMessages | kSecOTRSlowRoll);
322 SecOTRSessionRef bobCompactHashesSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRUseAppleCustomMessageFormat|kSecOTRIncludeHashesInMessages | kSecOTRSlowRoll);
323
324 ok(aliceCompactHashesSession, "create alice compact session with hashes");
325 ok(bobCompactHashesSession, "create bob compact session with hashes");
326
327 // Release the IDs, sessions shouldn't need us to retain them for them.
328 CFReleaseNull(aliceID);
329 CFReleaseNull(bobID);
330
331 CFReleaseNull(alicePublicID);
332 CFReleaseNull(bobPublicID);
333
334 negotiate(&aliceSession, &bobSession, true, true, true, false);
335
336 negotiate(&aliceSession, &bobSession, true, false, true, false);
337
338 negotiate(&aliceCompactSession, &bobCompactSession, true, true, false, true);
339
340 negotiate(&aliceCompactSession, &bobCompactSession, true, false, false, true);
341
342 negotiate(&aliceCompactHashesSession, &bobCompactHashesSession, true, true, false, true);
343
344 negotiate(&aliceCompactHashesSession, &bobCompactHashesSession, true, false, false, true);
345
346 /* cleanup keychain */
347 ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain");
348 SecMPLogError(testError);
349 CFReleaseNull(testError);
350
351 CFReleaseNull(aliceSession);
352 CFReleaseNull(bobSession);
353
354 CFReleaseNull(aliceCompactSession);
355 CFReleaseNull(bobCompactSession);
356
357 CFReleaseNull(aliceCompactHashesSession);
358 CFReleaseNull(bobCompactHashesSession);
359 }
360
361 int otr_60_slowroll(int argc, char *const *argv)
362 {
363 plan_tests(kTestTestCount);
364
365 tests();
366
367 return 0;
368 }