]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/Regressions/sc-70-engine.c
Security-57031.40.6.tar.gz
[apple/security.git] / Security / sec / SOSCircle / Regressions / sc-70-engine.c
1 /*
2 * Copyright (c) 2012-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 <SecureObjectSync/SOSEngine.h>
26 #include <SecureObjectSync/SOSPeer.h>
27
28 #include "SOSCircle_regressions.h"
29
30 #include <corecrypto/ccsha2.h>
31 #include <Security/SecBase64.h>
32
33 #include <utilities/SecCFWrappers.h>
34
35 #include <stdint.h>
36 #include "SOSTestDataSource.h"
37
38 #if 1
39 static int kTestTestCount = 0;
40 #else
41 static int kTestTestCount = 61;
42
43 static void tests(void)
44 {
45 CFErrorRef error = NULL;
46
47 /* Transport. */
48 __block unsigned msg_count = 0;
49 uint8_t msg_digest_buffer[CCSHA256_OUTPUT_SIZE];
50 uint8_t *msg_digest = msg_digest_buffer;
51
52 SOSPeerSendBlock sendBlock = ^bool (CFDataRef message, CFErrorRef *error) {
53 size_t msglen = CFDataGetLength(message);
54 const uint8_t *msg = CFDataGetBytePtr(message);
55 const struct ccdigest_info *sha256 = ccsha256_di();
56 if (msg_count++ == 0) {
57 /* message n=0 */
58 ccdigest(sha256, msglen, msg, msg_digest);
59 } else {
60 /* message n=n+1 */
61 ccdigest_di_decl(sha256, sha256_ctx);
62 ccdigest_init(sha256, sha256_ctx);
63 ccdigest_update(sha256, sha256_ctx, sizeof(msg_digest_buffer), msg_digest);
64 ccdigest_update(sha256, sha256_ctx, msglen, msg);
65 ccdigest_final(sha256, sha256_ctx, msg_digest);
66 }
67 size_t encmaxlen = SecBase64Encode(msg, msglen, NULL, 0);
68 CFMutableDataRef encoded = CFDataCreateMutable(NULL, encmaxlen);
69 CFDataSetLength(encoded, encmaxlen);
70 SecBase64Result rc;
71 char *enc = (char *)CFDataGetMutableBytePtr(encoded);
72 #ifndef NDEBUG
73 size_t enclen =
74 #endif
75 SecBase64Encode2(msg, msglen,
76 enc,
77 encmaxlen, kSecB64_F_LINE_LEN_USE_PARAM,
78 64, &rc);
79 assert(enclen < INT32_MAX);
80 // printf("=== BEGIN SOSMESSAGE ===\n%.*s\n=== END SOSMESSAGE ===\n", (int)enclen, enc);
81 CFRelease(encoded);
82 return true;
83 };
84
85 /* Create peer test. */
86 CFStringRef peer_id = CFSTR("peer 70");
87 SOSPeerRef peer;
88 ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error),
89 "create peer: %@", error);
90 CFReleaseNull(error);
91
92 /* DataSource */
93 SOSDataSourceRef ds = SOSTestDataSourceCreate();
94
95 /* Create engine test. */
96 SOSEngineRef engine;
97 ok(engine = SOSEngineCreate(ds, &error), "create engine: %@", error);
98 CFReleaseNull(error);
99
100 /* Make sure the engine did not yet send a any messages to the peer. */
101 unsigned expected_msg_count = 0;
102 is(msg_count, expected_msg_count, "Engine sent %d/%d messages",
103 msg_count, expected_msg_count);
104
105 /* Test passing peer messages to the engine. */
106 CFDataRef message;
107
108 /* Hand an empty message to the engine for handeling. */
109 message = CFDataCreate(NULL, NULL, 0);
110 ok(false == SOSEngineHandleMessage(engine, peer, message, &error),
111 "handle empty message: %@", error);
112 ok(false == SOSPeerSendMessageIfNeeded(engine, peer, &error, sendBlock),
113 "send response: %@", error);
114 CFReleaseNull(error);
115 CFReleaseNull(message);
116 /* Make sure the engine did not yet send a response to the peer. */
117 is(msg_count, expected_msg_count, "Engine sent %d/%d messages",
118 msg_count, expected_msg_count);
119
120
121 /* Create manifest digest message. */
122 SKIP: {
123 skip("Create manifest digest message failed", 2,
124 ok(message = SOSEngineCreateManifestDigestMessage(engine, peer,
125 &error),
126 "create manifest digest message: %@", error));
127 CFReleaseNull(error);
128 /* Pass manifest digest message to the engine for handeling. */
129 skip("", 1,
130 ok(SOSEngineHandleMessage(engine, peer, message, &error),
131 "handle manifest digest message: %@", error));
132 /* Make sure the engine sent a response to the peer. */
133 expected_msg_count++;
134 is(msg_count, expected_msg_count, "Engine sent %d/%d messages",
135 msg_count, expected_msg_count);
136 }
137 CFReleaseNull(message);
138 CFReleaseNull(error);
139
140 /* Create manifest message. */
141 SKIP: {
142 skip("Create manifest message failed", 2,
143 ok(message = SOSEngineCreateManifestMessage(engine, peer, &error),
144 "create manifest message: %@", error));
145 CFReleaseNull(error);
146 /* Pass manifest message to the engine for handeling. */
147 skip("", 1,
148 ok(SOSEngineHandleMessage(engine, peer, message, &error),
149 "handle manifest message: %@", error));
150 /* Make sure the engine sent a response to the peer. */
151 expected_msg_count++;
152 is(msg_count, expected_msg_count, "Engine sent %d/%d messages",
153 msg_count, expected_msg_count);
154 }
155 CFReleaseNull(message);
156 CFReleaseNull(error);
157
158 /* Create manifest and objects message. */
159 SKIP: {
160 skip("Create manifest and objects message failed", 2,
161 ok(message = SOSEngineCreateManifestAndObjectsMessage(engine, peer,
162 &error),
163 "create manifest and objects message: %@", error));
164 CFReleaseNull(error);
165 /* Pass manifest and objects message to the engine for handeling. */
166 skip("", 1,
167 ok(SOSEngineHandleMessage(engine, peer, message, &error),
168 "handle manifest and objects message: %@", error));
169 /* Make sure the engine sent a response to the peer. */
170 expected_msg_count++;
171 is(msg_count, expected_msg_count, "Engine sent %d/%d messages",
172 msg_count, expected_msg_count);
173 }
174 CFReleaseNull(message);
175 CFReleaseNull(error);
176
177 /* Clean up. */
178 CFReleaseSafe(peer);
179 SOSEngineDispose(engine);
180 }
181
182 static CFStringRef SOSMessageCopyDigestHex(CFDataRef message) {
183 uint8_t digest[CCSHA1_OUTPUT_SIZE];
184 ccdigest(ccsha1_di(), CFDataGetLength(message), CFDataGetBytePtr(message), digest);
185 CFMutableStringRef hex = CFStringCreateMutable(0, 2 * sizeof(digest));
186 for (unsigned int ix = 0; ix < sizeof(digest); ++ix) {
187 CFStringAppendFormat(hex, 0, CFSTR("%02X"), digest[ix]);
188 }
189 return hex;
190 }
191
192 static void testsync(const char *name, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), CFStringRef msg, ...) {
193 CFErrorRef error = NULL;
194
195 /* Setup Alice engine, dataSource and peer for Alice to talk to Bob */
196 SOSDataSourceRef aliceDataSource = SOSTestDataSourceCreate();
197 SOSEngineRef aliceEngine;
198 ok(aliceEngine = SOSEngineCreate(aliceDataSource, &error), "create alice engine: %@", error);
199 CFReleaseNull(error);
200 CFStringRef bobID = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("Bob-%s"), name);
201
202 __block CFDataRef queued_message = NULL;
203
204 SOSPeerSendBlock enqueueMessage = ^bool (CFDataRef message, CFErrorRef *error) {
205 if (queued_message)
206 fail("We already had an unproccessed message");
207
208 queued_message = (CFDataRef) CFRetain(message);
209 return true;
210 };
211
212 CFDataRef (^dequeueMessage)() = ^CFDataRef () {
213 CFDataRef result = queued_message;
214 queued_message = NULL;
215
216 return result;
217 };
218
219 SOSPeerRef bobPeer;
220 ok(bobPeer = SOSPeerCreateSimple(bobID, kSOSPeerVersion, &error, enqueueMessage),
221 "create peer: %@", error);
222
223 /* Setup Bob engine, dataSource and peer for Bob to talk to Alice */
224 SOSDataSourceRef bobDataSource = SOSTestDataSourceCreate();
225 SOSEngineRef bobEngine;
226 ok(bobEngine = SOSEngineCreate(bobDataSource, &error), "create bob engine: %@", error);
227 CFReleaseNull(error);
228 CFStringRef aliceID = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("Alice-%s"), name);
229
230 SOSPeerRef alicePeer;
231 ok(alicePeer = SOSPeerCreateSimple(aliceID, kSOSPeerVersion, &error, enqueueMessage),
232 "create peer: %@", error);
233 CFReleaseNull(error);
234
235 /* Now call provided setup blocks to populate the dataSources with
236 interesting stuff. */
237 aliceInit(aliceDataSource);
238 bobInit(bobDataSource);
239
240 CFDataRef message;
241
242 va_list msgs;
243 va_start(msgs, msg);
244
245 int msg_index = 0;
246 bool alice = false;
247 for (;;) {
248 message = dequeueMessage();
249 msg_index++;
250 /* We are expecting a message and msg is it's digest. */
251 if (message) {
252 CFStringRef messageDigestStr = SOSMessageCopyDigestHex(message);
253 if (msg) {
254 bool handeled = SOSEngineHandleMessage(alice ? aliceEngine : bobEngine, alice ? bobPeer : alicePeer, message, &error);
255 if (!CFEqual(messageDigestStr, msg)) {
256 if (handeled) {
257 fail("%s %s received message [%d] digest %@ != %@ %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, message);
258 } else {
259 fail("%s %s failed to handle message [%d] digest %@ != %@ %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, message, error);
260 CFReleaseNull(error);
261 }
262 } else if (handeled) {
263 pass("%s %s handled message [%d] %@", name, alice ? "Alice" : "Bob", msg_index, message);
264 } else {
265 fail("%s %s failed to handle message [%d] %@: %@", name, alice ? "Alice" : "Bob", msg_index, message, error);
266 CFReleaseNull(error);
267 }
268 } else {
269 fail("%s %s sent extra message [%d] with digest %@: %@", name, alice ? "Bob" : "Alice", msg_index, messageDigestStr, message);
270 }
271 CFRelease(messageDigestStr);
272 CFRelease(message);
273 } else {
274 if (msg) {
275 fail("%s %s expected message [%d] with digest %@, none received", name, alice ? "Alice" : "Bob", msg_index, msg);
276 } else {
277 /* Compare alice and bobs dataSources databases. */
278 ok(CFEqual(SOSTestDataSourceGetDatabase(aliceDataSource), SOSTestDataSourceGetDatabase(bobDataSource)), "%s Alice and Bob are in sync", name);
279 }
280 }
281
282 if (msg) {
283 alice = !alice;
284 msg = va_arg(msgs, CFStringRef);
285 } else
286 break;
287 }
288
289 va_end(msgs);
290
291
292
293
294 SOSEngineDispose(aliceEngine); // Also disposes aliceDataSource
295 CFReleaseSafe(alicePeer);
296 CFReleaseSafe(aliceID);
297
298 SOSEngineDispose(bobEngine); // Also disposes bobDataSource
299 CFReleaseSafe(bobPeer);
300 CFReleaseSafe(bobID);
301 }
302
303 #if 0
304 static void synctests(void) {
305 // Sync between 2 empty dataSources
306 testsync("empty",
307 ^ (SOSDataSourceRef dataSource) {},
308 ^ (SOSDataSourceRef dataSource) {},
309 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
310 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
311 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
312 NULL);
313
314 // Sync a dataSource with one object to an empty dataSource
315 testsync("alice1",
316 ^ (SOSDataSourceRef dataSource) {
317 CFErrorRef error = NULL;
318 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service"));
319 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
320 CFReleaseSafe(object);
321 CFReleaseNull(error);
322 },
323 ^ (SOSDataSourceRef dataSource) {},
324 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
325 CFSTR("147B6C509908CC4A9FC4263973A842104A64CE01"),
326 CFSTR("019B494F3C06B48BB02C280AF1E19AD861A7003C"),
327 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
328 NULL);
329
330 // Sync a dataSource with one object to another dataSource with the same object
331 testsync("alice1bob1",
332 ^ (SOSDataSourceRef dataSource) {
333 CFErrorRef error = NULL;
334 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service"));
335 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
336 CFReleaseSafe(object);
337 CFReleaseNull(error);
338 },
339 ^ (SOSDataSourceRef dataSource) {
340 CFErrorRef error = NULL;
341 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service"));
342 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
343 CFReleaseSafe(object);
344 CFReleaseNull(error);
345 },
346 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
347 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
348 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
349 NULL);
350
351 // Sync a dataSource with one object to another dataSource with the same object
352 testsync("alice1bob2",
353 ^ (SOSDataSourceRef dataSource) {
354 CFErrorRef error = NULL;
355 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service"));
356 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
357 CFReleaseSafe(object);
358 CFReleaseNull(error);
359 },
360 ^ (SOSDataSourceRef dataSource) {
361 CFErrorRef error = NULL;
362 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service"));
363 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
364 CFReleaseSafe(object);
365 object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1"));
366 ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error);
367 CFReleaseSafe(object);
368 CFReleaseNull(error);
369 },
370 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
371 CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"),
372 CFSTR("9624EA855BBED6B668868BB723443E804D04F6A1"),
373 CFSTR("063E097CCD4FEB7F3610ED12B3DA828467314846"),
374 CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
375 NULL);
376
377 }
378 #endif
379
380 #endif
381
382 int sc_70_engine(int argc, char *const *argv)
383 {
384 plan_tests(kTestTestCount);
385
386 //tests();
387 //synctests();
388 //testsync(NULL, NULL, NULL, NULL);
389
390 return 0;
391 }