1 /* ====================================================================
2 * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@openssl.org.
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
30 * 6. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
52 #include "internal/cryptlib.h"
54 #ifndef OPENSSL_NO_CHACHA
56 # include <openssl/evp.h>
57 # include <openssl/objects.h>
58 # include "evp_locl.h"
59 # include "internal/evp_int.h"
60 # include "internal/chacha.h"
64 double align
; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
65 unsigned int d
[CHACHA_KEY_SIZE
/ 4];
67 unsigned int counter
[CHACHA_CTR_SIZE
/ 4];
68 unsigned char buf
[CHACHA_BLK_SIZE
];
69 unsigned int partial_len
;
72 #define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
74 static int chacha_init_key(EVP_CIPHER_CTX
*ctx
,
75 const unsigned char user_key
[CHACHA_KEY_SIZE
],
76 const unsigned char iv
[CHACHA_CTR_SIZE
], int enc
)
78 EVP_CHACHA_KEY
*key
= data(ctx
);
82 for (i
= 0; i
< CHACHA_KEY_SIZE
; i
+=4) {
83 key
->key
.d
[i
/4] = CHACHA_U8TOU32(user_key
+i
);
87 for (i
= 0; i
< CHACHA_CTR_SIZE
; i
+=4) {
88 key
->counter
[i
/4] = CHACHA_U8TOU32(iv
+i
);
96 static int chacha_cipher(EVP_CIPHER_CTX
* ctx
, unsigned char *out
,
97 const unsigned char *inp
, size_t len
)
99 EVP_CHACHA_KEY
*key
= data(ctx
);
100 unsigned int n
, rem
, ctr32
;
102 if ((n
= key
->partial_len
)) {
103 while (len
&& n
< CHACHA_BLK_SIZE
) {
104 *out
++ = *inp
++ ^ key
->buf
[n
++];
107 key
->partial_len
= n
;
112 if (n
== CHACHA_BLK_SIZE
) {
113 key
->partial_len
= 0;
115 if (key
->counter
[0] == 0)
120 rem
= (unsigned int)(len
% CHACHA_BLK_SIZE
);
122 ctr32
= key
->counter
[0];
123 while (len
>= CHACHA_BLK_SIZE
) {
124 size_t blocks
= len
/ CHACHA_BLK_SIZE
;
126 * 1<<28 is just a not-so-small yet not-so-large number...
127 * Below condition is practically never met, but it has to
128 * be checked for code correctness.
130 if (sizeof(size_t)>sizeof(unsigned int) && blocks
>(1U<<28))
134 * As ChaCha20_ctr32 operates on 32-bit counter, caller
135 * has to handle overflow. 'if' below detects the
136 * overflow, which is then handled by limiting the
137 * amount of blocks to the exact overflow point...
139 ctr32
+= (unsigned int)blocks
;
140 if (ctr32
< blocks
) {
144 blocks
*= CHACHA_BLK_SIZE
;
145 ChaCha20_ctr32(out
, inp
, blocks
, key
->key
.d
, key
->counter
);
150 key
->counter
[0] = ctr32
;
151 if (ctr32
== 0) key
->counter
[1]++;
155 memset(key
->buf
, 0, sizeof(key
->buf
));
156 ChaCha20_ctr32(key
->buf
, key
->buf
, CHACHA_BLK_SIZE
,
157 key
->key
.d
, key
->counter
);
158 for (n
= 0; n
< rem
; n
++)
159 out
[n
] = inp
[n
] ^ key
->buf
[n
];
160 key
->partial_len
= rem
;
166 static const EVP_CIPHER chacha20
= {
169 CHACHA_KEY_SIZE
, /* key_len */
170 CHACHA_CTR_SIZE
, /* iv_len, 128-bit counter in the context */
175 sizeof(EVP_CHACHA_KEY
),
182 const EVP_CIPHER
*EVP_chacha20(void)
187 # ifndef OPENSSL_NO_POLY1305
188 # include "internal/poly1305.h"
192 unsigned int nonce
[12/4];
193 unsigned char tag
[POLY1305_BLOCK_SIZE
];
194 struct { uint64_t aad
, text
; } len
;
195 int aad
, mac_inited
, tag_len
, nonce_len
;
196 size_t tls_payload_length
;
197 } EVP_CHACHA_AEAD_CTX
;
199 # define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
200 # define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
201 # define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
203 static int chacha20_poly1305_init_key(EVP_CIPHER_CTX
*ctx
,
204 const unsigned char *inkey
,
205 const unsigned char *iv
, int enc
)
207 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
208 unsigned char temp
[CHACHA_CTR_SIZE
];
216 actx
->mac_inited
= 0;
217 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
219 /* pad on the left */
220 memset(temp
, 0, sizeof(temp
));
221 if (actx
->nonce_len
<= CHACHA_CTR_SIZE
)
222 memcpy(temp
+ CHACHA_CTR_SIZE
- actx
->nonce_len
, iv
, actx
->nonce_len
);
224 chacha_init_key(ctx
, inkey
, temp
, enc
);
226 actx
->nonce
[0] = actx
->key
.counter
[1];
227 actx
->nonce
[1] = actx
->key
.counter
[2];
228 actx
->nonce
[2] = actx
->key
.counter
[3];
233 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
234 const unsigned char *in
, size_t len
)
236 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
237 size_t rem
, plen
= actx
->tls_payload_length
;
238 static const unsigned char zero
[POLY1305_BLOCK_SIZE
] = { 0 };
240 if (!actx
->mac_inited
) {
241 actx
->key
.counter
[0] = 0;
242 memset(actx
->key
.buf
, 0, sizeof(actx
->key
.buf
));
243 ChaCha20_ctr32(actx
->key
.buf
, actx
->key
.buf
, CHACHA_BLK_SIZE
,
244 actx
->key
.key
.d
, actx
->key
.counter
);
245 Poly1305_Init(POLY1305_ctx(actx
), actx
->key
.buf
);
246 actx
->key
.counter
[0] = 1;
247 actx
->key
.partial_len
= 0;
248 actx
->len
.aad
= actx
->len
.text
= 0;
249 actx
->mac_inited
= 1;
252 if (in
) { /* aad or text */
253 if (out
== NULL
) { /* aad */
254 Poly1305_Update(POLY1305_ctx(actx
), in
, len
);
255 actx
->len
.aad
+= len
;
258 } else { /* plain- or ciphertext */
259 if (actx
->aad
) { /* wrap up aad */
260 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
261 Poly1305_Update(POLY1305_ctx(actx
), zero
,
262 POLY1305_BLOCK_SIZE
- rem
);
266 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
267 if (plen
== NO_TLS_PAYLOAD_LENGTH
)
269 else if (len
!= plen
+ POLY1305_BLOCK_SIZE
)
272 if (ctx
->encrypt
) { /* plaintext */
273 chacha_cipher(ctx
, out
, in
, plen
);
274 Poly1305_Update(POLY1305_ctx(actx
), out
, plen
);
277 actx
->len
.text
+= plen
;
278 } else { /* ciphertext */
279 Poly1305_Update(POLY1305_ctx(actx
), in
, plen
);
280 chacha_cipher(ctx
, out
, in
, plen
);
283 actx
->len
.text
+= plen
;
287 if (in
== NULL
/* explicit final */
288 || plen
!= len
) { /* or tls mode */
293 unsigned char temp
[POLY1305_BLOCK_SIZE
];
295 if (actx
->aad
) { /* wrap up aad */
296 if ((rem
= (size_t)actx
->len
.aad
% POLY1305_BLOCK_SIZE
))
297 Poly1305_Update(POLY1305_ctx(actx
), zero
,
298 POLY1305_BLOCK_SIZE
- rem
);
302 if ((rem
= (size_t)actx
->len
.text
% POLY1305_BLOCK_SIZE
))
303 Poly1305_Update(POLY1305_ctx(actx
), zero
,
304 POLY1305_BLOCK_SIZE
- rem
);
306 if (is_endian
.little
) {
307 Poly1305_Update(POLY1305_ctx(actx
),
308 (unsigned char *)&actx
->len
, POLY1305_BLOCK_SIZE
);
310 temp
[0] = (unsigned char)(actx
->len
.aad
);
311 temp
[1] = (unsigned char)(actx
->len
.aad
>>8);
312 temp
[2] = (unsigned char)(actx
->len
.aad
>>16);
313 temp
[3] = (unsigned char)(actx
->len
.aad
>>24);
314 temp
[4] = (unsigned char)(actx
->len
.aad
>>32);
315 temp
[5] = (unsigned char)(actx
->len
.aad
>>40);
316 temp
[6] = (unsigned char)(actx
->len
.aad
>>48);
317 temp
[7] = (unsigned char)(actx
->len
.aad
>>56);
319 temp
[8] = (unsigned char)(actx
->len
.text
);
320 temp
[9] = (unsigned char)(actx
->len
.text
>>8);
321 temp
[10] = (unsigned char)(actx
->len
.text
>>16);
322 temp
[11] = (unsigned char)(actx
->len
.text
>>24);
323 temp
[12] = (unsigned char)(actx
->len
.text
>>32);
324 temp
[13] = (unsigned char)(actx
->len
.text
>>40);
325 temp
[14] = (unsigned char)(actx
->len
.text
>>48);
326 temp
[15] = (unsigned char)(actx
->len
.text
>>56);
328 Poly1305_Update(POLY1305_ctx(actx
), temp
, POLY1305_BLOCK_SIZE
);
330 Poly1305_Final(POLY1305_ctx(actx
), ctx
->encrypt
? actx
->tag
332 actx
->mac_inited
= 0;
334 if (in
!= NULL
&& len
!= plen
) { /* tls mode */
336 memcpy(out
, actx
->tag
, POLY1305_BLOCK_SIZE
);
338 if (CRYPTO_memcmp(temp
, in
, POLY1305_BLOCK_SIZE
)) {
339 memset(out
, 0, plen
);
344 else if (!ctx
->encrypt
) {
345 if (CRYPTO_memcmp(temp
, actx
->tag
, actx
->tag_len
))
352 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX
*ctx
)
354 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
356 OPENSSL_cleanse(ctx
->cipher_data
, sizeof(*ctx
) + Poly1305_ctx_size());
360 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
363 EVP_CHACHA_AEAD_CTX
*actx
= aead_data(ctx
);
368 actx
= ctx
->cipher_data
369 = OPENSSL_zalloc(sizeof(*actx
) + Poly1305_ctx_size());
371 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_INITIALIZATION_ERROR
);
377 actx
->mac_inited
= 0;
379 actx
->nonce_len
= 12;
380 actx
->tls_payload_length
= NO_TLS_PAYLOAD_LENGTH
;
385 if ((((EVP_CIPHER_CTX
*)ptr
)->cipher_data
=
386 OPENSSL_memdup(actx
,sizeof(*actx
) + Poly1305_ctx_size()))
388 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL
, EVP_R_COPY_ERROR
);
394 case EVP_CTRL_AEAD_SET_IVLEN
:
395 if (arg
<= 0 || arg
> CHACHA_CTR_SIZE
)
397 actx
->nonce_len
= arg
;
400 case EVP_CTRL_AEAD_SET_IV_FIXED
:
403 actx
->nonce
[0] = actx
->key
.counter
[1]
404 = CHACHA_U8TOU32((unsigned char *)ptr
);
405 actx
->nonce
[1] = actx
->key
.counter
[2]
406 = CHACHA_U8TOU32((unsigned char *)ptr
+4);
407 actx
->nonce
[2] = actx
->key
.counter
[3]
408 = CHACHA_U8TOU32((unsigned char *)ptr
+8);
411 case EVP_CTRL_AEAD_SET_TAG
:
412 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
)
415 memcpy(actx
->tag
, ptr
, arg
);
420 case EVP_CTRL_AEAD_GET_TAG
:
421 if (arg
<= 0 || arg
> POLY1305_BLOCK_SIZE
|| !ctx
->encrypt
)
423 memcpy(ptr
, actx
->tag
, arg
);
426 case EVP_CTRL_AEAD_TLS1_AAD
:
427 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
431 unsigned char *aad
= ptr
, temp
[POLY1305_BLOCK_SIZE
];
433 len
= aad
[EVP_AEAD_TLS1_AAD_LEN
- 2] << 8 |
434 aad
[EVP_AEAD_TLS1_AAD_LEN
- 1];
436 len
-= POLY1305_BLOCK_SIZE
; /* discount attached tag */
437 memcpy(temp
, aad
, EVP_AEAD_TLS1_AAD_LEN
- 2);
439 temp
[EVP_AEAD_TLS1_AAD_LEN
- 2] = (unsigned char)(len
>> 8);
440 temp
[EVP_AEAD_TLS1_AAD_LEN
- 1] = (unsigned char)len
;
442 actx
->tls_payload_length
= len
;
445 * merge record sequence number as per
446 * draft-ietf-tls-chacha20-poly1305-03
448 actx
->key
.counter
[1] = actx
->nonce
[0];
449 actx
->key
.counter
[2] = actx
->nonce
[1] ^ CHACHA_U8TOU32(aad
);
450 actx
->key
.counter
[3] = actx
->nonce
[2] ^ CHACHA_U8TOU32(aad
+4);
451 actx
->mac_inited
= 0;
452 chacha20_poly1305_cipher(ctx
, NULL
, aad
, EVP_AEAD_TLS1_AAD_LEN
);
453 return POLY1305_BLOCK_SIZE
; /* tag length */
456 case EVP_CTRL_AEAD_SET_MAC_KEY
:
465 static EVP_CIPHER chacha20_poly1305
= {
466 NID_chacha20_poly1305
,
468 CHACHA_KEY_SIZE
, /* key_len */
469 12, /* iv_len, 96-bit nonce in the context */
470 EVP_CIPH_FLAG_AEAD_CIPHER
| EVP_CIPH_CUSTOM_IV
|
471 EVP_CIPH_ALWAYS_CALL_INIT
| EVP_CIPH_CTRL_INIT
|
472 EVP_CIPH_CUSTOM_COPY
| EVP_CIPH_FLAG_CUSTOM_CIPHER
,
473 chacha20_poly1305_init_key
,
474 chacha20_poly1305_cipher
,
475 chacha20_poly1305_cleanup
,
476 0, /* 0 moves context-specific structure allocation to ctrl */
477 NULL
, /* set_asn1_parameters */
478 NULL
, /* get_asn1_parameters */
479 chacha20_poly1305_ctrl
,
483 const EVP_CIPHER
*EVP_chacha20_poly1305(void)
485 return(&chacha20_poly1305
);