1
2#define TEST_NAME "aead_chacha20poly1305"
3#include "cmptest.h"
4
5static int
6tv(void)
7{
8#undef  MLEN
9#define MLEN 10U
10#undef  ADLEN
11#define ADLEN 10U
12#undef  CLEN
13#define CLEN (MLEN + crypto_aead_chacha20poly1305_ABYTES)
14    static const unsigned char firstkey[crypto_aead_chacha20poly1305_KEYBYTES]
15        = { 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf,
16            0x57, 0xf3, 0xbe, 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27,
17            0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07 };
18    static const unsigned char m[MLEN]
19        = { 0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca };
20    static const unsigned char nonce[crypto_aead_chacha20poly1305_NPUBBYTES]
21        = { 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a };
22    static const unsigned char ad[ADLEN]
23        = { 0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0 };
24    unsigned char *c = (unsigned char *) sodium_malloc(CLEN);
25    unsigned char *detached_c = (unsigned char *) sodium_malloc(MLEN);
26    unsigned char *mac = (unsigned char *) sodium_malloc(crypto_aead_chacha20poly1305_ABYTES);
27    unsigned char *m2 = (unsigned char *) sodium_malloc(MLEN);
28    unsigned long long found_clen;
29    unsigned long long found_maclen;
30    unsigned long long m2len;
31    size_t i;
32
33    crypto_aead_chacha20poly1305_encrypt(c, &found_clen, m, MLEN,
34                                         ad, ADLEN,
35                                         NULL, nonce, firstkey);
36    if (found_clen != CLEN) {
37        printf("found_clen is not properly set\n");
38    }
39    for (i = 0U; i < CLEN; ++i) {
40        printf(",0x%02x", (unsigned int) c[i]);
41        if (i % 8 == 7) {
42            printf("\n");
43        }
44    }
45    printf("\n");
46    crypto_aead_chacha20poly1305_encrypt_detached(detached_c,
47                                                  mac, &found_maclen,
48                                                  m, MLEN, ad, ADLEN,
49                                                  NULL, nonce, firstkey);
50    if (found_maclen != crypto_aead_chacha20poly1305_abytes()) {
51        printf("found_maclen is not properly set\n");
52    }
53    if (memcmp(detached_c, c, MLEN) != 0) {
54        printf("detached ciphertext is bogus\n");
55    }
56
57    if (crypto_aead_chacha20poly1305_decrypt(m2, &m2len, NULL, c, CLEN,
58                                             ad, ADLEN,
59                                             nonce, firstkey) != 0) {
60        printf("crypto_aead_chacha20poly1305_decrypt() failed\n");
61    }
62    if (m2len != MLEN) {
63        printf("m2len is not properly set\n");
64    }
65    if (memcmp(m, m2, MLEN) != 0) {
66        printf("m != m2\n");
67    }
68    memset(m2, 0, m2len);
69    assert(crypto_aead_chacha20poly1305_decrypt_detached(NULL, NULL,
70                                                         c, MLEN, mac,
71                                                         ad, ADLEN,
72                                                         nonce, firstkey) == 0);
73    if (crypto_aead_chacha20poly1305_decrypt_detached(m2, NULL,
74                                                      c, MLEN, mac,
75                                                      ad, ADLEN,
76                                                      nonce, firstkey) != 0) {
77        printf("crypto_aead_chacha20poly1305_decrypt_detached() failed\n");
78    }
79    if (memcmp(m, m2, MLEN) != 0) {
80        printf("detached m != m2\n");
81    }
82
83    for (i = 0U; i < CLEN; i++) {
84        c[i] ^= (i + 1U);
85        if (crypto_aead_chacha20poly1305_decrypt(m2, NULL, NULL, c, CLEN,
86                                                 ad, ADLEN, nonce, firstkey)
87            == 0 || memcmp(m, m2, MLEN) == 0) {
88            printf("message can be forged\n");
89        }
90        c[i] ^= (i + 1U);
91    }
92
93    crypto_aead_chacha20poly1305_encrypt(c, &found_clen, m, MLEN,
94                                         NULL, 0U, NULL, nonce, firstkey);
95    if (found_clen != CLEN) {
96        printf("found_clen is not properly set (adlen=0)\n");
97    }
98    for (i = 0U; i < CLEN; ++i) {
99        printf(",0x%02x", (unsigned int) c[i]);
100        if (i % 8 == 7) {
101            printf("\n");
102        }
103    }
104    printf("\n");
105
106    if (crypto_aead_chacha20poly1305_decrypt(m2, &m2len, NULL, c, CLEN,
107                                             NULL, 0U, nonce, firstkey) != 0) {
108        printf("crypto_aead_chacha20poly1305_decrypt() failed (adlen=0)\n");
109    }
110    if (m2len != MLEN) {
111        printf("m2len is not properly set (adlen=0)\n");
112    }
113    if (memcmp(m, m2, MLEN) != 0) {
114        printf("m != m2 (adlen=0)\n");
115    }
116    m2len = 1;
117    if (crypto_aead_chacha20poly1305_decrypt(
118            m2, &m2len, NULL, NULL,
119            randombytes_uniform(crypto_aead_chacha20poly1305_ABYTES),
120            NULL, 0U, nonce, firstkey) != -1) {
121        printf("crypto_aead_chacha20poly1305_decrypt() worked with a short "
122               "ciphertext\n");
123    }
124    if (m2len != 0) {
125        printf("Message length should have been set to zero after a failure\n");
126    }
127    m2len = 1;
128    if (crypto_aead_chacha20poly1305_decrypt(m2, &m2len, NULL, c, 0U, NULL, 0U,
129                                             nonce, firstkey) != -1) {
130        printf("crypto_aead_chacha20poly1305_decrypt() worked with an empty "
131               "ciphertext\n");
132    }
133    if (m2len != 0) {
134        printf("Message length should have been set to zero after a failure\n");
135    }
136
137    memcpy(c, m, MLEN);
138    crypto_aead_chacha20poly1305_encrypt(c, &found_clen, c, MLEN,
139                                         NULL, 0U, NULL, nonce, firstkey);
140    if (found_clen != CLEN) {
141        printf("found_clen is not properly set (adlen=0)\n");
142    }
143    for (i = 0U; i < CLEN; ++i) {
144        printf(",0x%02x", (unsigned int) c[i]);
145        if (i % 8 == 7) {
146            printf("\n");
147        }
148    }
149    printf("\n");
150
151    if (crypto_aead_chacha20poly1305_decrypt(c, &m2len, NULL, c, CLEN,
152                                             NULL, 0U, nonce, firstkey) != 0) {
153        printf("crypto_aead_chacha20poly1305_decrypt() failed (adlen=0)\n");
154    }
155    if (m2len != MLEN) {
156        printf("m2len is not properly set (adlen=0)\n");
157    }
158    if (memcmp(m, c, MLEN) != 0) {
159        printf("m != c (adlen=0)\n");
160    }
161
162    sodium_free(c);
163    sodium_free(detached_c);
164    sodium_free(mac);
165    sodium_free(m2);
166
167    assert(crypto_aead_chacha20poly1305_keybytes() > 0U);
168    assert(crypto_aead_chacha20poly1305_npubbytes() > 0U);
169    assert(crypto_aead_chacha20poly1305_nsecbytes() == 0U);
170    assert(crypto_aead_chacha20poly1305_messagebytes_max() > 0U);
171    assert(crypto_aead_chacha20poly1305_messagebytes_max() == crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX);
172    assert(crypto_aead_chacha20poly1305_keybytes() == crypto_aead_chacha20poly1305_KEYBYTES);
173    assert(crypto_aead_chacha20poly1305_nsecbytes() == crypto_aead_chacha20poly1305_NSECBYTES);
174    assert(crypto_aead_chacha20poly1305_npubbytes() == crypto_aead_chacha20poly1305_NPUBBYTES);
175    assert(crypto_aead_chacha20poly1305_abytes() == crypto_aead_chacha20poly1305_ABYTES);
176
177    return 0;
178}
179
180static int
181tv_ietf(void)
182{
183#undef  MLEN
184#define MLEN 114U
185#undef  ADLEN
186#define ADLEN 12U
187#undef  CLEN
188#define CLEN (MLEN + crypto_aead_chacha20poly1305_ietf_ABYTES)
189    static const unsigned char firstkey[crypto_aead_chacha20poly1305_ietf_KEYBYTES]
190        = {
191            0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
192            0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
193            0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
194            0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
195        };
196#undef  MESSAGE
197#define MESSAGE "Ladies and Gentlemen of the class of '99: If I could offer you " \
198"only one tip for the future, sunscreen would be it."
199    unsigned char *m = (unsigned char *) sodium_malloc(MLEN);
200    static const unsigned char nonce[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]
201        = { 0x07, 0x00, 0x00, 0x00,
202            0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 };
203    static const unsigned char ad[ADLEN]
204        = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 };
205    unsigned char *c = (unsigned char *) sodium_malloc(CLEN);
206    unsigned char *detached_c = (unsigned char *) sodium_malloc(MLEN);
207    unsigned char *mac = (unsigned char *) sodium_malloc(crypto_aead_chacha20poly1305_ietf_ABYTES);
208    unsigned char *m2 = (unsigned char *) sodium_malloc(MLEN);
209    unsigned long long found_clen;
210    unsigned long long found_maclen;
211    unsigned long long m2len;
212    size_t i;
213
214    assert(sizeof MESSAGE - 1U == MLEN);
215    memcpy(m, MESSAGE, MLEN);
216    crypto_aead_chacha20poly1305_ietf_encrypt(c, &found_clen, m, MLEN,
217                                              ad, ADLEN,
218                                              NULL, nonce, firstkey);
219    if (found_clen != MLEN + crypto_aead_chacha20poly1305_ietf_abytes()) {
220        printf("found_clen is not properly set\n");
221    }
222    for (i = 0U; i < CLEN; ++i) {
223        printf(",0x%02x", (unsigned int) c[i]);
224        if (i % 8 == 7) {
225            printf("\n");
226        }
227    }
228    printf("\n");
229    crypto_aead_chacha20poly1305_ietf_encrypt_detached(detached_c,
230                                                       mac, &found_maclen,
231                                                       m, MLEN,
232                                                       ad, ADLEN,
233                                                       NULL, nonce, firstkey);
234    if (found_maclen != crypto_aead_chacha20poly1305_ietf_abytes()) {
235        printf("found_maclen is not properly set\n");
236    }
237    if (memcmp(detached_c, c, MLEN) != 0) {
238        printf("detached ciphertext is bogus\n");
239    }
240
241    if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, CLEN, ad,
242                                                  ADLEN, nonce, firstkey) != 0) {
243        printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed\n");
244    }
245    if (m2len != MLEN) {
246        printf("m2len is not properly set\n");
247    }
248    if (memcmp(m, m2, MLEN) != 0) {
249        printf("m != m2\n");
250    }
251    memset(m2, 0, m2len);
252    assert(crypto_aead_chacha20poly1305_ietf_decrypt_detached(NULL, NULL,
253                                                              c, MLEN, mac,
254                                                              ad, ADLEN,
255                                                              nonce, firstkey) == 0);
256    if (crypto_aead_chacha20poly1305_ietf_decrypt_detached(m2, NULL,
257                                                           c, MLEN, mac,
258                                                           ad, ADLEN,
259                                                           nonce, firstkey) != 0) {
260        printf("crypto_aead_chacha20poly1305_ietf_decrypt_detached() failed\n");
261    }
262    if (memcmp(m, m2, MLEN) != 0) {
263        printf("detached m != m2\n");
264    }
265
266    for (i = 0U; i < CLEN; i++) {
267        c[i] ^= (i + 1U);
268        if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, NULL, NULL, c, CLEN,
269                                                      ad, ADLEN, nonce, firstkey)
270            == 0 || memcmp(m, m2, MLEN) == 0) {
271            printf("message can be forged\n");
272        }
273        c[i] ^= (i + 1U);
274    }
275    crypto_aead_chacha20poly1305_ietf_encrypt(c, &found_clen, m, MLEN,
276                                              NULL, 0U, NULL, nonce, firstkey);
277    if (found_clen != CLEN) {
278        printf("clen is not properly set (adlen=0)\n");
279    }
280    for (i = 0U; i < CLEN; ++i) {
281        printf(",0x%02x", (unsigned int) c[i]);
282        if (i % 8 == 7) {
283            printf("\n");
284        }
285    }
286    printf("\n");
287    if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, CLEN,
288                                                  NULL, 0U, nonce, firstkey) != 0) {
289        printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed (adlen=0)\n");
290    }
291    if (m2len != MLEN) {
292        printf("m2len is not properly set (adlen=0)\n");
293    }
294    if (memcmp(m, m2, MLEN) != 0) {
295        printf("m != m2 (adlen=0)\n");
296    }
297    m2len = 1;
298    if (crypto_aead_chacha20poly1305_ietf_decrypt(
299            m2, &m2len, NULL, NULL,
300            randombytes_uniform(crypto_aead_chacha20poly1305_ietf_ABYTES),
301            NULL, 0U, nonce, firstkey) != -1) {
302        printf("crypto_aead_chacha20poly1305_ietf_decrypt() worked with a short "
303               "ciphertext\n");
304    }
305    if (m2len != 0) {
306        printf("Message length should have been set to zero after a failure\n");
307    }
308    m2len = 1;
309    if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, 0U, NULL, 0U,
310                                                  nonce, firstkey) != -1) {
311        printf("crypto_aead_chacha20poly1305_ietf_decrypt() worked with an empty "
312               "ciphertext\n");
313    }
314    if (m2len != 0) {
315        printf("Message length should have been set to zero after a failure\n");
316    }
317
318    memcpy(c, m, MLEN);
319    crypto_aead_chacha20poly1305_ietf_encrypt(c, &found_clen, c, MLEN,
320                                              NULL, 0U, NULL, nonce, firstkey);
321    if (found_clen != CLEN) {
322        printf("clen is not properly set (adlen=0)\n");
323    }
324    for (i = 0U; i < CLEN; ++i) {
325        printf(",0x%02x", (unsigned int) c[i]);
326        if (i % 8 == 7) {
327            printf("\n");
328        }
329    }
330    printf("\n");
331
332    if (crypto_aead_chacha20poly1305_ietf_decrypt(c, &m2len, NULL, c, CLEN,
333                                                  NULL, 0U, nonce, firstkey) != 0) {
334        printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed (adlen=0)\n");
335    }
336    if (m2len != MLEN) {
337        printf("m2len is not properly set (adlen=0)\n");
338    }
339    if (memcmp(m, c, MLEN) != 0) {
340        printf("m != c (adlen=0)\n");
341    }
342
343    sodium_free(c);
344    sodium_free(detached_c);
345    sodium_free(mac);
346    sodium_free(m2);
347    sodium_free(m);
348
349    assert(crypto_aead_chacha20poly1305_ietf_keybytes() > 0U);
350    assert(crypto_aead_chacha20poly1305_ietf_keybytes() == crypto_aead_chacha20poly1305_keybytes());
351    assert(crypto_aead_chacha20poly1305_ietf_npubbytes() > 0U);
352    assert(crypto_aead_chacha20poly1305_ietf_npubbytes() > crypto_aead_chacha20poly1305_npubbytes());
353    assert(crypto_aead_chacha20poly1305_ietf_nsecbytes() == 0U);
354    assert(crypto_aead_chacha20poly1305_ietf_nsecbytes() == crypto_aead_chacha20poly1305_nsecbytes());
355    assert(crypto_aead_chacha20poly1305_ietf_messagebytes_max() == crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
356    assert(crypto_aead_chacha20poly1305_IETF_KEYBYTES  == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
357    assert(crypto_aead_chacha20poly1305_IETF_NSECBYTES == crypto_aead_chacha20poly1305_ietf_NSECBYTES);
358    assert(crypto_aead_chacha20poly1305_IETF_NPUBBYTES == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
359    assert(crypto_aead_chacha20poly1305_IETF_ABYTES    == crypto_aead_chacha20poly1305_ietf_ABYTES);
360    assert(crypto_aead_chacha20poly1305_IETF_MESSAGEBYTES_MAX == crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
361
362    return 0;
363}
364
365int
366main(void)
367{
368    tv();
369    tv_ietf();
370
371    return 0;
372}
373