blob: e632010a0c5c05bf1ca86769915a58c12b2632e1 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/aead.h>
16
17#include <string.h>
18
19#include <openssl/chacha.h>
20#include <openssl/cipher.h>
Robert Sloan4d1ac502017-02-06 08:36:14 -080021#include <openssl/cpu.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080022#include <openssl/err.h>
23#include <openssl/mem.h>
24#include <openssl/poly1305.h>
Robert Sloanfe7cd212017-08-07 09:03:39 -070025#include <openssl/type_check.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080026
Robert Sloan8ff03552017-06-14 12:40:58 -070027#include "../fipsmodule/cipher/internal.h"
David Benjamin4969cc92016-04-22 15:02:23 -040028#include "../internal.h"
Adam Vartanianbfcf3a72018-08-10 14:55:24 +010029#include "../chacha/internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080030
31
32#define POLY1305_TAG_LEN 16
Adam Langleyd9e397b2015-01-22 14:27:53 -080033
34struct aead_chacha20_poly1305_ctx {
Robert Sloanfe7cd212017-08-07 09:03:39 -070035 uint8_t key[32];
36};
37
38// For convenience (the x86_64 calling convention allows only six parameters in
39// registers), the final parameter for the assembly functions is both an input
40// and output parameter.
41union open_data {
42 struct {
43 alignas(16) uint8_t key[32];
44 uint32_t counter;
45 uint8_t nonce[12];
46 } in;
47 struct {
48 uint8_t tag[POLY1305_TAG_LEN];
49 } out;
50};
51
52union seal_data {
53 struct {
54 alignas(16) uint8_t key[32];
55 uint32_t counter;
56 uint8_t nonce[12];
57 const uint8_t *extra_ciphertext;
58 size_t extra_ciphertext_len;
59 } in;
60 struct {
61 uint8_t tag[POLY1305_TAG_LEN];
62 } out;
Adam Langleyd9e397b2015-01-22 14:27:53 -080063};
64
David Benjaminf31229b2017-01-25 14:08:15 -050065#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
66 !defined(OPENSSL_WINDOWS)
Robert Sloan4d1ac502017-02-06 08:36:14 -080067static int asm_capable(void) {
68 const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
69 return sse41_capable;
70}
71
Robert Sloanfe7cd212017-08-07 09:03:39 -070072OPENSSL_COMPILE_ASSERT(sizeof(union open_data) == 48, wrong_open_data_size);
73OPENSSL_COMPILE_ASSERT(sizeof(union seal_data) == 48 + 8 + 8,
74 wrong_seal_data_size);
75
76// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It decrypts
77// |plaintext_len| bytes from |ciphertext| and writes them to |out_plaintext|.
78// Additional input parameters are passed in |aead_data->in|. On exit, it will
79// write calculated tag value to |aead_data->out.tag|, which the caller must
80// check.
Robert Sloan4d1ac502017-02-06 08:36:14 -080081extern void chacha20_poly1305_open(uint8_t *out_plaintext,
82 const uint8_t *ciphertext,
83 size_t plaintext_len, const uint8_t *ad,
Robert Sloanfe7cd212017-08-07 09:03:39 -070084 size_t ad_len, union open_data *aead_data);
David Benjaminf31229b2017-01-25 14:08:15 -050085
Robert Sloanfe7cd212017-08-07 09:03:39 -070086// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It encrypts
87// |plaintext_len| bytes from |plaintext| and writes them to |out_ciphertext|.
88// Additional input parameters are passed in |aead_data->in|. The calculated tag
89// value is over the computed ciphertext concatenated with |extra_ciphertext|
90// and written to |aead_data->out.tag|.
Robert Sloan4d1ac502017-02-06 08:36:14 -080091extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
92 const uint8_t *plaintext,
93 size_t plaintext_len, const uint8_t *ad,
Robert Sloanfe7cd212017-08-07 09:03:39 -070094 size_t ad_len, union seal_data *aead_data);
David Benjaminf31229b2017-01-25 14:08:15 -050095#else
Robert Sloanfe7cd212017-08-07 09:03:39 -070096static int asm_capable(void) { return 0; }
Robert Sloan4d1ac502017-02-06 08:36:14 -080097
David Benjaminf31229b2017-01-25 14:08:15 -050098
99static void chacha20_poly1305_open(uint8_t *out_plaintext,
100 const uint8_t *ciphertext,
101 size_t plaintext_len, const uint8_t *ad,
Robert Sloanfe7cd212017-08-07 09:03:39 -0700102 size_t ad_len, union open_data *aead_data) {}
David Benjaminf31229b2017-01-25 14:08:15 -0500103
104static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
105 const uint8_t *plaintext,
106 size_t plaintext_len, const uint8_t *ad,
Robert Sloanfe7cd212017-08-07 09:03:39 -0700107 size_t ad_len, union seal_data *aead_data) {}
David Benjaminf31229b2017-01-25 14:08:15 -0500108#endif
109
Adam Langleyd9e397b2015-01-22 14:27:53 -0800110static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
111 size_t key_len, size_t tag_len) {
112 struct aead_chacha20_poly1305_ctx *c20_ctx;
113
114 if (tag_len == 0) {
115 tag_len = POLY1305_TAG_LEN;
116 }
117
118 if (tag_len > POLY1305_TAG_LEN) {
Kenny Rootb8494592015-09-25 02:29:14 +0000119 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800120 return 0;
121 }
122
123 if (key_len != sizeof(c20_ctx->key)) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700124 return 0; // internal error - EVP_AEAD_CTX_init should catch this.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800125 }
126
127 c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
128 if (c20_ctx == NULL) {
129 return 0;
130 }
131
Robert Sloan69939df2017-01-09 10:53:07 -0800132 OPENSSL_memcpy(c20_ctx->key, key, key_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800133 ctx->aead_state = c20_ctx;
Robert Sloan8ff03552017-06-14 12:40:58 -0700134 ctx->tag_len = tag_len;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800135
136 return 1;
137}
138
139static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
Robert Sloan2e9e66a2017-09-25 09:08:29 -0700140 OPENSSL_free(ctx->aead_state);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800141}
142
Kenny Roote99801b2015-11-06 15:31:15 -0800143static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800144 uint8_t length_bytes[8];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800145
David Benjaminf31229b2017-01-25 14:08:15 -0500146 for (unsigned i = 0; i < sizeof(length_bytes); i++) {
Kenny Roote99801b2015-11-06 15:31:15 -0800147 length_bytes[i] = data_len;
148 data_len >>= 8;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800149 }
150
Adam Langleyd9e397b2015-01-22 14:27:53 -0800151 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
152}
153
Robert Sloan8f860b12017-08-28 07:37:06 -0700154// calc_tag fills |tag| with the authentication tag for the given inputs.
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100155static void calc_tag(uint8_t tag[POLY1305_TAG_LEN], const uint8_t *key,
David Benjaminf31229b2017-01-25 14:08:15 -0500156 const uint8_t nonce[12], const uint8_t *ad, size_t ad_len,
Robert Sloana12bf462017-07-17 07:08:26 -0700157 const uint8_t *ciphertext, size_t ciphertext_len,
158 const uint8_t *ciphertext_extra,
159 size_t ciphertext_extra_len) {
David Benjamin4969cc92016-04-22 15:02:23 -0400160 alignas(16) uint8_t poly1305_key[32];
Robert Sloan69939df2017-01-09 10:53:07 -0800161 OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key));
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100162 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key, nonce,
163 0);
David Benjaminf31229b2017-01-25 14:08:15 -0500164
Robert Sloan8f860b12017-08-28 07:37:06 -0700165 static const uint8_t padding[16] = { 0 }; // Padding is all zeros.
Kenny Roote99801b2015-11-06 15:31:15 -0800166 poly1305_state ctx;
167 CRYPTO_poly1305_init(&ctx, poly1305_key);
Robert Sloana12bf462017-07-17 07:08:26 -0700168 CRYPTO_poly1305_update(&ctx, ad, ad_len);
169 if (ad_len % 16 != 0) {
170 CRYPTO_poly1305_update(&ctx, padding, sizeof(padding) - (ad_len % 16));
171 }
172 CRYPTO_poly1305_update(&ctx, ciphertext, ciphertext_len);
173 CRYPTO_poly1305_update(&ctx, ciphertext_extra, ciphertext_extra_len);
174 const size_t ciphertext_total = ciphertext_len + ciphertext_extra_len;
175 if (ciphertext_total % 16 != 0) {
176 CRYPTO_poly1305_update(&ctx, padding,
177 sizeof(padding) - (ciphertext_total % 16));
178 }
David Benjaminf31229b2017-01-25 14:08:15 -0500179 poly1305_update_length(&ctx, ad_len);
Robert Sloana12bf462017-07-17 07:08:26 -0700180 poly1305_update_length(&ctx, ciphertext_total);
Kenny Roote99801b2015-11-06 15:31:15 -0800181 CRYPTO_poly1305_finish(&ctx, tag);
182}
183
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100184static int chacha20_poly1305_seal_scatter(
185 const uint8_t *key, uint8_t *out, uint8_t *out_tag,
Robert Sloan8ff03552017-06-14 12:40:58 -0700186 size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
Robert Sloan927a4952017-07-03 11:25:09 -0700187 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100188 size_t extra_in_len, const uint8_t *ad, size_t ad_len, size_t tag_len) {
189 if (extra_in_len + tag_len < tag_len) {
Robert Sloana12bf462017-07-17 07:08:26 -0700190 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
191 return 0;
192 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100193 if (max_out_tag_len < tag_len + extra_in_len) {
Robert Sloana12bf462017-07-17 07:08:26 -0700194 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
195 return 0;
196 }
David Benjaminf31229b2017-01-25 14:08:15 -0500197 if (nonce_len != 12) {
198 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
199 return 0;
200 }
201
Robert Sloan8f860b12017-08-28 07:37:06 -0700202 // |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
203 // individual operations that work on more than 256GB at a time.
204 // |in_len_64| is needed because, on 32-bit platforms, size_t is only
205 // 32-bits and this produces a warning because it's always false.
206 // Casting to uint64_t inside the conditional is not sufficient to stop
207 // the warning.
Robert Sloan8ff03552017-06-14 12:40:58 -0700208 const uint64_t in_len_64 = in_len;
David Benjamin4969cc92016-04-22 15:02:23 -0400209 if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
Kenny Rootb8494592015-09-25 02:29:14 +0000210 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800211 return 0;
212 }
213
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100214 if (max_out_tag_len < tag_len) {
Kenny Rootb8494592015-09-25 02:29:14 +0000215 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800216 return 0;
217 }
218
Robert Sloan8f860b12017-08-28 07:37:06 -0700219 // The the extra input is given, it is expected to be very short and so is
220 // encrypted byte-by-byte first.
Robert Sloana12bf462017-07-17 07:08:26 -0700221 if (extra_in_len) {
222 static const size_t kChaChaBlockSize = 64;
223 uint32_t block_counter = 1 + (in_len / kChaChaBlockSize);
224 size_t offset = in_len % kChaChaBlockSize;
225 uint8_t block[64 /* kChaChaBlockSize */];
226
227 for (size_t done = 0; done < extra_in_len; block_counter++) {
228 memset(block, 0, sizeof(block));
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100229 CRYPTO_chacha_20(block, block, sizeof(block), key, nonce,
Robert Sloana12bf462017-07-17 07:08:26 -0700230 block_counter);
231 for (size_t i = offset; i < sizeof(block) && done < extra_in_len;
232 i++, done++) {
233 out_tag[done] = extra_in[done] ^ block[i];
234 }
235 offset = 0;
236 }
237 }
238
Robert Sloanfe7cd212017-08-07 09:03:39 -0700239 union seal_data data;
Robert Sloan4d1ac502017-02-06 08:36:14 -0800240 if (asm_capable()) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100241 OPENSSL_memcpy(data.in.key, key, 32);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700242 data.in.counter = 0;
243 OPENSSL_memcpy(data.in.nonce, nonce, 12);
244 data.in.extra_ciphertext = out_tag;
245 data.in.extra_ciphertext_len = extra_in_len;
246 chacha20_poly1305_seal(out, in, in_len, ad, ad_len, &data);
David Benjaminf31229b2017-01-25 14:08:15 -0500247 } else {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100248 CRYPTO_chacha_20(out, in, in_len, key, nonce, 1);
249 calc_tag(data.out.tag, key, nonce, ad, ad_len, out, in_len, out_tag,
Robert Sloanfe7cd212017-08-07 09:03:39 -0700250 extra_in_len);
David Benjaminf31229b2017-01-25 14:08:15 -0500251 }
Kenny Roote99801b2015-11-06 15:31:15 -0800252
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100253 OPENSSL_memcpy(out_tag + extra_in_len, data.out.tag, tag_len);
254 *out_tag_len = extra_in_len + tag_len;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800255 return 1;
256}
257
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100258static int aead_chacha20_poly1305_seal_scatter(
259 const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
260 size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
261 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
262 size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800263 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800264
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100265 return chacha20_poly1305_seal_scatter(
266 c20_ctx->key, out, out_tag, out_tag_len, max_out_tag_len, nonce,
267 nonce_len, in, in_len, extra_in, extra_in_len, ad, ad_len, ctx->tag_len);
268}
269
270static int aead_xchacha20_poly1305_seal_scatter(
271 const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
272 size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
273 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
274 size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
275 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
276
277 if (nonce_len != 24) {
278 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
279 return 0;
280 }
281
282 alignas(4) uint8_t derived_key[32];
283 alignas(4) uint8_t derived_nonce[12];
284 CRYPTO_hchacha20(derived_key, c20_ctx->key, nonce);
285 OPENSSL_memset(derived_nonce, 0, 4);
286 OPENSSL_memcpy(&derived_nonce[4], &nonce[16], 8);
287
288 return chacha20_poly1305_seal_scatter(
289 derived_key, out, out_tag, out_tag_len, max_out_tag_len,
290 derived_nonce, sizeof(derived_nonce), in, in_len, extra_in, extra_in_len,
291 ad, ad_len, ctx->tag_len);
292}
293
294static int chacha20_poly1305_open_gather(
295 const uint8_t *key, uint8_t *out, const uint8_t *nonce,
296 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
297 size_t in_tag_len, const uint8_t *ad, size_t ad_len, size_t tag_len) {
David Benjaminf31229b2017-01-25 14:08:15 -0500298 if (nonce_len != 12) {
299 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
300 return 0;
301 }
302
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100303 if (in_tag_len != tag_len) {
Kenny Rootb8494592015-09-25 02:29:14 +0000304 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800305 return 0;
306 }
307
Robert Sloan8f860b12017-08-28 07:37:06 -0700308 // |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
309 // individual operations that work on more than 256GB at a time.
310 // |in_len_64| is needed because, on 32-bit platforms, size_t is only
311 // 32-bits and this produces a warning because it's always false.
312 // Casting to uint64_t inside the conditional is not sufficient to stop
313 // the warning.
Robert Sloan8ff03552017-06-14 12:40:58 -0700314 const uint64_t in_len_64 = in_len;
David Benjamin4969cc92016-04-22 15:02:23 -0400315 if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
Kenny Rootb8494592015-09-25 02:29:14 +0000316 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800317 return 0;
318 }
319
Robert Sloanfe7cd212017-08-07 09:03:39 -0700320 union open_data data;
Robert Sloan4d1ac502017-02-06 08:36:14 -0800321 if (asm_capable()) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100322 OPENSSL_memcpy(data.in.key, key, 32);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700323 data.in.counter = 0;
324 OPENSSL_memcpy(data.in.nonce, nonce, 12);
325 chacha20_poly1305_open(out, in, in_len, ad, ad_len, &data);
David Benjaminf31229b2017-01-25 14:08:15 -0500326 } else {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100327 calc_tag(data.out.tag, key, nonce, ad, ad_len, in, in_len, NULL, 0);
328 CRYPTO_chacha_20(out, in, in_len, key, nonce, 1);
David Benjaminf31229b2017-01-25 14:08:15 -0500329 }
330
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100331 if (CRYPTO_memcmp(data.out.tag, in_tag, tag_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000332 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800333 return 0;
334 }
335
Adam Langleyd9e397b2015-01-22 14:27:53 -0800336 return 1;
337}
338
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100339static int aead_chacha20_poly1305_open_gather(
340 const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
341 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
342 size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
343 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
344
345 return chacha20_poly1305_open_gather(c20_ctx->key, out, nonce, nonce_len, in,
346 in_len, in_tag, in_tag_len, ad, ad_len,
347 ctx->tag_len);
348}
349
350static int aead_xchacha20_poly1305_open_gather(
351 const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
352 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
353 size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
354 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
355
356 if (nonce_len != 24) {
357 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
358 return 0;
359 }
360
361 alignas(4) uint8_t derived_key[32];
362 alignas(4) uint8_t derived_nonce[12];
363 CRYPTO_hchacha20(derived_key, c20_ctx->key, nonce);
364 OPENSSL_memset(derived_nonce, 0, 4);
365 OPENSSL_memcpy(&derived_nonce[4], &nonce[16], 8);
366
367 return chacha20_poly1305_open_gather(
368 derived_key, out, derived_nonce, sizeof(derived_nonce), in, in_len,
369 in_tag, in_tag_len, ad, ad_len, ctx->tag_len);
370}
371
Adam Langleyd9e397b2015-01-22 14:27:53 -0800372static const EVP_AEAD aead_chacha20_poly1305 = {
Robert Sloan8f860b12017-08-28 07:37:06 -0700373 32, // key len
374 12, // nonce len
375 POLY1305_TAG_LEN, // overhead
376 POLY1305_TAG_LEN, // max tag length
377 1, // seal_scatter_supports_extra_in
Robert Sloan927a4952017-07-03 11:25:09 -0700378
Adam Langleye9ada862015-05-11 17:20:37 -0700379 aead_chacha20_poly1305_init,
Robert Sloan8f860b12017-08-28 07:37:06 -0700380 NULL, // init_with_direction
Adam Langleye9ada862015-05-11 17:20:37 -0700381 aead_chacha20_poly1305_cleanup,
Robert Sloan8ff03552017-06-14 12:40:58 -0700382 NULL /* open */,
383 aead_chacha20_poly1305_seal_scatter,
384 aead_chacha20_poly1305_open_gather,
Robert Sloan8f860b12017-08-28 07:37:06 -0700385 NULL, // get_iv
386 NULL, // tag_len
Adam Langleyd9e397b2015-01-22 14:27:53 -0800387};
388
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100389static const EVP_AEAD aead_xchacha20_poly1305 = {
390 32, // key len
391 24, // nonce len
392 POLY1305_TAG_LEN, // overhead
393 POLY1305_TAG_LEN, // max tag length
394 1, // seal_scatter_supports_extra_in
395
396 aead_chacha20_poly1305_init,
397 NULL, // init_with_direction
398 aead_chacha20_poly1305_cleanup,
399 NULL /* open */,
400 aead_xchacha20_poly1305_seal_scatter,
401 aead_xchacha20_poly1305_open_gather,
402 NULL, // get_iv
403 NULL, // tag_len
404};
405
Adam Langley4139edb2016-01-13 15:00:54 -0800406const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
Kenny Root03bcf612015-11-05 20:20:27 +0000407 return &aead_chacha20_poly1305;
Adam Langleyfdeb4882015-10-30 13:15:30 -0700408}
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100409
410const EVP_AEAD *EVP_aead_xchacha20_poly1305(void) {
411 return &aead_xchacha20_poly1305;
412}