2 * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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 "evp_locl.h"
18 # include "internal/evp_int.h"
19 # include "internal/chacha.h"
23 double 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 static int chacha_init_key(EVP_CIPHER_CTX
*ctx
,
34 const unsigned char user_key
[CHACHA_KEY_SIZE
],
35 const unsigned char iv
[CHACHA_CTR_SIZE
], int enc
)
37 EVP_CHACHA_KEY
*key
= data(ctx
);
41 for (i
= 0; i
< CHACHA_KEY_SIZE
; i
+=4) {
42 key
->key
.d
[i
/4] = CHACHA_U8TOU32(user_key
+i
);
46 for (i
= 0; i
< CHACHA_CTR_SIZE
; i
+=4) {
47 key
->counter
[i
/4] = CHACHA_U8TOU32(iv
+i
);
55 static int chacha_cipher(EVP_CIPHER_CTX
* ctx
, unsigned char *out
,
56 const unsigned char *inp
, size_t len
)
58 EVP_CHACHA_KEY
*key
= data(ctx
);
59 unsigned int n
, rem
, ctr32
;
61 if ((n
= key
->partial_len
)) {
62 while (len
&& n
< CHACHA_BLK_SIZE
) {
63 *out
++ = *inp
++ ^ key
->buf
[n
++];
71 if (n
== CHACHA_BLK_SIZE
) {
74 if (key
->counter
[0] == 0)
79 rem
= (unsigned int)(len
% CHACHA_BLK_SIZE
);
81 ctr32
= key
->counter
[0];
82 while (len
>= CHACHA_BLK_SIZE
) {
83 size_t blocks
= len
/ CHACHA_BLK_SIZE
;
85 * 1<<28 is just a not-so-small yet not-so-large number...
86 * Below condition is practically never met, but it has to
87 * be checked for code correctness.
89 if (sizeof(size_t)>sizeof(unsigned int) && blocks
>(1U<<28))
93 * As ChaCha20_ctr32 operates on 32-bit counter, caller
94 * has to handle overflow. 'if' below detects the
95 * overflow, which is then handled by limiting the
96 * amount of blocks to the exact overflow point...
98 ctr32
+= (unsigned int)blocks
;
103 blocks
*= CHACHA_BLK_SIZE
;
104 ChaCha20_ctr32(out
, inp
, blocks
, key
->key
.d
, key
->counter
);
109 key
->counter
[0] = ctr32
;
110 if (ctr32
== 0) key
->counter
[1]++;
114 memset(key
->buf
, 0, sizeof(key
->buf
));
115 ChaCha20_ctr32(key
->buf
, key
->buf
, CHACHA_BLK_SIZE
,
116 key
->key
.d
, key
->counter
);
117 for (n
= 0; n
< rem
; n
++)
118 out
[n
] = inp
[n
] ^ key
->buf
[n
];
119 key
->partial_len
= rem
;
125 static const EVP_CIPHER chacha20
= {
128 CHACHA_KEY_SIZE
, /* key_len */
129 CHACHA_CTR_SIZE
, /* iv_len, 128-bit counter in the context */
134 sizeof(EVP_CHACHA_KEY
),
141 const EVP_CIPHER
*EVP_chacha20(void)
146 # ifndef OPENSSL_NO_POLY1305
147 # include "internal/poly1305.h"
151 unsigned int nonce
[12/4];
152 unsigned char tag
[POLY1305_BLOCK_SIZE
];
153 struct { uint64_t aad
, text
; } len
;
154 int aad
, mac_inited
, tag_len
, nonce_len
;
155 size_t tls_payload_length
;
156 } EVP_CHACHA_AEAD_CTX
;
158 # define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
159 # define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
160 # define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
162 static int chacha20_poly1305_init_key(EVP_CIPHER_CTX
*ctx
,
163 const unsigned char *inkey
,
164 const unsigned char *iv
, int enc
)
166 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
174 actx
->mac_inited
= 0;
175 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
178 unsigned char temp
[CHACHA_CTR_SIZE
] = { 0 };
180 /* pad on the left */
181 if (actx
->nonce_len
<= CHACHA_CTR_SIZE
)
182 memcpy(temp
+ CHACHA_CTR_SIZE
- actx
->nonce_len
, iv
, actx
->nonce_len
);
184 chacha_init_key(ctx
, inkey
, temp
, enc
);
186 actx
->nonce
[0] = actx
->key
.counter
[1];
187 actx
->nonce
[1] = actx
->key
.counter
[2];
188 actx
->nonce
[2] = actx
->key
.counter
[3];
190 chacha_init_key(ctx
, inkey
, NULL
, enc
);
196 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
197 const unsigned char *in
, size_t len
)
199 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
200 size_t rem
, plen
= actx
->tls_payload_length
;
201 static const unsigned char zero
[POLY1305_BLOCK_SIZE
] = { 0 };
203 if (!actx
->mac_inited
) {
204 actx
->key
.counter
[0] = 0;
205 memset(actx
->key
.buf
, 0, sizeof(actx
->key
.buf
));
206 ChaCha20_ctr32(actx
->key
.buf
, actx
->key
.buf
, CHACHA_BLK_SIZE
,
207 actx
->key
.key
.d
, actx
->key
.counter
);
208 Poly1305_Init(POLY1305_ctx(actx
), actx
->key
.buf
);
209 actx
->key
.counter
[0] = 1;
210 actx
->key
.partial_len
= 0;
211 actx
->len
.aad
= actx
->len
.text
= 0;
212 actx
->mac_inited
= 1;
215 if (in
) { /* aad or text */
216 if (out
== NULL
) { /* aad */
217 Poly1305_Update(POLY1305_ctx(actx
), in
, len
);
218 actx
->len
.aad
+= len
;
221 } else { /* plain- or ciphertext */
222 if (actx
->aad
) { /* wrap up aad */
223 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
224 Poly1305_Update(POLY1305_ctx(actx
), zero
,
225 POLY1305_BLOCK_SIZE
- rem
);
229 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
230 if (plen
== NO_TLS_PAYLOAD_LENGTH
)
232 else if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
235 if (ctx
->encrypt
) { /* plaintext */
236 chacha_cipher(ctx
, out
, in
, plen
);
237 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
240 actx
->len
.text
+= plen
;
241 } else { /* ciphertext */
242 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
243 chacha_cipher(ctx
, out
, in
, plen
);
246 actx
->len
.text
+= plen
;
250 if (in
== NULL
/* explicit final */
251 || plen
!= len
) { /* or tls mode */
256 unsigned char temp
[POLY1305_BLOCK_SIZE
];
258 if (actx
->aad
) { /* wrap up aad */
259 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
260 Poly1305_Update(POLY1305_ctx(actx
), zero
,
261 POLY1305_BLOCK_SIZE
- rem
);
265 if ((rem
= (size_t)actx
->len
.text
% POLY1305_BLOCK_SIZE
))
266 Poly1305_Update(POLY1305_ctx(actx
), zero
,
267 POLY1305_BLOCK_SIZE
- rem
);
269 if (is_endian
.little
) {
270 Poly1305_Update(POLY1305_ctx(actx
),
271 (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
273 temp
[0] = (unsigned char)(actx
->len
.aad
);
274 temp
[1] = (unsigned char)(actx
->len
.aad
>>8);
275 temp
[2] = (unsigned char)(actx
->len
.aad
>>16);
276 temp
[3] = (unsigned char)(actx
->len
.aad
>>24);
277 temp
[4] = (unsigned char)(actx
->len
.aad
>>32);
278 temp
[5] = (unsigned char)(actx
->len
.aad
>>40);
279 temp
[6] = (unsigned char)(actx
->len
.aad
>>48);
280 temp
[7] = (unsigned char)(actx
->len
.aad
>>56);
282 temp
[8] = (unsigned char)(actx
->len
.text
);
283 temp
[9] = (unsigned char)(actx
->len
.text
>>8);
284 temp
[10] = (unsigned char)(actx
->len
.text
>>16);
285 temp
[11] = (unsigned char)(actx
->len
.text
>>24);
286 temp
[12] = (unsigned char)(actx
->len
.text
>>32);
287 temp
[13] = (unsigned char)(actx
->len
.text
>>40);
288 temp
[14] = (unsigned char)(actx
->len
.text
>>48);
289 temp
[15] = (unsigned char)(actx
->len
.text
>>56);
291 Poly1305_Update(POLY1305_ctx(actx
), temp
, POLY1305_BLOCK_SIZE
);
293 Poly1305_Final(POLY1305_ctx(actx
), ctx
->encrypt
? actx
->tag
295 actx
->mac_inited
= 0;
297 if (in
!= NULL
&& len
!= plen
) { /* tls mode */
299 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
301 if (CRYPTO_memcmp(temp
, in
, POLY1305_BLOCK_SIZE
)) {
302 memset(out
, 0, plen
);
307 else if (!ctx
->encrypt
) {
308 if (CRYPTO_memcmp(temp
, actx
->tag
, actx
->tag_len
))
315 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX
*ctx
)
317 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
319 OPENSSL_cleanse(ctx
->cipher_data
, sizeof(*ctx
) + Poly1305_ctx_size());
323 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
326 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
331 actx
= ctx
->cipher_data
332 = OPENSSL_zalloc(sizeof(*actx
) + Poly1305_ctx_size());
334 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_INITIALIZATION_ERROR
);
340 actx
->mac_inited
= 0;
342 actx
->nonce_len
= 12;
343 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
348 if ((((EVP_CIPHER_CTX
*)ptr
)->cipher_data
=
349 OPENSSL_memdup(actx
,sizeof(*actx
) + Poly1305_ctx_size()))
351 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_COPY_ERROR
);
357 case EVP_CTRL_AEAD_SET_IVLEN
:
358 if (arg
<= 0 || arg
> CHACHA_CTR_SIZE
)
360 actx
->nonce_len
= arg
;
363 case EVP_CTRL_AEAD_SET_IV_FIXED
:
366 actx
->nonce
[0] = actx
->key
.counter
[1]
367 = CHACHA_U8TOU32((unsigned char *)ptr
);
368 actx
->nonce
[1] = actx
->key
.counter
[2]
369 = CHACHA_U8TOU32((unsigned char *)ptr
+4);
370 actx
->nonce
[2] = actx
->key
.counter
[3]
371 = CHACHA_U8TOU32((unsigned char *)ptr
+8);
374 case EVP_CTRL_AEAD_SET_TAG
:
375 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
)
378 memcpy(actx
->tag
, ptr
, arg
);
383 case EVP_CTRL_AEAD_GET_TAG
:
384 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
|| !ctx
->encrypt
)
386 memcpy(ptr
, actx
->tag
, arg
);
389 case EVP_CTRL_AEAD_TLS1_AAD
:
390 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
394 unsigned char *aad
= ptr
, temp
[POLY1305_BLOCK_SIZE
];
396 len
= aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] << 8 |
397 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1];
399 len
-= POLY1305_BLOCK_SIZE
; /* discount attached tag */
400 memcpy(temp
, aad
, EVP_AEAD_TLS1_AAD_LEN
- 2);
402 temp
[EVP_AEAD_TLS1_AAD_LEN
- 2] = (unsigned char)(len
>> 8);
403 temp
[EVP_AEAD_TLS1_AAD_LEN
- 1] = (unsigned char)len
;
405 actx
->tls_payload_length
= len
;
408 * merge record sequence number as per
409 * draft-ietf-tls-chacha20-poly1305-03
411 actx
->key
.counter
[1] = actx
->nonce
[0];
412 actx
->key
.counter
[2] = actx
->nonce
[1] ^ CHACHA_U8TOU32(aad
);
413 actx
->key
.counter
[3] = actx
->nonce
[2] ^ CHACHA_U8TOU32(aad
+4);
414 actx
->mac_inited
= 0;
415 chacha20_poly1305_cipher(ctx
, NULL
, aad
, EVP_AEAD_TLS1_AAD_LEN
);
416 return POLY1305_BLOCK_SIZE
; /* tag length */
419 case EVP_CTRL_AEAD_SET_MAC_KEY
:
428 static EVP_CIPHER chacha20_poly1305
= {
429 NID_chacha20_poly1305
,
431 CHACHA_KEY_SIZE
, /* key_len */
432 12, /* iv_len, 96-bit nonce in the context */
433 EVP_CIPH_FLAG_AEAD_CIPHER
| EVP_CIPH_CUSTOM_IV
|
434 EVP_CIPH_ALWAYS_CALL_INIT
| EVP_CIPH_CTRL_INIT
|
435 EVP_CIPH_CUSTOM_COPY
| EVP_CIPH_FLAG_CUSTOM_CIPHER
,
436 chacha20_poly1305_init_key
,
437 chacha20_poly1305_cipher
,
438 chacha20_poly1305_cleanup
,
439 0, /* 0 moves context-specific structure allocation to ctrl */
440 NULL
, /* set_asn1_parameters */
441 NULL
, /* get_asn1_parameters */
442 chacha20_poly1305_ctrl
,
446 const EVP_CIPHER
*EVP_chacha20_poly1305(void)
448 return(&chacha20_poly1305
);