]> git.saurik.com Git - apple/security.git/blob - sec/Security/Regressions/otr/otr-30-negotiation.c
Security-55471.14.tar.gz
[apple/security.git] / sec / Security / Regressions / otr / otr-30-negotiation.c
1 //
2 // otr-30-negotiation.c
3 // regressions
4 //
5 // Created by Mitch Adler on 6/7/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
7 //
8
9 #include "Security_regressions.h"
10
11 #include <CoreFoundation/CFData.h>
12 #include <Security/SecOTRSession.h>
13 #include <Security/SecInternal.h>
14 #include <Security/SecBasePriv.h>
15
16 static void SecMPLogError(CFErrorRef error) {
17 if (error == NULL) {
18 return;
19 }
20 CFDictionaryRef tempDictionary = CFErrorCopyUserInfo(error);
21 CFIndex errorCode = CFErrorGetCode(error);
22 CFStringRef errorDomain = CFErrorGetDomain(error);
23 CFStringRef errorString = CFDictionaryGetValue(tempDictionary, kCFErrorDescriptionKey);
24 CFErrorRef previousError = (CFErrorRef)CFDictionaryGetValue(tempDictionary, kCFErrorUnderlyingErrorKey);
25 if (previousError != NULL) {
26 SecMPLogError(previousError);
27 }
28 char errorDomainStr[1024];
29 char errorStringStr[1024];
30
31 CFStringGetCString(errorDomain, errorDomainStr, 1024, kCFStringEncodingUTF8);
32 CFStringGetCString(errorString, errorStringStr, 1024, kCFStringEncodingUTF8);
33 printf("MessageProtection: %s (%ld) -- %s\n", errorDomainStr, errorCode, errorStringStr);
34 CFReleaseSafe(tempDictionary);
35 }
36
37 static void serializeAndDeserialize(SecOTRSessionRef* thisOne)
38 {
39 CFMutableDataRef serialized = CFDataCreateMutable(kCFAllocatorDefault, 0);
40
41 SecOTRSAppendSerialization(*thisOne, serialized);
42 CFReleaseNull(*thisOne);
43 *thisOne = SecOTRSessionCreateFromData(kCFAllocatorDefault, serialized);
44
45 CFReleaseSafe(serialized);
46 }
47
48
49
50 #define sendMessagesCount(n) ((n) * 8)
51 static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessionRef *aliceSession, bool serialize)
52 {
53 for(int count = howMany; count > 0; --count) {
54 const char* aliceToBob = "aliceToBob";
55 CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
56 CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
57 CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
58
59 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
60 ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
61
62 if (serialize) {
63 serializeAndDeserialize(bobSession);
64 serializeAndDeserialize(aliceSession);
65 }
66
67 ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
68 && 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
69
70 CFReleaseNull(rawAliceToBob);
71 CFReleaseNull(protectedAliceToBob);
72 CFReleaseNull(bobDecode);
73
74 const char* bobToAlice = "i liked your silly message from me to you";
75 CFDataRef rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
76 CFMutableDataRef protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
77 CFMutableDataRef aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
78
79 ok_status(SecOTRSSignAndProtectMessage(*bobSession, rawBobToAlice, protectedBobToAlice), "encode reply");
80 ok_status(SecOTRSVerifyAndExposeMessage(*aliceSession, protectedBobToAlice, aliceDecode), "decode reply");
81
82 if (serialize) {
83 serializeAndDeserialize(bobSession);
84 serializeAndDeserialize(aliceSession);
85 }
86
87 ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
88 && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
89
90 CFReleaseNull(rawAliceToBob);
91 CFReleaseNull(protectedAliceToBob);
92 CFReleaseNull(aliceDecode);
93
94 CFStringRef stateString = CFCopyDescription(*bobSession);
95 ok(stateString, "getting state from bob");
96 CFReleaseNull(stateString);
97
98 stateString = CFCopyDescription(*aliceSession);
99 ok(stateString, "getting state from alice");
100 CFReleaseNull(stateString);
101 }
102 }
103
104 #define kNegotiateTestCount (14 + sendMessagesCount(5) \
105 + 2 + sendMessagesCount(1) \
106 + 1 + sendMessagesCount(1))
107 static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serialize)
108 {
109 // Step 1: Create a start packet for each side of the transaction
110 CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
111
112 ok_status(SecOTRSAppendStartPacket(*bobSession, bobStartPacket), "Bob start packet");
113
114 if (serialize)
115 serializeAndDeserialize(bobSession);
116
117 CFMutableDataRef aliceStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
118
119 ok_status(SecOTRSAppendStartPacket(*aliceSession, aliceStartPacket), "Alice start packet");
120
121 if (serialize)
122 serializeAndDeserialize(aliceSession);
123
124 // Step 2: Exchange the start packets, forcing the DH commit messages to collide
125 CFMutableDataRef aliceDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
126
127 ok_status(SecOTRSProcessPacket(*aliceSession, bobStartPacket, aliceDHKeyResponse),
128 "Bob DH packet failed");
129
130 if (serialize)
131 serializeAndDeserialize(aliceSession);
132
133 CFReleaseNull(bobStartPacket);
134
135 CFMutableDataRef bobDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
136
137 ok_status(SecOTRSProcessPacket(*bobSession, aliceStartPacket, bobDHKeyResponse),
138 "Alice DH packet failed");
139
140 if (serialize)
141 serializeAndDeserialize(bobSession);
142
143 CFReleaseNull(aliceStartPacket);
144
145 // Step 3: With one "real" DH key message, and one replayed DH commit message, try to get a "reveal sig" out of one side
146
147 CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
148
149 ok_status(SecOTRSProcessPacket(*bobSession, aliceDHKeyResponse, bobRevealSigResponse),
150 "Alice DH Key packet failed");
151
152 if (serialize)
153 serializeAndDeserialize(bobSession);
154
155 CFReleaseNull(aliceDHKeyResponse);
156
157 CFMutableDataRef aliceRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
158
159 ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyResponse, aliceRevealSigResponse),
160 "Bob DH Key packet failed");
161
162 if (serialize)
163 serializeAndDeserialize(aliceSession);
164
165 CFReleaseNull(bobDHKeyResponse);
166
167 // Step 4: Having gotten the reveal signature, now work for the signature
168
169 CFMutableDataRef aliceSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
170
171 ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigResponse),
172 "Bob Reveal sig failed");
173
174 if (serialize)
175 serializeAndDeserialize(aliceSession);
176
177 CFReleaseNull(bobRevealSigResponse);
178
179 CFMutableDataRef bobSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
180
181 ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigResponse, bobSigResponse),
182 "Alice Reveal sig failed");
183
184 if (serialize)
185 serializeAndDeserialize(bobSession);
186
187 CFReleaseNull(aliceRevealSigResponse);
188
189 // Step 5: All the messages have been sent, now deal with any replays from the collision handling
190 CFMutableDataRef bobFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
191
192 ok_status(SecOTRSProcessPacket(*bobSession, aliceSigResponse, bobFinalResponse),
193 "Alice Final Sig failed");
194
195 if (serialize)
196 serializeAndDeserialize(bobSession);
197
198 CFMutableDataRef aliceFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
199
200 ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse),
201 "Bob Final Sig failed");
202
203 if (serialize)
204 serializeAndDeserialize(aliceSession);
205
206 is(6, CFDataGetLength(bobFinalResponse), "Alice had nothing left to say");
207 is(6, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say");
208 ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
209 ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
210
211 CFReleaseNull(aliceSigResponse);
212 CFReleaseNull(bobFinalResponse);
213
214 sendMessages(5, bobSession, aliceSession, serialize);
215
216 const char* aliceToBob = "deferredMessage";
217 CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
218 CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
219 CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
220
221 ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
222
223 sendMessages(1, bobSession, aliceSession, serialize);
224
225 ok(errSecOTRTooOld ==SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode old message");
226
227 sendMessages(1, bobSession, aliceSession, serialize);
228
229 ok(errSecOTRTooOld == SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Fail to decode excessively old message");
230
231 CFReleaseNull(rawAliceToBob);
232 CFReleaseNull(protectedAliceToBob);
233 CFReleaseNull(bobDecode);
234 }
235
236
237 #define kTestTestCount (7 + kNegotiateTestCount)
238
239 static void tests()
240 {
241 CFErrorRef testError = NULL;
242 SecOTRFullIdentityRef aliceID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
243 SecMPLogError(testError);
244 CFReleaseNull(testError);
245 testError = NULL;
246 SecOTRFullIdentityRef bobID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
247 SecMPLogError(testError);
248 CFReleaseNull(testError);
249 testError = NULL;
250
251 ok(aliceID, "create alice ID");
252 ok(bobID, "create bob ID");
253
254 SecOTRPublicIdentityRef alicePublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, aliceID, &testError);
255 SecMPLogError(testError);
256 CFReleaseNull(testError);
257 SecOTRPublicIdentityRef bobPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, bobID, &testError);
258 SecMPLogError(testError);
259 CFReleaseNull(testError);
260
261 ok(alicePublicID, "extract alice public");
262 ok(bobPublicID, "extract bob public");
263
264 SecOTRSessionRef aliceSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRSendTextMessages);
265 SecOTRSessionRef bobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRSendTextMessages);
266
267 ok(aliceSession, "create alice session");
268 ok(bobSession, "create bob session");
269
270 // Release the IDs, sessions shouldn't need us to retain them for them.
271 CFReleaseNull(aliceID);
272 CFReleaseNull(bobID);
273
274 CFReleaseNull(alicePublicID);
275 CFReleaseNull(bobPublicID);
276
277 negotiate(&aliceSession, &bobSession, true);
278
279 /* cleanup keychain */
280 ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain");
281 SecMPLogError(testError);
282 CFReleaseNull(testError);
283
284 CFReleaseNull(aliceSession);
285 CFReleaseNull(bobSession);
286 }
287
288 int otr_30_negotiation(int argc, char *const *argv)
289 {
290 plan_tests(kTestTestCount);
291
292 tests();
293
294 return 0;
295 }