1
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <limits.h>
5 #include <string.h>
6
7 #include "core.h"
8 #include "crypto_aead_chacha20poly1305.h"
9 #include "crypto_onetimeauth_poly1305.h"
10 #include "crypto_stream_chacha20.h"
11 #include "crypto_verify_16.h"
12 #include "randombytes.h"
13 #include "utils.h"
14
15 #include "private/common.h"
16
17 static const unsigned char _pad0[16] = { 0 };
18
19 int
crypto_aead_chacha20poly1305_encrypt_detached(unsigned char * c,unsigned char * mac,unsigned long long * maclen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)20 crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
21 unsigned char *mac,
22 unsigned long long *maclen_p,
23 const unsigned char *m,
24 unsigned long long mlen,
25 const unsigned char *ad,
26 unsigned long long adlen,
27 const unsigned char *nsec,
28 const unsigned char *npub,
29 const unsigned char *k)
30 {
31 crypto_onetimeauth_poly1305_state state;
32 unsigned char block0[64U];
33 unsigned char slen[8U];
34
35 (void) nsec;
36 crypto_stream_chacha20(block0, sizeof block0, npub, k);
37 crypto_onetimeauth_poly1305_init(&state, block0);
38 sodium_memzero(block0, sizeof block0);
39
40 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
41 STORE64_LE(slen, (uint64_t) adlen);
42 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
43
44 crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
45
46 crypto_onetimeauth_poly1305_update(&state, c, mlen);
47 STORE64_LE(slen, (uint64_t) mlen);
48 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
49
50 crypto_onetimeauth_poly1305_final(&state, mac);
51 sodium_memzero(&state, sizeof state);
52
53 if (maclen_p != NULL) {
54 *maclen_p = crypto_aead_chacha20poly1305_ABYTES;
55 }
56 return 0;
57 }
58
59 int
crypto_aead_chacha20poly1305_encrypt(unsigned char * c,unsigned long long * clen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)60 crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
61 unsigned long long *clen_p,
62 const unsigned char *m,
63 unsigned long long mlen,
64 const unsigned char *ad,
65 unsigned long long adlen,
66 const unsigned char *nsec,
67 const unsigned char *npub,
68 const unsigned char *k)
69 {
70 unsigned long long clen = 0ULL;
71 int ret;
72
73 if (mlen > crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX) {
74 sodium_misuse();
75 }
76 ret = crypto_aead_chacha20poly1305_encrypt_detached(c,
77 c + mlen, NULL,
78 m, mlen,
79 ad, adlen,
80 nsec, npub, k);
81 if (clen_p != NULL) {
82 if (ret == 0) {
83 clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
84 }
85 *clen_p = clen;
86 }
87 return ret;
88 }
89
90 int
crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char * c,unsigned char * mac,unsigned long long * maclen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)91 crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
92 unsigned char *mac,
93 unsigned long long *maclen_p,
94 const unsigned char *m,
95 unsigned long long mlen,
96 const unsigned char *ad,
97 unsigned long long adlen,
98 const unsigned char *nsec,
99 const unsigned char *npub,
100 const unsigned char *k)
101 {
102 crypto_onetimeauth_poly1305_state state;
103 unsigned char block0[64U];
104 unsigned char slen[8U];
105
106 (void) nsec;
107 crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
108 crypto_onetimeauth_poly1305_init(&state, block0);
109 sodium_memzero(block0, sizeof block0);
110
111 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
112 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
113
114 crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k);
115
116 crypto_onetimeauth_poly1305_update(&state, c, mlen);
117 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
118
119 STORE64_LE(slen, (uint64_t) adlen);
120 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
121
122 STORE64_LE(slen, (uint64_t) mlen);
123 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
124
125 crypto_onetimeauth_poly1305_final(&state, mac);
126 sodium_memzero(&state, sizeof state);
127
128 if (maclen_p != NULL) {
129 *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
130 }
131 return 0;
132 }
133
134 int
crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char * c,unsigned long long * clen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)135 crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
136 unsigned long long *clen_p,
137 const unsigned char *m,
138 unsigned long long mlen,
139 const unsigned char *ad,
140 unsigned long long adlen,
141 const unsigned char *nsec,
142 const unsigned char *npub,
143 const unsigned char *k)
144 {
145 unsigned long long clen = 0ULL;
146 int ret;
147
148 if (mlen > crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX) {
149 sodium_misuse();
150 }
151 ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c,
152 c + mlen, NULL,
153 m, mlen,
154 ad, adlen,
155 nsec, npub, k);
156 if (clen_p != NULL) {
157 if (ret == 0) {
158 clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES;
159 }
160 *clen_p = clen;
161 }
162 return ret;
163 }
164
165 int
crypto_aead_chacha20poly1305_decrypt_detached(unsigned char * m,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * mac,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)166 crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
167 unsigned char *nsec,
168 const unsigned char *c,
169 unsigned long long clen,
170 const unsigned char *mac,
171 const unsigned char *ad,
172 unsigned long long adlen,
173 const unsigned char *npub,
174 const unsigned char *k)
175 {
176 crypto_onetimeauth_poly1305_state state;
177 unsigned char block0[64U];
178 unsigned char slen[8U];
179 unsigned char computed_mac[crypto_aead_chacha20poly1305_ABYTES];
180 unsigned long long mlen;
181 int ret;
182
183 (void) nsec;
184 crypto_stream_chacha20(block0, sizeof block0, npub, k);
185 crypto_onetimeauth_poly1305_init(&state, block0);
186 sodium_memzero(block0, sizeof block0);
187
188 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
189 STORE64_LE(slen, (uint64_t) adlen);
190 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
191
192 mlen = clen;
193 crypto_onetimeauth_poly1305_update(&state, c, mlen);
194 STORE64_LE(slen, (uint64_t) mlen);
195 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
196
197 crypto_onetimeauth_poly1305_final(&state, computed_mac);
198 sodium_memzero(&state, sizeof state);
199
200 COMPILER_ASSERT(sizeof computed_mac == 16U);
201 ret = crypto_verify_16(computed_mac, mac);
202 sodium_memzero(computed_mac, sizeof computed_mac);
203 if (m == NULL) {
204 return ret;
205 }
206 if (ret != 0) {
207 memset(m, 0, mlen);
208 return -1;
209 }
210 crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k);
211
212 return 0;
213 }
214
215 int
crypto_aead_chacha20poly1305_decrypt(unsigned char * m,unsigned long long * mlen_p,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)216 crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
217 unsigned long long *mlen_p,
218 unsigned char *nsec,
219 const unsigned char *c,
220 unsigned long long clen,
221 const unsigned char *ad,
222 unsigned long long adlen,
223 const unsigned char *npub,
224 const unsigned char *k)
225 {
226 unsigned long long mlen = 0ULL;
227 int ret = -1;
228
229 if (clen >= crypto_aead_chacha20poly1305_ABYTES) {
230 ret = crypto_aead_chacha20poly1305_decrypt_detached
231 (m, nsec,
232 c, clen - crypto_aead_chacha20poly1305_ABYTES,
233 c + clen - crypto_aead_chacha20poly1305_ABYTES,
234 ad, adlen, npub, k);
235 }
236 if (mlen_p != NULL) {
237 if (ret == 0) {
238 mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
239 }
240 *mlen_p = mlen;
241 }
242 return ret;
243 }
244
245 int
crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char * m,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * mac,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)246 crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
247 unsigned char *nsec,
248 const unsigned char *c,
249 unsigned long long clen,
250 const unsigned char *mac,
251 const unsigned char *ad,
252 unsigned long long adlen,
253 const unsigned char *npub,
254 const unsigned char *k)
255 {
256 crypto_onetimeauth_poly1305_state state;
257 unsigned char block0[64U];
258 unsigned char slen[8U];
259 unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
260 unsigned long long mlen;
261 int ret;
262
263 (void) nsec;
264 crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
265 crypto_onetimeauth_poly1305_init(&state, block0);
266 sodium_memzero(block0, sizeof block0);
267
268 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
269 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
270
271 mlen = clen;
272 crypto_onetimeauth_poly1305_update(&state, c, mlen);
273 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
274
275 STORE64_LE(slen, (uint64_t) adlen);
276 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
277
278 STORE64_LE(slen, (uint64_t) mlen);
279 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
280
281 crypto_onetimeauth_poly1305_final(&state, computed_mac);
282 sodium_memzero(&state, sizeof state);
283
284 COMPILER_ASSERT(sizeof computed_mac == 16U);
285 ret = crypto_verify_16(computed_mac, mac);
286 sodium_memzero(computed_mac, sizeof computed_mac);
287 if (m == NULL) {
288 return ret;
289 }
290 if (ret != 0) {
291 memset(m, 0, mlen);
292 return -1;
293 }
294 crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k);
295
296 return 0;
297 }
298
299 int
crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char * m,unsigned long long * mlen_p,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)300 crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
301 unsigned long long *mlen_p,
302 unsigned char *nsec,
303 const unsigned char *c,
304 unsigned long long clen,
305 const unsigned char *ad,
306 unsigned long long adlen,
307 const unsigned char *npub,
308 const unsigned char *k)
309 {
310 unsigned long long mlen = 0ULL;
311 int ret = -1;
312
313 if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) {
314 ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
315 (m, nsec,
316 c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
317 c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
318 ad, adlen, npub, k);
319 }
320 if (mlen_p != NULL) {
321 if (ret == 0) {
322 mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES;
323 }
324 *mlen_p = mlen;
325 }
326 return ret;
327 }
328
329 size_t
crypto_aead_chacha20poly1305_ietf_keybytes(void)330 crypto_aead_chacha20poly1305_ietf_keybytes(void)
331 {
332 return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
333 }
334
335 size_t
crypto_aead_chacha20poly1305_ietf_npubbytes(void)336 crypto_aead_chacha20poly1305_ietf_npubbytes(void)
337 {
338 return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
339 }
340
341 size_t
crypto_aead_chacha20poly1305_ietf_nsecbytes(void)342 crypto_aead_chacha20poly1305_ietf_nsecbytes(void)
343 {
344 return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
345 }
346
347 size_t
crypto_aead_chacha20poly1305_ietf_abytes(void)348 crypto_aead_chacha20poly1305_ietf_abytes(void)
349 {
350 return crypto_aead_chacha20poly1305_ietf_ABYTES;
351 }
352
353 size_t
crypto_aead_chacha20poly1305_ietf_messagebytes_max(void)354 crypto_aead_chacha20poly1305_ietf_messagebytes_max(void)
355 {
356 return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX;
357 }
358
359 void
crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES])360 crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES])
361 {
362 randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
363 }
364
365 size_t
crypto_aead_chacha20poly1305_keybytes(void)366 crypto_aead_chacha20poly1305_keybytes(void)
367 {
368 return crypto_aead_chacha20poly1305_KEYBYTES;
369 }
370
371 size_t
crypto_aead_chacha20poly1305_npubbytes(void)372 crypto_aead_chacha20poly1305_npubbytes(void)
373 {
374 return crypto_aead_chacha20poly1305_NPUBBYTES;
375 }
376
377 size_t
crypto_aead_chacha20poly1305_nsecbytes(void)378 crypto_aead_chacha20poly1305_nsecbytes(void)
379 {
380 return crypto_aead_chacha20poly1305_NSECBYTES;
381 }
382
383 size_t
crypto_aead_chacha20poly1305_abytes(void)384 crypto_aead_chacha20poly1305_abytes(void)
385 {
386 return crypto_aead_chacha20poly1305_ABYTES;
387 }
388
389 size_t
crypto_aead_chacha20poly1305_messagebytes_max(void)390 crypto_aead_chacha20poly1305_messagebytes_max(void)
391 {
392 return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX;
393 }
394
395 void
crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES])396 crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES])
397 {
398 randombytes_buf(k, crypto_aead_chacha20poly1305_KEYBYTES);
399 }
400