1
2 #define TEST_NAME "secretstream"
3 #include "cmptest.h"
4
5 int
main(void)6 main(void)
7 {
8 crypto_secretstream_xchacha20poly1305_state *state, *statesave;
9 crypto_secretstream_xchacha20poly1305_state state_copy;
10 unsigned char *ad;
11 unsigned char *header;
12 unsigned char *k;
13 unsigned char *c1, *c2, *c3, *csave;
14 unsigned char *m1, *m2, *m3;
15 unsigned char *m1_, *m2_, *m3_;
16 unsigned long long res_len;
17 size_t ad_len;
18 size_t m1_len, m2_len, m3_len;
19 int ret;
20 unsigned char tag;
21
22 state = (crypto_secretstream_xchacha20poly1305_state *)
23 sodium_malloc(crypto_secretstream_xchacha20poly1305_statebytes());
24 statesave = (crypto_secretstream_xchacha20poly1305_state *)
25 sodium_malloc(crypto_secretstream_xchacha20poly1305_statebytes());
26 header = (unsigned char *)
27 sodium_malloc(crypto_secretstream_xchacha20poly1305_HEADERBYTES);
28
29 ad_len = randombytes_uniform(100);
30 m1_len = randombytes_uniform(1000);
31 m2_len = randombytes_uniform(1000);
32 m3_len = randombytes_uniform(1000);
33
34 c1 = (unsigned char *)
35 sodium_malloc(m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
36 c2 = (unsigned char *)
37 sodium_malloc(m2_len + crypto_secretstream_xchacha20poly1305_ABYTES);
38 c3 = (unsigned char *)
39 sodium_malloc(m3_len + crypto_secretstream_xchacha20poly1305_ABYTES);
40 csave = (unsigned char *)
41 sodium_malloc((m1_len | m2_len | m3_len) + crypto_secretstream_xchacha20poly1305_ABYTES);
42
43 ad = (unsigned char *) sodium_malloc(ad_len);
44 m1 = (unsigned char *) sodium_malloc(m1_len);
45 m2 = (unsigned char *) sodium_malloc(m2_len);
46 m3 = (unsigned char *) sodium_malloc(m3_len);
47 m1_ = (unsigned char *) sodium_malloc(m1_len);
48 m2_ = (unsigned char *) sodium_malloc(m2_len);
49 m3_ = (unsigned char *) sodium_malloc(m3_len);
50
51 randombytes_buf(ad, ad_len);
52
53 randombytes_buf(m1, m1_len);
54 memcpy(m1_, m1, m1_len);
55 randombytes_buf(m2, m2_len);
56 memcpy(m2_, m2, m2_len);
57 randombytes_buf(m3, m3_len);
58 memcpy(m3_, m3, m3_len);
59
60 k = (unsigned char *)
61 sodium_malloc(crypto_secretstream_xchacha20poly1305_KEYBYTES);
62 crypto_secretstream_xchacha20poly1305_keygen(k);
63
64 /* push */
65
66 ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
67 assert(ret == 0);
68
69 ret = crypto_secretstream_xchacha20poly1305_push
70 (state, c1, &res_len, m1, m1_len, NULL, 0, 0);
71 assert(ret == 0);
72 assert(res_len == m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
73
74 ret = crypto_secretstream_xchacha20poly1305_push
75 (state, c2, NULL, m2, m2_len, ad, 0, 0);
76 assert(ret == 0);
77
78 ret = crypto_secretstream_xchacha20poly1305_push
79 (state, c3, NULL, m3, m3_len, ad, ad_len,
80 crypto_secretstream_xchacha20poly1305_TAG_FINAL);
81 assert(ret == 0);
82
83 /* pull */
84
85 ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
86 assert(ret == 0);
87
88 ret = crypto_secretstream_xchacha20poly1305_pull
89 (state, m1, &res_len, &tag,
90 c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
91 assert(ret == 0);
92 assert(tag == 0);
93 assert(memcmp(m1, m1_, m1_len) == 0);
94 assert(res_len == m1_len);
95
96 ret = crypto_secretstream_xchacha20poly1305_pull
97 (state, m2, NULL, &tag,
98 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
99 assert(ret == 0);
100 assert(tag == 0);
101 assert(memcmp(m2, m2_, m2_len) == 0);
102
103 if (ad_len > 0) {
104 ret = crypto_secretstream_xchacha20poly1305_pull
105 (state, m3, NULL, &tag,
106 c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
107 assert(ret == -1);
108 }
109 ret = crypto_secretstream_xchacha20poly1305_pull
110 (state, m3, NULL, &tag,
111 c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, ad, ad_len);
112 assert(ret == 0);
113 assert(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL);
114 assert(memcmp(m3, m3_, m3_len) == 0);
115
116 /* previous with FINAL tag */
117
118 ret = crypto_secretstream_xchacha20poly1305_pull
119 (state, m3, NULL, &tag,
120 c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, ad, ad_len);
121 assert(ret == -1);
122
123 /* previous without a tag */
124
125 ret = crypto_secretstream_xchacha20poly1305_pull
126 (state, m2, NULL, &tag,
127 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
128 assert(ret == -1);
129
130 /* short ciphertext */
131
132 ret = crypto_secretstream_xchacha20poly1305_pull
133 (state, m2, NULL, &tag, c2,
134 randombytes_uniform(crypto_secretstream_xchacha20poly1305_ABYTES),
135 NULL, 0);
136 assert(ret == -1);
137 ret = crypto_secretstream_xchacha20poly1305_pull
138 (state, m2, NULL, &tag, c2, 0, NULL, 0);
139 assert(ret == -1);
140
141 /* empty ciphertext */
142
143 ret = crypto_secretstream_xchacha20poly1305_pull
144 (state, m2, NULL, &tag, c2,
145 crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
146 assert(ret == -1);
147
148 /* without explicit rekeying */
149
150 ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
151 assert(ret == 0);
152 ret = crypto_secretstream_xchacha20poly1305_push
153 (state, c1, NULL, m1, m1_len, NULL, 0, 0);
154 assert(ret == 0);
155 ret = crypto_secretstream_xchacha20poly1305_push
156 (state, c2, NULL, m2, m2_len, NULL, 0, 0);
157 assert(ret == 0);
158
159 ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
160 assert(ret == 0);
161 ret = crypto_secretstream_xchacha20poly1305_pull
162 (state, m1, NULL, &tag,
163 c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
164 assert(ret == 0);
165 ret = crypto_secretstream_xchacha20poly1305_pull
166 (state, m2, NULL, &tag,
167 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
168 assert(ret == 0);
169
170 /* with explicit rekeying */
171
172 ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
173 assert(ret == 0);
174 ret = crypto_secretstream_xchacha20poly1305_push
175 (state, c1, NULL, m1, m1_len, NULL, 0, 0);
176 assert(ret == 0);
177
178 crypto_secretstream_xchacha20poly1305_rekey(state);
179
180 ret = crypto_secretstream_xchacha20poly1305_push
181 (state, c2, NULL, m2, m2_len, NULL, 0, 0);
182 assert(ret == 0);
183
184 ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
185 assert(ret == 0);
186 ret = crypto_secretstream_xchacha20poly1305_pull
187 (state, m1, NULL, &tag,
188 c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
189 assert(ret == 0);
190
191 ret = crypto_secretstream_xchacha20poly1305_pull
192 (state, m2, NULL, &tag,
193 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
194 assert(ret == -1);
195
196 crypto_secretstream_xchacha20poly1305_rekey(state);
197
198 ret = crypto_secretstream_xchacha20poly1305_pull
199 (state, m2, NULL, &tag,
200 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
201 assert(ret == 0);
202
203 /* with explicit rekeying using TAG_REKEY */
204
205 ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
206 assert(ret == 0);
207
208 memcpy(statesave, state, sizeof *state);
209
210 ret = crypto_secretstream_xchacha20poly1305_push
211 (state, c1, NULL, m1, m1_len, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_REKEY);
212 assert(ret == 0);
213
214 ret = crypto_secretstream_xchacha20poly1305_push
215 (state, c2, NULL, m2, m2_len, NULL, 0, 0);
216 assert(ret == 0);
217
218 memcpy(csave, c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES);
219
220 ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
221 assert(ret == 0);
222 ret = crypto_secretstream_xchacha20poly1305_pull
223 (state, m1, NULL, &tag,
224 c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, &tag, 0);
225 assert(ret == 0);
226 assert(tag == crypto_secretstream_xchacha20poly1305_TAG_REKEY);
227
228 ret = crypto_secretstream_xchacha20poly1305_pull
229 (state, m2, NULL, &tag,
230 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, &tag, 0);
231 assert(ret == 0);
232 assert(tag == 0);
233
234 memcpy(state, statesave, sizeof *state);
235
236 ret = crypto_secretstream_xchacha20poly1305_push
237 (state, c1, NULL, m1, m1_len, NULL, 0, 0);
238 assert(ret == 0);
239
240 ret = crypto_secretstream_xchacha20poly1305_push
241 (state, c2, NULL, m2, m2_len, NULL, 0, 0);
242 assert(ret == 0);
243
244 assert(memcmp(csave, c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES) != 0);
245
246 /* New stream */
247
248 ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
249 assert(ret == 0);
250
251 ret = crypto_secretstream_xchacha20poly1305_push
252 (state, c1, &res_len, m1, m1_len, NULL, 0,
253 crypto_secretstream_xchacha20poly1305_TAG_PUSH);
254 assert(ret == 0);
255 assert(res_len == m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
256
257 /* Force a counter overflow, check that the key has been updated
258 * even though the tag was not changed to REKEY */
259
260 memset(state->nonce, 0xff, 4U);
261 state_copy = *state;
262
263 ret = crypto_secretstream_xchacha20poly1305_push
264 (state, c2, NULL, m2, m2_len, ad, 0, 0);
265 assert(ret == 0);
266
267 assert(memcmp(state_copy.k, state->k, sizeof state->k) != 0);
268 assert(memcmp(state_copy.nonce, state->nonce, sizeof state->nonce) != 0);
269 assert(state->nonce[0] == 1U);
270 assert(sodium_is_zero(state->nonce + 1, 3U));
271
272 ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
273 assert(ret == 0);
274
275 ret = crypto_secretstream_xchacha20poly1305_pull
276 (state, m1, &res_len, &tag,
277 c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
278 assert(ret == 0);
279 assert(tag == crypto_secretstream_xchacha20poly1305_TAG_PUSH);
280 assert(memcmp(m1, m1_, m1_len) == 0);
281 assert(res_len == m1_len);
282
283 memset(state->nonce, 0xff, 4U);
284
285 ret = crypto_secretstream_xchacha20poly1305_pull
286 (state, m2, NULL, &tag,
287 c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
288 assert(ret == 0);
289 assert(tag == 0);
290 assert(memcmp(m2, m2_, m2_len) == 0);
291
292 sodium_free(m3_);
293 sodium_free(m2_);
294 sodium_free(m1_);
295 sodium_free(m3);
296 sodium_free(m2);
297 sodium_free(m1);
298 sodium_free(ad);
299 sodium_free(csave);
300 sodium_free(c3);
301 sodium_free(c2);
302 sodium_free(c1);
303 sodium_free(k);
304 sodium_free(header);
305 sodium_free(statesave);
306 sodium_free(state);
307
308 assert(crypto_secretstream_xchacha20poly1305_abytes() ==
309 crypto_secretstream_xchacha20poly1305_ABYTES);
310 assert(crypto_secretstream_xchacha20poly1305_headerbytes() ==
311 crypto_secretstream_xchacha20poly1305_HEADERBYTES);
312 assert(crypto_secretstream_xchacha20poly1305_keybytes() ==
313 crypto_secretstream_xchacha20poly1305_KEYBYTES);
314 assert(crypto_secretstream_xchacha20poly1305_messagebytes_max() ==
315 crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
316
317 assert(crypto_secretstream_xchacha20poly1305_tag_message() ==
318 crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
319 assert(crypto_secretstream_xchacha20poly1305_tag_push() ==
320 crypto_secretstream_xchacha20poly1305_TAG_PUSH);
321 assert(crypto_secretstream_xchacha20poly1305_tag_rekey() ==
322 crypto_secretstream_xchacha20poly1305_TAG_REKEY);
323 assert(crypto_secretstream_xchacha20poly1305_tag_final() ==
324 crypto_secretstream_xchacha20poly1305_TAG_FINAL);
325
326 printf("OK\n");
327
328 return 0;
329 }
330