blob: f0af5ded2670e0e3fac396b557f6ec8d964c1440 [file] [log] [blame]
Daniel Kingb8025c52016-05-17 14:43:01 -03001/**
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +02002 * \file chachapoly.c
Daniel Kingb8025c52016-05-17 14:43:01 -03003 *
4 * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
5 *
6 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23#if !defined(MBEDTLS_CONFIG_FILE)
24#include "mbedtls/config.h"
25#else
26#include MBEDTLS_CONFIG_FILE
27#endif
28
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020029#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030030
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020031#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020032#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000033#include "mbedtls/error.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020034
Daniel Kingb8025c52016-05-17 14:43:01 -030035#include <string.h>
36
37#if defined(MBEDTLS_SELF_TEST)
38#if defined(MBEDTLS_PLATFORM_C)
39#include "mbedtls/platform.h"
40#else
41#include <stdio.h>
42#define mbedtls_printf printf
43#endif /* MBEDTLS_PLATFORM_C */
44#endif /* MBEDTLS_SELF_TEST */
45
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020046#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030047
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050048/* Parameter validation macros */
49#define CHACHAPOLY_VALIDATE_RET( cond ) \
50 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
51#define CHACHAPOLY_VALIDATE( cond ) \
52 MBEDTLS_INTERNAL_VALIDATE( cond )
53
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020054#define CHACHAPOLY_STATE_INIT ( 0 )
55#define CHACHAPOLY_STATE_AAD ( 1 )
56#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
57#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030058
Daniel Kingb8025c52016-05-17 14:43:01 -030059/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020060 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030061 *
62 * \param ctx The ChaCha20-Poly1305 context.
63 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020064static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030065{
Daniel Kinge6e79682016-05-24 11:16:17 -030066 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030067 unsigned char zeroes[15];
68
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020069 if( partial_block_len == 0U )
70 return( 0 );
71
72 memset( zeroes, 0, sizeof( zeroes ) );
73
74 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
75 zeroes,
76 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030077}
78
79/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020080 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030081 *
82 * \param ctx The ChaCha20-Poly1305 context.
83 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020084static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030085{
Daniel Kinge6e79682016-05-24 11:16:17 -030086 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030087 unsigned char zeroes[15];
88
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020089 if( partial_block_len == 0U )
90 return( 0 );
91
92 memset( zeroes, 0, sizeof( zeroes ) );
93 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
94 zeroes,
95 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030096}
97
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020098void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030099{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500100 CHACHAPOLY_VALIDATE( ctx != NULL );
101
102 mbedtls_chacha20_init( &ctx->chacha20_ctx );
103 mbedtls_poly1305_init( &ctx->poly1305_ctx );
104 ctx->aad_len = 0U;
105 ctx->ciphertext_len = 0U;
106 ctx->state = CHACHAPOLY_STATE_INIT;
107 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300108}
109
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200110void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300111{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500112 if( ctx == NULL )
113 return;
114
115 mbedtls_chacha20_free( &ctx->chacha20_ctx );
116 mbedtls_poly1305_free( &ctx->poly1305_ctx );
117 ctx->aad_len = 0U;
118 ctx->ciphertext_len = 0U;
119 ctx->state = CHACHAPOLY_STATE_INIT;
120 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300121}
122
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200123int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
124 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300125{
Janos Follath24eed8d2019-11-22 13:21:35 +0000126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500127 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
128 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300129
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200130 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300131
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200132 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300133}
134
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200135int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
136 const unsigned char nonce[12],
137 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300138{
Janos Follath24eed8d2019-11-22 13:21:35 +0000139 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300140 unsigned char poly1305_key[64];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500141 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
142 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300143
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200144 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200145 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
146 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300147 goto cleanup;
148
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200149 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
150 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300151 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
152 * The other 256 bits are discarded.
153 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200154 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200155 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200156 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200157 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300158 goto cleanup;
159
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200160 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300161
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200162 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300163 {
164 ctx->aad_len = 0U;
165 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200166 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300167 ctx->mode = mode;
168 }
169
170cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200171 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200172 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300173}
174
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200175int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200176 const unsigned char *aad,
177 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300178{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500179 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
180 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
181
182 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200183 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300184
185 ctx->aad_len += aad_len;
186
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200187 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300188}
189
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200190int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
191 size_t len,
192 const unsigned char *input,
193 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300194{
Janos Follath24eed8d2019-11-22 13:21:35 +0000195 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500196 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
197 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
198 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200199
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500200 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
201 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300202 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200203 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300204 }
205
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200206 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300207 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200208 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300209
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200210 ret = chachapoly_pad_aad( ctx );
211 if( ret != 0 )
212 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300213 }
214
215 ctx->ciphertext_len += len;
216
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200217 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300218 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200219 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
220 if( ret != 0 )
221 return( ret );
222
223 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
224 if( ret != 0 )
225 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300226 }
227 else /* DECRYPT */
228 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200229 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
230 if( ret != 0 )
231 return( ret );
232
233 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
234 if( ret != 0 )
235 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300236 }
237
238 return( 0 );
239}
240
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200241int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
242 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300243{
Janos Follath24eed8d2019-11-22 13:21:35 +0000244 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300245 unsigned char len_block[16];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500246 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
247 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300248
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500249 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300250 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200251 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300252 }
253
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200254 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300255 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200256 ret = chachapoly_pad_aad( ctx );
257 if( ret != 0 )
258 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300259 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200260 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300261 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200262 ret = chachapoly_pad_ciphertext( ctx );
263 if( ret != 0 )
264 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300265 }
266
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200267 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300268
269 /* The lengths of the AAD and ciphertext are processed by
270 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
271 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200272 len_block[ 0] = (unsigned char)( ctx->aad_len );
273 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
274 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
275 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
276 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
277 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
278 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
279 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
280 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
281 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
282 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
283 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
284 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
285 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
286 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
287 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300288
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200289 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
290 if( ret != 0 )
291 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300292
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200293 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
294
295 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300296}
297
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200298static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
299 mbedtls_chachapoly_mode_t mode,
300 size_t length,
301 const unsigned char nonce[12],
302 const unsigned char *aad,
303 size_t aad_len,
304 const unsigned char *input,
305 unsigned char *output,
306 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300307{
Janos Follath24eed8d2019-11-22 13:21:35 +0000308 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300309
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200310 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
311 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300312 goto cleanup;
313
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200314 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
315 if( ret != 0 )
316 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300317
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200318 ret = mbedtls_chachapoly_update( ctx, length, input, output );
319 if( ret != 0 )
320 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300321
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200322 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300323
324cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200325 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300326}
327
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200328int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
329 size_t length,
330 const unsigned char nonce[12],
331 const unsigned char *aad,
332 size_t aad_len,
333 const unsigned char *input,
334 unsigned char *output,
335 unsigned char tag[16] )
336{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500337 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
338 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
339 CHACHAPOLY_VALIDATE_RET( tag != NULL );
340 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
341 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
342 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
343
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200344 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
345 length, nonce, aad, aad_len,
346 input, output, tag ) );
347}
348
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200349int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
350 size_t length,
351 const unsigned char nonce[12],
352 const unsigned char *aad,
353 size_t aad_len,
354 const unsigned char tag[16],
355 const unsigned char *input,
356 unsigned char *output )
357{
Janos Follath24eed8d2019-11-22 13:21:35 +0000358 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200359 unsigned char check_tag[16];
360 size_t i;
361 int diff;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500362 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
363 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
364 CHACHAPOLY_VALIDATE_RET( tag != NULL );
365 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
366 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
367 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200368
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200369 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200370 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
371 aad, aad_len, input, output, check_tag ) ) != 0 )
372 {
373 return( ret );
374 }
375
376 /* Check tag in "constant-time" */
377 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
378 diff |= tag[i] ^ check_tag[i];
379
380 if( diff != 0 )
381 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200382 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200383 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
384 }
385
386 return( 0 );
387}
388
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200389#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200390
Daniel Kingb8025c52016-05-17 14:43:01 -0300391#if defined(MBEDTLS_SELF_TEST)
392
393static const unsigned char test_key[1][32] =
394{
395 {
396 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
397 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
398 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
399 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
400 }
401};
402
403static const unsigned char test_nonce[1][12] =
404{
405 {
406 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
407 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
408 }
409};
410
411static const unsigned char test_aad[1][12] =
412{
413 {
414 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
415 0xc4, 0xc5, 0xc6, 0xc7
416 }
417};
418
419static const size_t test_aad_len[1] =
420{
421 12U
422};
423
424static const unsigned char test_input[1][114] =
425{
426 {
427 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
428 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
429 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
430 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
431 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
432 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
433 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
434 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
435 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
436 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
437 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
438 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
439 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
440 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
441 0x74, 0x2e
442 }
443};
444
445static const unsigned char test_output[1][114] =
446{
447 {
448 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
449 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
450 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
451 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
452 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
453 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
454 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
455 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
456 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
457 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
458 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
459 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
460 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
461 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
462 0x61, 0x16
463 }
464};
465
466static const size_t test_input_len[1] =
467{
468 114U
469};
470
471static const unsigned char test_mac[1][16] =
472{
473 {
474 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
475 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
476 }
477};
478
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200479#define ASSERT( cond, args ) \
480 do \
481 { \
482 if( ! ( cond ) ) \
483 { \
484 if( verbose != 0 ) \
485 mbedtls_printf args; \
486 \
487 return( -1 ); \
488 } \
489 } \
490 while( 0 )
491
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200492int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300493{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200494 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200495 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300497 unsigned char output[200];
498 unsigned char mac[16];
499
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200500 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300501 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200502 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200503 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300504
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200505 mbedtls_chachapoly_init( &ctx );
506
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200507 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
508 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200509
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200510 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
511 test_input_len[i],
512 test_nonce[i],
513 test_aad[i],
514 test_aad_len[i],
515 test_input[i],
516 output,
517 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300518
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200519 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300520
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200521 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
522 ( "failure (wrong output)\n" ) );
523
524 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
525 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300526
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200527 mbedtls_chachapoly_free( &ctx );
528
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200529 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300530 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300531 }
532
533 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300534 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300535
536 return( 0 );
537}
538
539#endif /* MBEDTLS_SELF_TEST */
540
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200541#endif /* MBEDTLS_CHACHAPOLY_C */