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
);
167 unsigned char temp
[CHACHA_CTR_SIZE
];
175 actx
->mac_inited
= 0;
176 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
178 /* pad on the left */
179 memset(temp
, 0, sizeof(temp
));
180 if (actx
->nonce_len
<= CHACHA_CTR_SIZE
)
181 memcpy(temp
+ CHACHA_CTR_SIZE
- actx
->nonce_len
, iv
, actx
->nonce_len
);
183 chacha_init_key(ctx
, inkey
, temp
, enc
);
185 actx
->nonce
[0] = actx
->key
.counter
[1];
186 actx
->nonce
[1] = actx
->key
.counter
[2];
187 actx
->nonce
[2] = actx
->key
.counter
[3];
192 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
193 const unsigned char *in
, size_t len
)
195 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
196 size_t rem
, plen
= actx
->tls_payload_length
;
197 static const unsigned char zero
[POLY1305_BLOCK_SIZE
] = { 0 };
199 if (!actx
->mac_inited
) {
200 actx
->key
.counter
[0] = 0;
201 memset(actx
->key
.buf
, 0, sizeof(actx
->key
.buf
));
202 ChaCha20_ctr32(actx
->key
.buf
, actx
->key
.buf
, CHACHA_BLK_SIZE
,
203 actx
->key
.key
.d
, actx
->key
.counter
);
204 Poly1305_Init(POLY1305_ctx(actx
), actx
->key
.buf
);
205 actx
->key
.counter
[0] = 1;
206 actx
->key
.partial_len
= 0;
207 actx
->len
.aad
= actx
->len
.text
= 0;
208 actx
->mac_inited
= 1;
211 if (in
) { /* aad or text */
212 if (out
== NULL
) { /* aad */
213 Poly1305_Update(POLY1305_ctx(actx
), in
, len
);
214 actx
->len
.aad
+= len
;
217 } else { /* plain- or ciphertext */
218 if (actx
->aad
) { /* wrap up aad */
219 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
220 Poly1305_Update(POLY1305_ctx(actx
), zero
,
221 POLY1305_BLOCK_SIZE
- rem
);
225 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
226 if (plen
== NO_TLS_PAYLOAD_LENGTH
)
228 else if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
231 if (ctx
->encrypt
) { /* plaintext */
232 chacha_cipher(ctx
, out
, in
, plen
);
233 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
236 actx
->len
.text
+= plen
;
237 } else { /* ciphertext */
238 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
239 chacha_cipher(ctx
, out
, in
, plen
);
242 actx
->len
.text
+= plen
;
246 if (in
== NULL
/* explicit final */
247 || plen
!= len
) { /* or tls mode */
252 unsigned char temp
[POLY1305_BLOCK_SIZE
];
254 if (actx
->aad
) { /* wrap up aad */
255 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
256 Poly1305_Update(POLY1305_ctx(actx
), zero
,
257 POLY1305_BLOCK_SIZE
- rem
);
261 if ((rem
= (size_t)actx
->len
.text
% POLY1305_BLOCK_SIZE
))
262 Poly1305_Update(POLY1305_ctx(actx
), zero
,
263 POLY1305_BLOCK_SIZE
- rem
);
265 if (is_endian
.little
) {
266 Poly1305_Update(POLY1305_ctx(actx
),
267 (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
269 temp
[0] = (unsigned char)(actx
->len
.aad
);
270 temp
[1] = (unsigned char)(actx
->len
.aad
>>8);
271 temp
[2] = (unsigned char)(actx
->len
.aad
>>16);
272 temp
[3] = (unsigned char)(actx
->len
.aad
>>24);
273 temp
[4] = (unsigned char)(actx
->len
.aad
>>32);
274 temp
[5] = (unsigned char)(actx
->len
.aad
>>40);
275 temp
[6] = (unsigned char)(actx
->len
.aad
>>48);
276 temp
[7] = (unsigned char)(actx
->len
.aad
>>56);
278 temp
[8] = (unsigned char)(actx
->len
.text
);
279 temp
[9] = (unsigned char)(actx
->len
.text
>>8);
280 temp
[10] = (unsigned char)(actx
->len
.text
>>16);
281 temp
[11] = (unsigned char)(actx
->len
.text
>>24);
282 temp
[12] = (unsigned char)(actx
->len
.text
>>32);
283 temp
[13] = (unsigned char)(actx
->len
.text
>>40);
284 temp
[14] = (unsigned char)(actx
->len
.text
>>48);
285 temp
[15] = (unsigned char)(actx
->len
.text
>>56);
287 Poly1305_Update(POLY1305_ctx(actx
), temp
, POLY1305_BLOCK_SIZE
);
289 Poly1305_Final(POLY1305_ctx(actx
), ctx
->encrypt
? actx
->tag
291 actx
->mac_inited
= 0;
293 if (in
!= NULL
&& len
!= plen
) { /* tls mode */
295 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
297 if (CRYPTO_memcmp(temp
, in
, POLY1305_BLOCK_SIZE
)) {
298 memset(out
, 0, plen
);
303 else if (!ctx
->encrypt
) {
304 if (CRYPTO_memcmp(temp
, actx
->tag
, actx
->tag_len
))
311 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX
*ctx
)
313 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
315 OPENSSL_cleanse(ctx
->cipher_data
, sizeof(*ctx
) + Poly1305_ctx_size());
319 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
322 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
327 actx
= ctx
->cipher_data
328 = OPENSSL_zalloc(sizeof(*actx
) + Poly1305_ctx_size());
330 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_INITIALIZATION_ERROR
);
336 actx
->mac_inited
= 0;
338 actx
->nonce_len
= 12;
339 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
344 if ((((EVP_CIPHER_CTX
*)ptr
)->cipher_data
=
345 OPENSSL_memdup(actx
,sizeof(*actx
) + Poly1305_ctx_size()))
347 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_COPY_ERROR
);
353 case EVP_CTRL_AEAD_SET_IVLEN
:
354 if (arg
<= 0 || arg
> CHACHA_CTR_SIZE
)
356 actx
->nonce_len
= arg
;
359 case EVP_CTRL_AEAD_SET_IV_FIXED
:
362 actx
->nonce
[0] = actx
->key
.counter
[1]
363 = CHACHA_U8TOU32((unsigned char *)ptr
);
364 actx
->nonce
[1] = actx
->key
.counter
[2]
365 = CHACHA_U8TOU32((unsigned char *)ptr
+4);
366 actx
->nonce
[2] = actx
->key
.counter
[3]
367 = CHACHA_U8TOU32((unsigned char *)ptr
+8);
370 case EVP_CTRL_AEAD_SET_TAG
:
371 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
)
374 memcpy(actx
->tag
, ptr
, arg
);
379 case EVP_CTRL_AEAD_GET_TAG
:
380 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
|| !ctx
->encrypt
)
382 memcpy(ptr
, actx
->tag
, arg
);
385 case EVP_CTRL_AEAD_TLS1_AAD
:
386 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
390 unsigned char *aad
= ptr
, temp
[POLY1305_BLOCK_SIZE
];
392 len
= aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] << 8 |
393 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1];
395 len
-= POLY1305_BLOCK_SIZE
; /* discount attached tag */
396 memcpy(temp
, aad
, EVP_AEAD_TLS1_AAD_LEN
- 2);
398 temp
[EVP_AEAD_TLS1_AAD_LEN
- 2] = (unsigned char)(len
>> 8);
399 temp
[EVP_AEAD_TLS1_AAD_LEN
- 1] = (unsigned char)len
;
401 actx
->tls_payload_length
= len
;
404 * merge record sequence number as per
405 * draft-ietf-tls-chacha20-poly1305-03
407 actx
->key
.counter
[1] = actx
->nonce
[0];
408 actx
->key
.counter
[2] = actx
->nonce
[1] ^ CHACHA_U8TOU32(aad
);
409 actx
->key
.counter
[3] = actx
->nonce
[2] ^ CHACHA_U8TOU32(aad
+4);
410 actx
->mac_inited
= 0;
411 chacha20_poly1305_cipher(ctx
, NULL
, aad
, EVP_AEAD_TLS1_AAD_LEN
);
412 return POLY1305_BLOCK_SIZE
; /* tag length */
415 case EVP_CTRL_AEAD_SET_MAC_KEY
:
424 static EVP_CIPHER chacha20_poly1305
= {
425 NID_chacha20_poly1305
,
427 CHACHA_KEY_SIZE
, /* key_len */
428 12, /* iv_len, 96-bit nonce in the context */
429 EVP_CIPH_FLAG_AEAD_CIPHER
| EVP_CIPH_CUSTOM_IV
|
430 EVP_CIPH_ALWAYS_CALL_INIT
| EVP_CIPH_CTRL_INIT
|
431 EVP_CIPH_CUSTOM_COPY
| EVP_CIPH_FLAG_CUSTOM_CIPHER
,
432 chacha20_poly1305_init_key
,
433 chacha20_poly1305_cipher
,
434 chacha20_poly1305_cleanup
,
435 0, /* 0 moves context-specific structure allocation to ctrl */
436 NULL
, /* set_asn1_parameters */
437 NULL
, /* get_asn1_parameters */
438 chacha20_poly1305_ctrl
,
442 const EVP_CIPHER
*EVP_chacha20_poly1305(void)
444 return(&chacha20_poly1305
);