2 * Copyright 2015-2019 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"
13 #ifndef OPENSSL_NO_CHACHA
15 # include <openssl/evp.h>
16 # include <openssl/objects.h>
17 # include "internal/evp_int.h"
18 # include "evp_locl.h"
19 # include "internal/chacha.h"
23 OSSL_UNION_ALIGN
; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
24 unsigned int d
[CHACHA_KEY_SIZE
/ 4];
26 unsigned int counter
[CHACHA_CTR_SIZE
/ 4];
27 unsigned char buf
[CHACHA_BLK_SIZE
];
28 unsigned int partial_len
;
31 #define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
33 #define CHACHA20_POLY1305_MAX_IVLEN 12
35 static int chacha_init_key(EVP_CIPHER_CTX
*ctx
,
36 const unsigned char user_key
[CHACHA_KEY_SIZE
],
37 const unsigned char iv
[CHACHA_CTR_SIZE
], int enc
)
39 EVP_CHACHA_KEY
*key
= data(ctx
);
43 for (i
= 0; i
< CHACHA_KEY_SIZE
; i
+=4) {
44 key
->key
.d
[i
/4] = CHACHA_U8TOU32(user_key
+i
);
48 for (i
= 0; i
< CHACHA_CTR_SIZE
; i
+=4) {
49 key
->counter
[i
/4] = CHACHA_U8TOU32(iv
+i
);
57 static int chacha_cipher(EVP_CIPHER_CTX
* ctx
, unsigned char *out
,
58 const unsigned char *inp
, size_t len
)
60 EVP_CHACHA_KEY
*key
= data(ctx
);
61 unsigned int n
, rem
, ctr32
;
63 if ((n
= key
->partial_len
)) {
64 while (len
&& n
< CHACHA_BLK_SIZE
) {
65 *out
++ = *inp
++ ^ key
->buf
[n
++];
73 if (n
== CHACHA_BLK_SIZE
) {
76 if (key
->counter
[0] == 0)
81 rem
= (unsigned int)(len
% CHACHA_BLK_SIZE
);
83 ctr32
= key
->counter
[0];
84 while (len
>= CHACHA_BLK_SIZE
) {
85 size_t blocks
= len
/ CHACHA_BLK_SIZE
;
87 * 1<<28 is just a not-so-small yet not-so-large number...
88 * Below condition is practically never met, but it has to
89 * be checked for code correctness.
91 if (sizeof(size_t)>sizeof(unsigned int) && blocks
>(1U<<28))
95 * As ChaCha20_ctr32 operates on 32-bit counter, caller
96 * has to handle overflow. 'if' below detects the
97 * overflow, which is then handled by limiting the
98 * amount of blocks to the exact overflow point...
100 ctr32
+= (unsigned int)blocks
;
101 if (ctr32
< blocks
) {
105 blocks
*= CHACHA_BLK_SIZE
;
106 ChaCha20_ctr32(out
, inp
, blocks
, key
->key
.d
, key
->counter
);
111 key
->counter
[0] = ctr32
;
112 if (ctr32
== 0) key
->counter
[1]++;
116 memset(key
->buf
, 0, sizeof(key
->buf
));
117 ChaCha20_ctr32(key
->buf
, key
->buf
, CHACHA_BLK_SIZE
,
118 key
->key
.d
, key
->counter
);
119 for (n
= 0; n
< rem
; n
++)
120 out
[n
] = inp
[n
] ^ key
->buf
[n
];
121 key
->partial_len
= rem
;
127 static const EVP_CIPHER chacha20
= {
130 CHACHA_KEY_SIZE
, /* key_len */
131 CHACHA_CTR_SIZE
, /* iv_len, 128-bit counter in the context */
132 EVP_CIPH_CUSTOM_IV
| EVP_CIPH_ALWAYS_CALL_INIT
,
136 sizeof(EVP_CHACHA_KEY
),
143 const EVP_CIPHER
*EVP_chacha20(void)
148 # ifndef OPENSSL_NO_POLY1305
149 # include "internal/poly1305.h"
153 unsigned int nonce
[12/4];
154 unsigned char tag
[POLY1305_BLOCK_SIZE
];
155 unsigned char tls_aad
[POLY1305_BLOCK_SIZE
];
156 struct { uint64_t aad
, text
; } len
;
157 int aad
, mac_inited
, tag_len
, nonce_len
;
158 size_t tls_payload_length
;
159 } EVP_CHACHA_AEAD_CTX
;
161 # define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
162 # define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
163 # define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
165 static int chacha20_poly1305_init_key(EVP_CIPHER_CTX
*ctx
,
166 const unsigned char *inkey
,
167 const unsigned char *iv
, int enc
)
169 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
177 actx
->mac_inited
= 0;
178 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
181 unsigned char temp
[CHACHA_CTR_SIZE
] = { 0 };
183 /* pad on the left */
184 if (actx
->nonce_len
<= CHACHA_CTR_SIZE
)
185 memcpy(temp
+ CHACHA_CTR_SIZE
- actx
->nonce_len
, iv
,
188 chacha_init_key(ctx
, inkey
, temp
, enc
);
190 actx
->nonce
[0] = actx
->key
.counter
[1];
191 actx
->nonce
[1] = actx
->key
.counter
[2];
192 actx
->nonce
[2] = actx
->key
.counter
[3];
194 chacha_init_key(ctx
, inkey
, NULL
, enc
);
200 # if !defined(OPENSSL_SMALL_FOOTPRINT)
202 # if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
203 defined(_M_AMD64) || defined(_M_X64))
204 # define XOR128_HELPERS
205 void *xor128_encrypt_n_pad(void *out
, const void *inp
, void *otp
, size_t len
);
206 void *xor128_decrypt_n_pad(void *out
, const void *inp
, void *otp
, size_t len
);
207 static const unsigned char zero
[4 * CHACHA_BLK_SIZE
] = { 0 };
209 static const unsigned char zero
[2 * CHACHA_BLK_SIZE
] = { 0 };
212 static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
213 const unsigned char *in
, size_t len
)
215 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
216 size_t tail
, tohash_len
, buf_len
, plen
= actx
->tls_payload_length
;
217 unsigned char *buf
, *tohash
, *ctr
, storage
[sizeof(zero
) + 32];
219 if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
222 buf
= storage
+ ((0 - (size_t)storage
) & 15); /* align */
223 ctr
= buf
+ CHACHA_BLK_SIZE
;
224 tohash
= buf
+ CHACHA_BLK_SIZE
- POLY1305_BLOCK_SIZE
;
226 # ifdef XOR128_HELPERS
227 if (plen
<= 3 * CHACHA_BLK_SIZE
) {
228 actx
->key
.counter
[0] = 0;
229 buf_len
= (plen
+ 2 * CHACHA_BLK_SIZE
- 1) & (0 - CHACHA_BLK_SIZE
);
230 ChaCha20_ctr32(buf
, zero
, buf_len
, actx
->key
.key
.d
,
232 Poly1305_Init(POLY1305_ctx(actx
), buf
);
233 actx
->key
.partial_len
= 0;
234 memcpy(tohash
, actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
235 tohash_len
= POLY1305_BLOCK_SIZE
;
236 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
237 actx
->len
.text
= plen
;
241 ctr
= xor128_encrypt_n_pad(out
, in
, ctr
, plen
);
243 ctr
= xor128_decrypt_n_pad(out
, in
, ctr
, plen
);
247 tohash_len
= (size_t)(ctr
- tohash
);
251 if (plen
<= CHACHA_BLK_SIZE
) {
254 actx
->key
.counter
[0] = 0;
255 ChaCha20_ctr32(buf
, zero
, (buf_len
= 2 * CHACHA_BLK_SIZE
),
256 actx
->key
.key
.d
, actx
->key
.counter
);
257 Poly1305_Init(POLY1305_ctx(actx
), buf
);
258 actx
->key
.partial_len
= 0;
259 memcpy(tohash
, actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
260 tohash_len
= POLY1305_BLOCK_SIZE
;
261 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
262 actx
->len
.text
= plen
;
265 for (i
= 0; i
< plen
; i
++) {
266 out
[i
] = ctr
[i
] ^= in
[i
];
269 for (i
= 0; i
< plen
; i
++) {
270 unsigned char c
= in
[i
];
279 tail
= (0 - i
) & (POLY1305_BLOCK_SIZE
- 1);
280 memset(ctr
+ i
, 0, tail
);
282 tohash_len
+= i
+ tail
;
286 actx
->key
.counter
[0] = 0;
287 ChaCha20_ctr32(buf
, zero
, (buf_len
= CHACHA_BLK_SIZE
),
288 actx
->key
.key
.d
, actx
->key
.counter
);
289 Poly1305_Init(POLY1305_ctx(actx
), buf
);
290 actx
->key
.counter
[0] = 1;
291 actx
->key
.partial_len
= 0;
292 Poly1305_Update(POLY1305_ctx(actx
), actx
->tls_aad
, POLY1305_BLOCK_SIZE
);
295 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
296 actx
->len
.text
= plen
;
299 ChaCha20_ctr32(out
, in
, plen
, actx
->key
.key
.d
, actx
->key
.counter
);
300 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
302 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
303 ChaCha20_ctr32(out
, in
, plen
, actx
->key
.key
.d
, actx
->key
.counter
);
308 tail
= (0 - plen
) & (POLY1305_BLOCK_SIZE
- 1);
309 Poly1305_Update(POLY1305_ctx(actx
), zero
, tail
);
318 if (is_endian
.little
) {
319 memcpy(ctr
, (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
321 ctr
[0] = (unsigned char)(actx
->len
.aad
);
322 ctr
[1] = (unsigned char)(actx
->len
.aad
>>8);
323 ctr
[2] = (unsigned char)(actx
->len
.aad
>>16);
324 ctr
[3] = (unsigned char)(actx
->len
.aad
>>24);
325 ctr
[4] = (unsigned char)(actx
->len
.aad
>>32);
326 ctr
[5] = (unsigned char)(actx
->len
.aad
>>40);
327 ctr
[6] = (unsigned char)(actx
->len
.aad
>>48);
328 ctr
[7] = (unsigned char)(actx
->len
.aad
>>56);
330 ctr
[8] = (unsigned char)(actx
->len
.text
);
331 ctr
[9] = (unsigned char)(actx
->len
.text
>>8);
332 ctr
[10] = (unsigned char)(actx
->len
.text
>>16);
333 ctr
[11] = (unsigned char)(actx
->len
.text
>>24);
334 ctr
[12] = (unsigned char)(actx
->len
.text
>>32);
335 ctr
[13] = (unsigned char)(actx
->len
.text
>>40);
336 ctr
[14] = (unsigned char)(actx
->len
.text
>>48);
337 ctr
[15] = (unsigned char)(actx
->len
.text
>>56);
339 tohash_len
+= POLY1305_BLOCK_SIZE
;
342 Poly1305_Update(POLY1305_ctx(actx
), tohash
, tohash_len
);
343 OPENSSL_cleanse(buf
, buf_len
);
344 Poly1305_Final(POLY1305_ctx(actx
), ctx
->encrypt
? actx
->tag
347 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
350 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
352 if (CRYPTO_memcmp(tohash
, in
, POLY1305_BLOCK_SIZE
)) {
353 memset(out
- (len
- POLY1305_BLOCK_SIZE
), 0,
354 len
- POLY1305_BLOCK_SIZE
);
362 static const unsigned char zero
[CHACHA_BLK_SIZE
] = { 0 };
365 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
366 const unsigned char *in
, size_t len
)
368 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
369 size_t rem
, plen
= actx
->tls_payload_length
;
371 if (!actx
->mac_inited
) {
372 # if !defined(OPENSSL_SMALL_FOOTPRINT)
373 if (plen
!= NO_TLS_PAYLOAD_LENGTH
&& out
!= NULL
)
374 return chacha20_poly1305_tls_cipher(ctx
, out
, in
, len
);
376 actx
->key
.counter
[0] = 0;
377 ChaCha20_ctr32(actx
->key
.buf
, zero
, CHACHA_BLK_SIZE
,
378 actx
->key
.key
.d
, actx
->key
.counter
);
379 Poly1305_Init(POLY1305_ctx(actx
), actx
->key
.buf
);
380 actx
->key
.counter
[0] = 1;
381 actx
->key
.partial_len
= 0;
382 actx
->len
.aad
= actx
->len
.text
= 0;
383 actx
->mac_inited
= 1;
384 if (plen
!= NO_TLS_PAYLOAD_LENGTH
) {
385 Poly1305_Update(POLY1305_ctx(actx
), actx
->tls_aad
,
386 EVP_AEAD_TLS1_AAD_LEN
);
387 actx
->len
.aad
= EVP_AEAD_TLS1_AAD_LEN
;
392 if (in
) { /* aad or text */
393 if (out
== NULL
) { /* aad */
394 Poly1305_Update(POLY1305_ctx(actx
), in
, len
);
395 actx
->len
.aad
+= len
;
398 } else { /* plain- or ciphertext */
399 if (actx
->aad
) { /* wrap up aad */
400 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
401 Poly1305_Update(POLY1305_ctx(actx
), zero
,
402 POLY1305_BLOCK_SIZE
- rem
);
406 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
407 if (plen
== NO_TLS_PAYLOAD_LENGTH
)
409 else if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
412 if (ctx
->encrypt
) { /* plaintext */
413 chacha_cipher(ctx
, out
, in
, plen
);
414 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
417 actx
->len
.text
+= plen
;
418 } else { /* ciphertext */
419 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
420 chacha_cipher(ctx
, out
, in
, plen
);
423 actx
->len
.text
+= plen
;
427 if (in
== NULL
/* explicit final */
428 || plen
!= len
) { /* or tls mode */
433 unsigned char temp
[POLY1305_BLOCK_SIZE
];
435 if (actx
->aad
) { /* wrap up aad */
436 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
437 Poly1305_Update(POLY1305_ctx(actx
), zero
,
438 POLY1305_BLOCK_SIZE
- rem
);
442 if ((rem
= (size_t)actx
->len
.text
% POLY1305_BLOCK_SIZE
))
443 Poly1305_Update(POLY1305_ctx(actx
), zero
,
444 POLY1305_BLOCK_SIZE
- rem
);
446 if (is_endian
.little
) {
447 Poly1305_Update(POLY1305_ctx(actx
),
448 (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
450 temp
[0] = (unsigned char)(actx
->len
.aad
);
451 temp
[1] = (unsigned char)(actx
->len
.aad
>>8);
452 temp
[2] = (unsigned char)(actx
->len
.aad
>>16);
453 temp
[3] = (unsigned char)(actx
->len
.aad
>>24);
454 temp
[4] = (unsigned char)(actx
->len
.aad
>>32);
455 temp
[5] = (unsigned char)(actx
->len
.aad
>>40);
456 temp
[6] = (unsigned char)(actx
->len
.aad
>>48);
457 temp
[7] = (unsigned char)(actx
->len
.aad
>>56);
459 temp
[8] = (unsigned char)(actx
->len
.text
);
460 temp
[9] = (unsigned char)(actx
->len
.text
>>8);
461 temp
[10] = (unsigned char)(actx
->len
.text
>>16);
462 temp
[11] = (unsigned char)(actx
->len
.text
>>24);
463 temp
[12] = (unsigned char)(actx
->len
.text
>>32);
464 temp
[13] = (unsigned char)(actx
->len
.text
>>40);
465 temp
[14] = (unsigned char)(actx
->len
.text
>>48);
466 temp
[15] = (unsigned char)(actx
->len
.text
>>56);
468 Poly1305_Update(POLY1305_ctx(actx
), temp
, POLY1305_BLOCK_SIZE
);
470 Poly1305_Final(POLY1305_ctx(actx
), ctx
->encrypt
? actx
->tag
472 actx
->mac_inited
= 0;
474 if (in
!= NULL
&& len
!= plen
) { /* tls mode */
476 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
478 if (CRYPTO_memcmp(temp
, in
, POLY1305_BLOCK_SIZE
)) {
479 memset(out
- plen
, 0, plen
);
484 else if (!ctx
->encrypt
) {
485 if (CRYPTO_memcmp(temp
, actx
->tag
, actx
->tag_len
))
492 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX
*ctx
)
494 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
496 OPENSSL_cleanse(ctx
->cipher_data
, sizeof(*actx
) + Poly1305_ctx_size());
500 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
503 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
508 actx
= ctx
->cipher_data
509 = OPENSSL_zalloc(sizeof(*actx
) + Poly1305_ctx_size());
511 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_INITIALIZATION_ERROR
);
517 actx
->mac_inited
= 0;
519 actx
->nonce_len
= 12;
520 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
521 memset(actx
->tls_aad
, 0, POLY1305_BLOCK_SIZE
);
526 EVP_CIPHER_CTX
*dst
= (EVP_CIPHER_CTX
*)ptr
;
529 OPENSSL_memdup(actx
, sizeof(*actx
) + Poly1305_ctx_size());
530 if (dst
->cipher_data
== NULL
) {
531 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_COPY_ERROR
);
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
|| !ctx
->encrypt
)
566 memcpy(ptr
, actx
->tag
, arg
);
569 case EVP_CTRL_AEAD_TLS1_AAD
:
570 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
574 unsigned char *aad
= ptr
;
576 memcpy(actx
->tls_aad
, ptr
, EVP_AEAD_TLS1_AAD_LEN
);
577 len
= aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] << 8 |
578 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1];
581 if (len
< POLY1305_BLOCK_SIZE
)
583 len
-= POLY1305_BLOCK_SIZE
; /* discount attached tag */
584 aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] = (unsigned char)(len
>> 8);
585 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1] = (unsigned char)len
;
587 actx
->tls_payload_length
= len
;
590 * merge record sequence number as per RFC7905
592 actx
->key
.counter
[1] = actx
->nonce
[0];
593 actx
->key
.counter
[2] = actx
->nonce
[1] ^ CHACHA_U8TOU32(aad
);
594 actx
->key
.counter
[3] = actx
->nonce
[2] ^ CHACHA_U8TOU32(aad
+4);
595 actx
->mac_inited
= 0;
597 return POLY1305_BLOCK_SIZE
; /* tag length */
600 case EVP_CTRL_AEAD_SET_MAC_KEY
:
609 static EVP_CIPHER chacha20_poly1305
= {
610 NID_chacha20_poly1305
,
612 CHACHA_KEY_SIZE
, /* key_len */
613 12, /* iv_len, 96-bit nonce in the context */
614 EVP_CIPH_FLAG_AEAD_CIPHER
| EVP_CIPH_CUSTOM_IV
|
615 EVP_CIPH_ALWAYS_CALL_INIT
| EVP_CIPH_CTRL_INIT
|
616 EVP_CIPH_CUSTOM_COPY
| EVP_CIPH_FLAG_CUSTOM_CIPHER
,
617 chacha20_poly1305_init_key
,
618 chacha20_poly1305_cipher
,
619 chacha20_poly1305_cleanup
,
620 0, /* 0 moves context-specific structure allocation to ctrl */
621 NULL
, /* set_asn1_parameters */
622 NULL
, /* get_asn1_parameters */
623 chacha20_poly1305_ctrl
,
627 const EVP_CIPHER
*EVP_chacha20_poly1305(void)
629 return(&chacha20_poly1305
);