2 * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include "internal/cryptlib.h"
12 #include "internal/endian.h"
14 #ifndef OPENSSL_NO_CHACHA
16 # include <openssl/evp.h>
17 # include <openssl/objects.h>
18 # include "crypto/evp.h"
19 # include "evp_local.h"
20 # include "crypto/chacha.h"
24 OSSL_UNION_ALIGN
; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
25 unsigned int d
[CHACHA_KEY_SIZE
/ 4];
27 unsigned int counter
[CHACHA_CTR_SIZE
/ 4];
28 unsigned char buf
[CHACHA_BLK_SIZE
];
29 unsigned int partial_len
;
32 #define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
34 #define CHACHA20_POLY1305_MAX_IVLEN 12
36 static int chacha_init_key(EVP_CIPHER_CTX
*ctx
,
37 const unsigned char user_key
[CHACHA_KEY_SIZE
],
38 const unsigned char iv
[CHACHA_CTR_SIZE
], int enc
)
40 EVP_CHACHA_KEY
*key
= data(ctx
);
44 for (i
= 0; i
< CHACHA_KEY_SIZE
; i
+=4) {
45 key
->key
.d
[i
/4] = CHACHA_U8TOU32(user_key
+i
);
49 for (i
= 0; i
< CHACHA_CTR_SIZE
; i
+=4) {
50 key
->counter
[i
/4] = CHACHA_U8TOU32(iv
+i
);
58 static int chacha_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
59 const unsigned char *inp
, size_t len
)
61 EVP_CHACHA_KEY
*key
= data(ctx
);
62 unsigned int n
, rem
, ctr32
;
64 if ((n
= key
->partial_len
)) {
65 while (len
&& n
< CHACHA_BLK_SIZE
) {
66 *out
++ = *inp
++ ^ key
->buf
[n
++];
74 if (n
== CHACHA_BLK_SIZE
) {
77 if (key
->counter
[0] == 0)
82 rem
= (unsigned int)(len
% CHACHA_BLK_SIZE
);
84 ctr32
= key
->counter
[0];
85 while (len
>= CHACHA_BLK_SIZE
) {
86 size_t blocks
= len
/ CHACHA_BLK_SIZE
;
88 * 1<<28 is just a not-so-small yet not-so-large number...
89 * Below condition is practically never met, but it has to
90 * be checked for code correctness.
92 if (sizeof(size_t)>sizeof(unsigned int) && blocks
>(1U<<28))
96 * As ChaCha20_ctr32 operates on 32-bit counter, caller
97 * has to handle overflow. 'if' below detects the
98 * overflow, which is then handled by limiting the
99 * amount of blocks to the exact overflow point...
101 ctr32
+= (unsigned int)blocks
;
102 if (ctr32
< blocks
) {
106 blocks
*= CHACHA_BLK_SIZE
;
107 ChaCha20_ctr32(out
, inp
, blocks
, key
->key
.d
, key
->counter
);
112 key
->counter
[0] = ctr32
;
113 if (ctr32
== 0) key
->counter
[1]++;
117 memset(key
->buf
, 0, sizeof(key
->buf
));
118 ChaCha20_ctr32(key
->buf
, key
->buf
, CHACHA_BLK_SIZE
,
119 key
->key
.d
, key
->counter
);
120 for (n
= 0; n
< rem
; n
++)
121 out
[n
] = inp
[n
] ^ key
->buf
[n
];
122 key
->partial_len
= rem
;
128 static const EVP_CIPHER chacha20
= {
131 CHACHA_KEY_SIZE
, /* key_len */
132 CHACHA_CTR_SIZE
, /* iv_len, 128-bit counter in the context */
133 EVP_CIPH_CUSTOM_IV
| EVP_CIPH_ALWAYS_CALL_INIT
,
138 sizeof(EVP_CHACHA_KEY
),
145 const EVP_CIPHER
*EVP_chacha20(void)
150 # ifndef OPENSSL_NO_POLY1305
151 # include "crypto/poly1305.h"
155 unsigned int nonce
[12/4];
156 unsigned char tag
[POLY1305_BLOCK_SIZE
];
157 unsigned char tls_aad
[POLY1305_BLOCK_SIZE
];
158 struct { uint64_t aad
, text
; } len
;
159 int aad
, mac_inited
, tag_len
, nonce_len
;
160 size_t tls_payload_length
;
161 } EVP_CHACHA_AEAD_CTX
;
163 # define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
164 # define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
165 # define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
167 static int chacha20_poly1305_init_key(EVP_CIPHER_CTX
*ctx
,
168 const unsigned char *inkey
,
169 const unsigned char *iv
, int enc
)
171 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
179 actx
->mac_inited
= 0;
180 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
183 unsigned char temp
[CHACHA_CTR_SIZE
] = { 0 };
185 /* pad on the left */
186 if (actx
->nonce_len
<= CHACHA_CTR_SIZE
)
187 memcpy(temp
+ CHACHA_CTR_SIZE
- actx
->nonce_len
, iv
,
190 chacha_init_key(ctx
, inkey
, temp
, enc
);
192 actx
->nonce
[0] = actx
->key
.counter
[1];
193 actx
->nonce
[1] = actx
->key
.counter
[2];
194 actx
->nonce
[2] = actx
->key
.counter
[3];
196 chacha_init_key(ctx
, inkey
, NULL
, enc
);
202 # if !defined(OPENSSL_SMALL_FOOTPRINT)
204 # if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
205 defined(_M_AMD64) || defined(_M_X64))
206 # define XOR128_HELPERS
207 void *xor128_encrypt_n_pad(void *out
, const void *inp
, void *otp
, size_t len
);
208 void *xor128_decrypt_n_pad(void *out
, const void *inp
, void *otp
, size_t len
);
209 static const unsigned char zero
[4 * CHACHA_BLK_SIZE
] = { 0 };
211 static const unsigned char zero
[2 * CHACHA_BLK_SIZE
] = { 0 };
214 static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
215 const unsigned char *in
, size_t len
)
217 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
218 size_t tail
, tohash_len
, buf_len
, plen
= actx
->tls_payload_length
;
219 unsigned char *buf
, *tohash
, *ctr
, storage
[sizeof(zero
) + 32];
221 if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
224 buf
= storage
+ ((0 - (size_t)storage
) & 15); /* align */
225 ctr
= buf
+ CHACHA_BLK_SIZE
;
226 tohash
= buf
+ CHACHA_BLK_SIZE
- POLY1305_BLOCK_SIZE
;
228 # ifdef XOR128_HELPERS
229 if (plen
<= 3 * CHACHA_BLK_SIZE
) {
230 actx
->key
.counter
[0] = 0;
231 buf_len
= (plen
+ 2 * CHACHA_BLK_SIZE
- 1) & (0 - CHACHA_BLK_SIZE
);
232 ChaCha20_ctr32(buf
, zero
, buf_len
, actx
->key
.key
.d
,
234 Poly1305_Init(POLY1305_ctx(actx
), buf
);
235 actx
->key
.partial_len
= 0;
236 memcpy(tohash
, actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
237 tohash_len
= POLY1305_BLOCK_SIZE
;
238 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
239 actx
->len
.text
= plen
;
242 if (EVP_CIPHER_CTX_is_encrypting(ctx
))
243 ctr
= xor128_encrypt_n_pad(out
, in
, ctr
, plen
);
245 ctr
= xor128_decrypt_n_pad(out
, in
, ctr
, plen
);
249 tohash_len
= (size_t)(ctr
- tohash
);
253 if (plen
<= CHACHA_BLK_SIZE
) {
256 actx
->key
.counter
[0] = 0;
257 ChaCha20_ctr32(buf
, zero
, (buf_len
= 2 * CHACHA_BLK_SIZE
),
258 actx
->key
.key
.d
, actx
->key
.counter
);
259 Poly1305_Init(POLY1305_ctx(actx
), buf
);
260 actx
->key
.partial_len
= 0;
261 memcpy(tohash
, actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
262 tohash_len
= POLY1305_BLOCK_SIZE
;
263 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
264 actx
->len
.text
= plen
;
266 if (EVP_CIPHER_CTX_is_encrypting(ctx
)) {
267 for (i
= 0; i
< plen
; i
++) {
268 out
[i
] = ctr
[i
] ^= in
[i
];
271 for (i
= 0; i
< plen
; i
++) {
272 unsigned char c
= in
[i
];
281 tail
= (0 - i
) & (POLY1305_BLOCK_SIZE
- 1);
282 memset(ctr
+ i
, 0, tail
);
284 tohash_len
+= i
+ tail
;
288 actx
->key
.counter
[0] = 0;
289 ChaCha20_ctr32(buf
, zero
, (buf_len
= CHACHA_BLK_SIZE
),
290 actx
->key
.key
.d
, actx
->key
.counter
);
291 Poly1305_Init(POLY1305_ctx(actx
), buf
);
292 actx
->key
.counter
[0] = 1;
293 actx
->key
.partial_len
= 0;
294 Poly1305_Update(POLY1305_ctx(actx
), actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
297 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
298 actx
->len
.text
= plen
;
300 if (EVP_CIPHER_CTX_is_encrypting(ctx
)) {
301 ChaCha20_ctr32(out
, in
, plen
, actx
->key
.key
.d
, actx
->key
.counter
);
302 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
304 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
305 ChaCha20_ctr32(out
, in
, plen
, actx
->key
.key
.d
, actx
->key
.counter
);
310 tail
= (0 - plen
) & (POLY1305_BLOCK_SIZE
- 1);
311 Poly1305_Update(POLY1305_ctx(actx
), zero
, tail
);
317 if (IS_LITTLE_ENDIAN
) {
318 memcpy(ctr
, (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
320 ctr
[0] = (unsigned char)(actx
->len
.aad
);
321 ctr
[1] = (unsigned char)(actx
->len
.aad
>>8);
322 ctr
[2] = (unsigned char)(actx
->len
.aad
>>16);
323 ctr
[3] = (unsigned char)(actx
->len
.aad
>>24);
324 ctr
[4] = (unsigned char)(actx
->len
.aad
>>32);
325 ctr
[5] = (unsigned char)(actx
->len
.aad
>>40);
326 ctr
[6] = (unsigned char)(actx
->len
.aad
>>48);
327 ctr
[7] = (unsigned char)(actx
->len
.aad
>>56);
329 ctr
[8] = (unsigned char)(actx
->len
.text
);
330 ctr
[9] = (unsigned char)(actx
->len
.text
>>8);
331 ctr
[10] = (unsigned char)(actx
->len
.text
>>16);
332 ctr
[11] = (unsigned char)(actx
->len
.text
>>24);
333 ctr
[12] = (unsigned char)(actx
->len
.text
>>32);
334 ctr
[13] = (unsigned char)(actx
->len
.text
>>40);
335 ctr
[14] = (unsigned char)(actx
->len
.text
>>48);
336 ctr
[15] = (unsigned char)(actx
->len
.text
>>56);
338 tohash_len
+= POLY1305_BLOCK_SIZE
;
341 Poly1305_Update(POLY1305_ctx(actx
), tohash
, tohash_len
);
342 OPENSSL_cleanse(buf
, buf_len
);
343 Poly1305_Final(POLY1305_ctx(actx
),
344 EVP_CIPHER_CTX_is_encrypting(ctx
) ? actx
->tag
: tohash
);
346 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
348 if (EVP_CIPHER_CTX_is_encrypting(ctx
)) {
349 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
351 if (CRYPTO_memcmp(tohash
, in
, POLY1305_BLOCK_SIZE
)) {
352 memset(out
- (len
- POLY1305_BLOCK_SIZE
), 0,
353 len
- POLY1305_BLOCK_SIZE
);
361 static const unsigned char zero
[CHACHA_BLK_SIZE
] = { 0 };
364 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
365 const unsigned char *in
, size_t len
)
367 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
368 size_t rem
, plen
= actx
->tls_payload_length
;
370 if (!actx
->mac_inited
) {
371 # if !defined(OPENSSL_SMALL_FOOTPRINT)
372 if (plen
!= NO_TLS_PAYLOAD_LENGTH
&& out
!= NULL
)
373 return chacha20_poly1305_tls_cipher(ctx
, out
, in
, len
);
375 actx
->key
.counter
[0] = 0;
376 ChaCha20_ctr32(actx
->key
.buf
, zero
, CHACHA_BLK_SIZE
,
377 actx
->key
.key
.d
, actx
->key
.counter
);
378 Poly1305_Init(POLY1305_ctx(actx
), actx
->key
.buf
);
379 actx
->key
.counter
[0] = 1;
380 actx
->key
.partial_len
= 0;
381 actx
->len
.aad
= actx
->len
.text
= 0;
382 actx
->mac_inited
= 1;
383 if (plen
!= NO_TLS_PAYLOAD_LENGTH
) {
384 Poly1305_Update(POLY1305_ctx(actx
), actx
->tls_aad
,
385 EVP_AEAD_TLS1_AAD_LEN
);
386 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
391 if (in
) { /* aad or text */
392 if (out
== NULL
) { /* aad */
393 Poly1305_Update(POLY1305_ctx(actx
), in
, len
);
394 actx
->len
.aad
+= len
;
397 } else { /* plain- or ciphertext */
398 if (actx
->aad
) { /* wrap up aad */
399 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
400 Poly1305_Update(POLY1305_ctx(actx
), zero
,
401 POLY1305_BLOCK_SIZE
- rem
);
405 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
406 if (plen
== NO_TLS_PAYLOAD_LENGTH
)
408 else if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
411 if (EVP_CIPHER_CTX_is_encrypting(ctx
)) { /* plaintext */
412 chacha_cipher(ctx
, out
, in
, plen
);
413 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
416 actx
->len
.text
+= plen
;
417 } else { /* ciphertext */
418 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
419 chacha_cipher(ctx
, out
, in
, plen
);
422 actx
->len
.text
+= plen
;
426 if (in
== NULL
/* explicit final */
427 || plen
!= len
) { /* or tls mode */
429 unsigned char temp
[POLY1305_BLOCK_SIZE
];
431 if (actx
->aad
) { /* wrap up aad */
432 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
433 Poly1305_Update(POLY1305_ctx(actx
), zero
,
434 POLY1305_BLOCK_SIZE
- rem
);
438 if ((rem
= (size_t)actx
->len
.text
% POLY1305_BLOCK_SIZE
))
439 Poly1305_Update(POLY1305_ctx(actx
), zero
,
440 POLY1305_BLOCK_SIZE
- rem
);
442 if (IS_LITTLE_ENDIAN
) {
443 Poly1305_Update(POLY1305_ctx(actx
),
444 (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
446 temp
[0] = (unsigned char)(actx
->len
.aad
);
447 temp
[1] = (unsigned char)(actx
->len
.aad
>>8);
448 temp
[2] = (unsigned char)(actx
->len
.aad
>>16);
449 temp
[3] = (unsigned char)(actx
->len
.aad
>>24);
450 temp
[4] = (unsigned char)(actx
->len
.aad
>>32);
451 temp
[5] = (unsigned char)(actx
->len
.aad
>>40);
452 temp
[6] = (unsigned char)(actx
->len
.aad
>>48);
453 temp
[7] = (unsigned char)(actx
->len
.aad
>>56);
455 temp
[8] = (unsigned char)(actx
->len
.text
);
456 temp
[9] = (unsigned char)(actx
->len
.text
>>8);
457 temp
[10] = (unsigned char)(actx
->len
.text
>>16);
458 temp
[11] = (unsigned char)(actx
->len
.text
>>24);
459 temp
[12] = (unsigned char)(actx
->len
.text
>>32);
460 temp
[13] = (unsigned char)(actx
->len
.text
>>40);
461 temp
[14] = (unsigned char)(actx
->len
.text
>>48);
462 temp
[15] = (unsigned char)(actx
->len
.text
>>56);
464 Poly1305_Update(POLY1305_ctx(actx
), temp
, POLY1305_BLOCK_SIZE
);
466 Poly1305_Final(POLY1305_ctx(actx
),
467 EVP_CIPHER_CTX_is_encrypting(ctx
) ? actx
->tag
: temp
);
468 actx
->mac_inited
= 0;
470 if (in
!= NULL
&& len
!= plen
) { /* tls mode */
471 if (EVP_CIPHER_CTX_is_encrypting(ctx
)) {
472 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
474 if (CRYPTO_memcmp(temp
, in
, POLY1305_BLOCK_SIZE
)) {
475 memset(out
- plen
, 0, plen
);
480 else if (!EVP_CIPHER_CTX_is_encrypting(ctx
)) {
481 if (CRYPTO_memcmp(temp
, actx
->tag
, actx
->tag_len
))
488 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX
*ctx
)
490 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
492 OPENSSL_cleanse(ctx
->cipher_data
, sizeof(*actx
) + Poly1305_ctx_size());
496 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
499 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
504 actx
= ctx
->cipher_data
505 = OPENSSL_zalloc(sizeof(*actx
) + Poly1305_ctx_size());
507 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
513 actx
->mac_inited
= 0;
515 actx
->nonce_len
= 12;
516 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
517 memset(actx
->tls_aad
, 0, POLY1305_BLOCK_SIZE
);
522 EVP_CIPHER_CTX
*dst
= (EVP_CIPHER_CTX
*)ptr
;
525 OPENSSL_memdup(actx
, sizeof(*actx
) + Poly1305_ctx_size());
526 if (dst
->cipher_data
== NULL
) {
527 ERR_raise(ERR_LIB_EVP
, EVP_R_COPY_ERROR
);
533 case EVP_CTRL_GET_IVLEN
:
534 *(int *)ptr
= actx
->nonce_len
;
537 case EVP_CTRL_AEAD_SET_IVLEN
:
538 if (arg
<= 0 || arg
> CHACHA20_POLY1305_MAX_IVLEN
)
540 actx
->nonce_len
= arg
;
543 case EVP_CTRL_AEAD_SET_IV_FIXED
:
546 actx
->nonce
[0] = actx
->key
.counter
[1]
547 = CHACHA_U8TOU32((unsigned char *)ptr
);
548 actx
->nonce
[1] = actx
->key
.counter
[2]
549 = CHACHA_U8TOU32((unsigned char *)ptr
+4);
550 actx
->nonce
[2] = actx
->key
.counter
[3]
551 = CHACHA_U8TOU32((unsigned char *)ptr
+8);
554 case EVP_CTRL_AEAD_SET_TAG
:
555 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
)
558 memcpy(actx
->tag
, ptr
, arg
);
563 case EVP_CTRL_AEAD_GET_TAG
:
564 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
||
565 !EVP_CIPHER_CTX_is_encrypting(ctx
))
567 memcpy(ptr
, actx
->tag
, arg
);
570 case EVP_CTRL_AEAD_TLS1_AAD
:
571 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
575 unsigned char *aad
= ptr
;
577 memcpy(actx
->tls_aad
, ptr
, EVP_AEAD_TLS1_AAD_LEN
);
578 len
= aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] << 8 |
579 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1];
581 if (!EVP_CIPHER_CTX_is_encrypting(ctx
)) {
582 if (len
< POLY1305_BLOCK_SIZE
)
584 len
-= POLY1305_BLOCK_SIZE
; /* discount attached tag */
585 aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] = (unsigned char)(len
>> 8);
586 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1] = (unsigned char)len
;
588 actx
->tls_payload_length
= len
;
591 * merge record sequence number as per RFC7905
593 actx
->key
.counter
[1] = actx
->nonce
[0];
594 actx
->key
.counter
[2] = actx
->nonce
[1] ^ CHACHA_U8TOU32(aad
);
595 actx
->key
.counter
[3] = actx
->nonce
[2] ^ CHACHA_U8TOU32(aad
+4);
596 actx
->mac_inited
= 0;
598 return POLY1305_BLOCK_SIZE
; /* tag length */
601 case EVP_CTRL_AEAD_SET_MAC_KEY
:
610 static EVP_CIPHER chacha20_poly1305
= {
611 NID_chacha20_poly1305
,
613 CHACHA_KEY_SIZE
, /* key_len */
614 12, /* iv_len, 96-bit nonce in the context */
615 EVP_CIPH_FLAG_AEAD_CIPHER
| EVP_CIPH_CUSTOM_IV
|
616 EVP_CIPH_ALWAYS_CALL_INIT
| EVP_CIPH_CTRL_INIT
|
617 EVP_CIPH_CUSTOM_COPY
| EVP_CIPH_FLAG_CUSTOM_CIPHER
|
618 EVP_CIPH_CUSTOM_IV_LENGTH
,
620 chacha20_poly1305_init_key
,
621 chacha20_poly1305_cipher
,
622 chacha20_poly1305_cleanup
,
623 0, /* 0 moves context-specific structure allocation to ctrl */
624 NULL
, /* set_asn1_parameters */
625 NULL
, /* get_asn1_parameters */
626 chacha20_poly1305_ctrl
,
630 const EVP_CIPHER
*EVP_chacha20_poly1305(void)
632 return(&chacha20_poly1305
);