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