1 
2 #define TEST_NAME "chacha20"
3 #include "cmptest.h"
4 
5 static
6 void tv(void)
7 {
8     static struct {
9         const char *key_hex;
10         const char *nonce_hex;
11     } tests[]
12       = { { "0000000000000000000000000000000000000000000000000000000000000000",
13             "0000000000000000" },
14           { "0000000000000000000000000000000000000000000000000000000000000001",
15             "0000000000000000" },
16           { "0000000000000000000000000000000000000000000000000000000000000000",
17             "0000000000000001" },
18           { "0000000000000000000000000000000000000000000000000000000000000000",
19             "0100000000000000" },
20           { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
21             "0001020304050607" } };
22     unsigned char  key[crypto_stream_chacha20_KEYBYTES];
23     unsigned char  nonce[crypto_stream_chacha20_NONCEBYTES];
24     unsigned char *part;
25     unsigned char  out[160];
26     unsigned char  zero[160];
27     char           out_hex[160 * 2 + 1];
28     size_t         i = 0U;
29     size_t         plen;
30 
31     memset(zero, 0, sizeof zero);
32     do {
33         sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex,
34                        strlen(tests[i].key_hex), NULL, NULL, NULL);
35         sodium_hex2bin(nonce, sizeof nonce, tests[i].nonce_hex,
36                        strlen(tests[i].nonce_hex), NULL, NULL, NULL);
37         crypto_stream_chacha20(out, sizeof out, nonce, key);
38         sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
39         printf("[%s]\n", out_hex);
40         for (plen = 1U; plen < sizeof out; plen++) {
41             part = (unsigned char *) sodium_malloc(plen);
42             crypto_stream_chacha20_xor(part, out, plen, nonce, key);
43             if (memcmp(part, zero, plen) != 0) {
44                 printf("Failed with length %lu\n", (unsigned long) plen);
45             }
46             sodium_free(part);
47         }
48     } while (++i < (sizeof tests) / (sizeof tests[0]));
49     assert(66 <= sizeof out);
50     for (plen = 1U; plen < 66; plen += 3) {
51         memset(out, (int) (plen & 0xff), sizeof out);
52         crypto_stream_chacha20(out, plen, nonce, key);
53         sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
54         printf("[%s]\n", out_hex);
55     }
56     randombytes_buf(out, sizeof out);
57     crypto_stream_chacha20(out, sizeof out, nonce, key);
58     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
59     printf("[%s]\n", out_hex);
60 
61     assert(crypto_stream_chacha20(out, 0U, nonce, key) == 0);
62     assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0);
63     assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0);
64     assert(crypto_stream_chacha20_xor_ic(out, out, 0U, nonce, 1U, key) == 0);
65 
66     memset(out, 0x42, sizeof out);
67     crypto_stream_chacha20_xor(out, out, sizeof out, nonce, key);
68     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
69     printf("[%s]\n", out_hex);
70 
71     crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 0U, key);
72     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
73     printf("[%s]\n", out_hex);
74 
75     crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 1U, key);
76     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
77     printf("[%s]\n", out_hex);
78 }
79 
80 static
81 void tv_ietf(void)
82 {
83     static struct {
84         const char *key_hex;
85         const char *nonce_hex;
86         uint32_t    ic;
87     } tests[]
88       = { { "0000000000000000000000000000000000000000000000000000000000000000",
89             "000000000000000000000000",
90             0U },
91           { "0000000000000000000000000000000000000000000000000000000000000000",
92             "000000000000000000000000",
93             1U },
94           { "0000000000000000000000000000000000000000000000000000000000000001",
95             "000000000000000000000000",
96             1U },
97           { "00ff000000000000000000000000000000000000000000000000000000000000",
98             "000000000000000000000000",
99             2U },
100           { "0000000000000000000000000000000000000000000000000000000000000000",
101             "000000000000000000000002",
102             0U },
103           { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
104             "000000090000004a00000000",
105             1U },
106           { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
107             "000000090000004a00000000",
108             0xffffffff }};
109     unsigned char  key[crypto_stream_chacha20_KEYBYTES];
110     unsigned char  nonce[crypto_stream_chacha20_IETF_NONCEBYTES];
111     unsigned char *part;
112     unsigned char  out[160];
113     unsigned char  zero[160];
114     char           out_hex[160 * 2 + 1];
115     size_t         i = 0U;
116     size_t         plen;
117 
118     memset(zero, 0, sizeof zero);
119     do {
120         sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex,
121                        strlen(tests[i].key_hex), ": ", NULL, NULL);
122         sodium_hex2bin(nonce, sizeof nonce, tests[i].nonce_hex,
123                        strlen(tests[i].nonce_hex), ": ", NULL, NULL);
124         memset(out, 0, sizeof out);
125         crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, tests[i].ic, key);
126         sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
127         printf("[%s]\n", out_hex);
128         for (plen = 1U; plen < sizeof out; plen++) {
129             part = (unsigned char *) sodium_malloc(plen);
130             crypto_stream_chacha20_ietf_xor_ic(part, out, plen, nonce, tests[i].ic, key);
131             if (memcmp(part, zero, plen) != 0) {
132                 printf("Failed with length %lu\n", (unsigned long) plen);
133             }
134             sodium_free(part);
135         }
136     } while (++i < (sizeof tests) / (sizeof tests[0]));
137     assert(66 <= sizeof out);
138     for (plen = 1U; plen < 66; plen += 3) {
139         memset(out, (int) (plen & 0xff), sizeof out);
140         crypto_stream_chacha20(out, plen, nonce, key);
141         sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
142         printf("[%s]\n", out_hex);
143     }
144     randombytes_buf(out, sizeof out);
145     crypto_stream_chacha20_ietf(out, sizeof out, nonce, key);
146     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
147     printf("[%s]\n", out_hex);
148 
149     assert(crypto_stream_chacha20_ietf(out, 0U, nonce, key) == 0);
150     assert(crypto_stream_chacha20_ietf_xor(out, out, 0U, nonce, key) == 0);
151     assert(crypto_stream_chacha20_ietf_xor(out, out, 0U, nonce, key) == 0);
152     assert(crypto_stream_chacha20_ietf_xor_ic(out, out, 0U, nonce, 1U, key) == 0);
153 
154     memset(out, 0x42, sizeof out);
155     crypto_stream_chacha20_ietf_xor(out, out, sizeof out, nonce, key);
156     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
157     printf("[%s]\n", out_hex);
158 
159     crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, 0U, key);
160     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
161     printf("[%s]\n", out_hex);
162 
163     crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, 1U, key);
164     sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
165     printf("[%s]\n", out_hex);
166 }
167 
168 int
169 main(void)
170 {
171     tv();
172     tv_ietf();
173 
174     assert(crypto_stream_chacha20_keybytes() > 0U);
175     assert(crypto_stream_chacha20_keybytes() == crypto_stream_chacha20_KEYBYTES);
176     assert(crypto_stream_chacha20_noncebytes() > 0U);
177     assert(crypto_stream_chacha20_noncebytes() == crypto_stream_chacha20_NONCEBYTES);
178     assert(crypto_stream_chacha20_messagebytes_max() == crypto_stream_chacha20_MESSAGEBYTES_MAX);
179     assert(crypto_stream_chacha20_ietf_keybytes() > 0U);
180     assert(crypto_stream_chacha20_ietf_keybytes() == crypto_stream_chacha20_ietf_KEYBYTES);
181     assert(crypto_stream_chacha20_ietf_noncebytes() > 0U);
182     assert(crypto_stream_chacha20_ietf_noncebytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
183     assert(crypto_stream_chacha20_ietf_messagebytes_max() == crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
184 
185     return 0;
186 }
187