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_aead_xchacha20poly1305.h"
10 #include "crypto_core_hchacha20.h"
11 #include "crypto_onetimeauth_poly1305.h"
12 #include "crypto_stream_chacha20.h"
13 #include "crypto_verify_16.h"
14 #include "randombytes.h"
15 #include "utils.h"
16
17 #include "private/chacha20_ietf_ext.h"
18 #include "private/common.h"
19
20 static const unsigned char _pad0[16] = { 0 };
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)21
22 static int
23 _encrypt_detached(unsigned char *c,
24 unsigned char *mac,
25 unsigned long long *maclen_p,
26 const unsigned char *m,
27 unsigned long long mlen,
28 const unsigned char *ad,
29 unsigned long long adlen,
30 const unsigned char *nsec,
31 const unsigned char *npub,
32 const unsigned char *k)
33 {
34 crypto_onetimeauth_poly1305_state state;
35 unsigned char block0[64U];
36 unsigned char slen[8U];
37
38 (void) nsec;
39 crypto_stream_chacha20_ietf_ext(block0, sizeof block0, npub, k);
40 crypto_onetimeauth_poly1305_init(&state, block0);
41 sodium_memzero(block0, sizeof block0);
42
43 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
44 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
45
46 crypto_stream_chacha20_ietf_ext_xor_ic(c, m, mlen, npub, 1U, k);
47
48 crypto_onetimeauth_poly1305_update(&state, c, mlen);
49 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
50
51 STORE64_LE(slen, (uint64_t) adlen);
52 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
53
54 STORE64_LE(slen, (uint64_t) mlen);
55 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
56
57 crypto_onetimeauth_poly1305_final(&state, mac);
58 sodium_memzero(&state, sizeof state);
59
60 if (maclen_p != NULL) {
61 *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
62 }
63 return 0;
64 }
65
66 static int
67 _decrypt_detached(unsigned char *m,
68 unsigned char *nsec,
69 const unsigned char *c,
70 unsigned long long clen,
71 const unsigned char *mac,
72 const unsigned char *ad,
73 unsigned long long adlen,
74 const unsigned char *npub,
75 const unsigned char *k)
76 {
77 crypto_onetimeauth_poly1305_state state;
78 unsigned char block0[64U];
79 unsigned char slen[8U];
80 unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
81 unsigned long long mlen;
82 int ret;
83
84 (void) nsec;
85 crypto_stream_chacha20_ietf_ext(block0, sizeof block0, npub, k);
86 crypto_onetimeauth_poly1305_init(&state, block0);
87 sodium_memzero(block0, sizeof block0);
88
89 crypto_onetimeauth_poly1305_update(&state, ad, adlen);
90 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
91
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)92 mlen = clen;
93 crypto_onetimeauth_poly1305_update(&state, c, mlen);
94 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
95
96 STORE64_LE(slen, (uint64_t) adlen);
97 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
98
99 STORE64_LE(slen, (uint64_t) mlen);
100 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
101
102 crypto_onetimeauth_poly1305_final(&state, computed_mac);
103 sodium_memzero(&state, sizeof state);
104
105 COMPILER_ASSERT(sizeof computed_mac == 16U);
106 ret = crypto_verify_16(computed_mac, mac);
107 sodium_memzero(computed_mac, sizeof computed_mac);
108 if (m == NULL) {
109 return ret;
110 }
111 if (ret != 0) {
112 memset(m, 0, mlen);
113 return -1;
114 }
115 crypto_stream_chacha20_ietf_ext_xor_ic(m, c, mlen, npub, 1U, k);
116
117 return 0;
118 }
119
120 int
121 crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char *c,
122 unsigned char *mac,
123 unsigned long long *maclen_p,
124 const unsigned char *m,
125 unsigned long long mlen,
126 const unsigned char *ad,
127 unsigned long long adlen,
128 const unsigned char *nsec,
129 const unsigned char *npub,
130 const unsigned char *k)
131 {
132 unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
133 unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
134 int ret;
135
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)136 crypto_core_hchacha20(k2, npub, k, NULL);
137 memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
138 crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
139 ret = _encrypt_detached(c, mac, maclen_p, m, mlen, ad, adlen,
140 nsec, npub2, k2);
141 sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
142
143 return ret;
144 }
145
146 int
147 crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c,
148 unsigned long long *clen_p,
149 const unsigned char *m,
150 unsigned long long mlen,
151 const unsigned char *ad,
152 unsigned long long adlen,
153 const unsigned char *nsec,
154 const unsigned char *npub,
155 const unsigned char *k)
156 {
157 unsigned long long clen = 0ULL;
158 int ret;
159
160 if (mlen > crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX) {
161 sodium_misuse();
162 }
163 ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached
164 (c, c + mlen, NULL, m, mlen, ad, adlen, nsec, npub, k);
165 if (clen_p != NULL) {
166 if (ret == 0) {
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)167 clen = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES;
168 }
169 *clen_p = clen;
170 }
171 return ret;
172 }
173
174 int
175 crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char *m,
176 unsigned char *nsec,
177 const unsigned char *c,
178 unsigned long long clen,
179 const unsigned char *mac,
180 const unsigned char *ad,
181 unsigned long long adlen,
182 const unsigned char *npub,
183 const unsigned char *k)
184 {
185 unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
186 unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
187 int ret;
188
189 crypto_core_hchacha20(k2, npub, k, NULL);
190 memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
191 crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
192 ret = _decrypt_detached(m, nsec, c, clen, mac, ad, adlen, npub2, k2);
193 sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
194
195 return ret;
196 }
197
198 int
199 crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m,
200 unsigned long long *mlen_p,
201 unsigned char *nsec,
202 const unsigned char *c,
203 unsigned long long clen,
204 const unsigned char *ad,
205 unsigned long long adlen,
206 const unsigned char *npub,
207 const unsigned char *k)
208 {
209 unsigned long long mlen = 0ULL;
210 int ret = -1;
211
212 if (clen >= crypto_aead_xchacha20poly1305_ietf_ABYTES) {
213 ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached
214 (m, nsec,
215 c, clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
216 c + clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
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)217 ad, adlen, npub, k);
218 }
219 if (mlen_p != NULL) {
220 if (ret == 0) {
221 mlen = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES;
222 }
223 *mlen_p = mlen;
224 }
225 return ret;
226 }
227
228 size_t
229 crypto_aead_xchacha20poly1305_ietf_keybytes(void)
230 {
231 return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
232 }
233
234 size_t
235 crypto_aead_xchacha20poly1305_ietf_npubbytes(void)
236 {
237 return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
238 }
239
240 size_t
241 crypto_aead_xchacha20poly1305_ietf_nsecbytes(void)
242 {
243 return crypto_aead_xchacha20poly1305_ietf_NSECBYTES;
244 }
245
246 size_t
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)247 crypto_aead_xchacha20poly1305_ietf_abytes(void)
248 {
249 return crypto_aead_xchacha20poly1305_ietf_ABYTES;
250 }
251
252 size_t
253 crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void)
254 {
255 return crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX;
256 }
257
258 void
259 crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES])
260 {
261 randombytes_buf(k, crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
262 }
263