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