1//
2//  sc-60-peer.c
3//  sec
4//
5//  Created by Michael Brouwer on 8/2/12.
6//  Copyright 2012 Apple Inc. All rights reserved.
7//
8
9#include <SecureObjectSync/SOSPeer.h>
10
11#include "SOSCircle_regressions.h"
12
13#include <corecrypto/ccsha2.h>
14
15#include <Security/SecBase64.h>
16
17#include <utilities/SecCFWrappers.h>
18
19#include <stdint.h>
20
21static int kTestTestCount = 13;
22
23struct SOSTestTransport {
24    struct SOSTransport t;
25    unsigned t_msg_count;
26    uint8_t digest[CCSHA256_OUTPUT_SIZE];
27};
28
29
30static void tests(void)
31{
32    const unsigned kSOSPeerVersion = 0;
33
34    CFErrorRef error = NULL;
35    SOSPeerRef peer;
36
37    /* Create peer test. */
38    CFStringRef peer_id = CFSTR("peer 60");
39
40    __block unsigned msg_count = 0;
41    uint8_t msg_digest_buffer[CCSHA256_OUTPUT_SIZE];
42    uint8_t *msg_digest = msg_digest_buffer;
43
44    SOSPeerSendBlock sendBlock = ^bool (CFDataRef message, CFErrorRef *error) {
45        size_t msglen = CFDataGetLength(message);
46        const uint8_t *msg = CFDataGetBytePtr(message);
47        const struct ccdigest_info *sha256 = ccsha256_di();
48        if (msg_count++ == 0) {
49            /* message n=0 */
50            ccdigest(sha256, msglen, msg, msg_digest);
51        } else {
52            /* message n=n+1 */
53            ccdigest_di_decl(sha256, sha256_ctx);
54            ccdigest_init(sha256, sha256_ctx);
55            ccdigest_update(sha256, sha256_ctx, sizeof(msg_digest_buffer), msg_digest);
56            ccdigest_update(sha256, sha256_ctx, msglen, msg);
57            ccdigest_final(sha256, sha256_ctx, msg_digest);
58        }
59        size_t encmaxlen = SecBase64Encode(msg, msglen, NULL, 0);
60        CFMutableDataRef encoded = CFDataCreateMutable(NULL, encmaxlen);
61        CFDataSetLength(encoded, encmaxlen);
62        SecBase64Result rc;
63        char *enc = (char *)CFDataGetMutableBytePtr(encoded);
64#ifndef NDEBUG
65        size_t enclen =
66#endif
67            SecBase64Encode2(msg, msglen,
68                             enc,
69                             encmaxlen, kSecB64_F_LINE_LEN_USE_PARAM,
70                             64, &rc);
71        assert(enclen < INT32_MAX);
72
73//      printf("=== BEGIN SOSMESSAGE ===\n%.*s\n=== END SOSMESSAGE ===\n", (int)enclen, enc);
74
75        CFRelease(encoded);
76        return true;
77    };
78
79
80    ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error, sendBlock),
81       "create peer: %@", error);
82    CFReleaseNull(error);
83
84    /* Send a test message. */
85    is((int)msg_count, 0, "no message sent yet");
86    size_t msglen = 10;
87    uint8_t msg[msglen];
88    memcpy(msg, "0123456789", msglen);
89    CFDataRef message = CFDataCreate(NULL, msg, msglen);
90    ok(SOSPeerSendMessage(peer, message, &error),
91       "send message to peer: %@", error);
92    CFReleaseNull(error);
93    is((int)msg_count, 1, "We sent %d/1 messages", msg_count);
94    CFRelease(message);
95
96    /* Check the peer's version. */
97    is(SOSPeerGetVersion(peer), kSOSPeerVersion, "version is correct");
98
99    /* Get the peer's manifest. */
100    SOSManifestRef manifest = SOSPeerCopyManifest(peer, &error);
101    ok(manifest == NULL, "No manifest yet for this peer: %@", error);
102    CFReleaseNull(error);
103    CFReleaseNull(manifest);
104
105    /* Get the peer's manifest digest. */
106    CFDataRef digest = SOSPeerCopyManifestDigest(peer, &error);
107    ok(digest == NULL, "No digest yet for this peer's manifest: %@", error);
108    CFReleaseNull(error);
109    CFReleaseNull(digest);
110
111    ok(manifest = SOSManifestCreateWithBytes(NULL, 0, &error), "Create empty manifest: %@", error);
112    CFReleaseNull(error);
113    ok(SOSPeerSetManifest(peer, manifest, &error), "Set empty manifest on peer: %@", error);
114    CFReleaseNull(error);
115
116    /* Get the peer's empty manifest digest. */
117    digest = SOSPeerCopyManifestDigest(peer, &error);
118    ok(digest, "Got a digest: %@ this peer's manifest: %@", digest, error);
119    CFReleaseNull(error);
120
121    /* Clean up. */
122    SOSPeerDispose(peer);
123
124    SOSPeerRef reinflated_peer = NULL;
125    ok(reinflated_peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error, sendBlock),
126       "create peer: %@", error);
127    CFReleaseNull(error);
128
129    CFDataRef digestAfterReinflate = SOSPeerCopyManifestDigest(reinflated_peer, &error);
130    ok(digest != NULL, "Got NULL after reinflate (%@)", error);
131    ok(CFEqual(digest, digestAfterReinflate), "Compare digest after reinflate, before: %@ after: %@", digest, digestAfterReinflate);
132    CFReleaseNull(error);
133
134    SOSPeerDispose(reinflated_peer);
135
136    CFReleaseNull(digestAfterReinflate);
137    CFReleaseNull(digest);
138}
139
140int sc_60_peer(int argc, char *const *argv)
141{
142    plan_tests(kTestTestCount);
143
144    tests();
145
146	return 0;
147}
148