blob: d51227a557f3c582756e82544e72be845bc3e264 [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 */
Gilles Peskinedb09ef62020-06-03 01:43:33 +020023#include "common.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030024
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020025#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030026
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020027#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000029#include "mbedtls/error.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020030
Daniel Kingb8025c52016-05-17 14:43:01 -030031#include <string.h>
32
33#if defined(MBEDTLS_SELF_TEST)
34#if defined(MBEDTLS_PLATFORM_C)
35#include "mbedtls/platform.h"
36#else
37#include <stdio.h>
38#define mbedtls_printf printf
39#endif /* MBEDTLS_PLATFORM_C */
40#endif /* MBEDTLS_SELF_TEST */
41
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020042#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030043
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050044/* Parameter validation macros */
45#define CHACHAPOLY_VALIDATE_RET( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
47#define CHACHAPOLY_VALIDATE( cond ) \
48 MBEDTLS_INTERNAL_VALIDATE( cond )
49
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020050#define CHACHAPOLY_STATE_INIT ( 0 )
51#define CHACHAPOLY_STATE_AAD ( 1 )
52#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
53#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030054
Daniel Kingb8025c52016-05-17 14:43:01 -030055/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020056 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030057 *
58 * \param ctx The ChaCha20-Poly1305 context.
59 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020060static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030061{
Daniel Kinge6e79682016-05-24 11:16:17 -030062 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030063 unsigned char zeroes[15];
64
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020065 if( partial_block_len == 0U )
66 return( 0 );
67
68 memset( zeroes, 0, sizeof( zeroes ) );
69
70 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
71 zeroes,
72 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030073}
74
75/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020076 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030077 *
78 * \param ctx The ChaCha20-Poly1305 context.
79 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020080static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030081{
Daniel Kinge6e79682016-05-24 11:16:17 -030082 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030083 unsigned char zeroes[15];
84
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020085 if( partial_block_len == 0U )
86 return( 0 );
87
88 memset( zeroes, 0, sizeof( zeroes ) );
89 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
90 zeroes,
91 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030092}
93
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020094void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030095{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050096 CHACHAPOLY_VALIDATE( ctx != NULL );
97
98 mbedtls_chacha20_init( &ctx->chacha20_ctx );
99 mbedtls_poly1305_init( &ctx->poly1305_ctx );
100 ctx->aad_len = 0U;
101 ctx->ciphertext_len = 0U;
102 ctx->state = CHACHAPOLY_STATE_INIT;
103 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300104}
105
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200106void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300107{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500108 if( ctx == NULL )
109 return;
110
111 mbedtls_chacha20_free( &ctx->chacha20_ctx );
112 mbedtls_poly1305_free( &ctx->poly1305_ctx );
113 ctx->aad_len = 0U;
114 ctx->ciphertext_len = 0U;
115 ctx->state = CHACHAPOLY_STATE_INIT;
116 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300117}
118
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200119int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
120 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300121{
Janos Follath24eed8d2019-11-22 13:21:35 +0000122 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500123 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
124 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300125
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200126 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300127
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200128 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300129}
130
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200131int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
132 const unsigned char nonce[12],
133 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300134{
Janos Follath24eed8d2019-11-22 13:21:35 +0000135 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300136 unsigned char poly1305_key[64];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500137 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
138 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300139
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200140 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200141 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
142 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300143 goto cleanup;
144
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200145 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
146 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300147 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
148 * The other 256 bits are discarded.
149 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200150 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200151 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200152 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200153 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300154 goto cleanup;
155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300157
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200158 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300159 {
160 ctx->aad_len = 0U;
161 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200162 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300163 ctx->mode = mode;
164 }
165
166cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200167 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200168 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300169}
170
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200171int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200172 const unsigned char *aad,
173 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300174{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500175 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
176 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
177
178 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200179 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300180
181 ctx->aad_len += aad_len;
182
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200183 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300184}
185
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200186int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
187 size_t len,
188 const unsigned char *input,
189 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300190{
Janos Follath24eed8d2019-11-22 13:21:35 +0000191 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500192 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
193 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
194 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200195
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500196 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
197 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300198 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200199 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300200 }
201
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200202 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300203 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200204 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300205
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200206 ret = chachapoly_pad_aad( ctx );
207 if( ret != 0 )
208 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300209 }
210
211 ctx->ciphertext_len += len;
212
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200213 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300214 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200215 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
216 if( ret != 0 )
217 return( ret );
218
219 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
220 if( ret != 0 )
221 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300222 }
223 else /* DECRYPT */
224 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200225 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
226 if( ret != 0 )
227 return( ret );
228
229 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
230 if( ret != 0 )
231 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300232 }
233
234 return( 0 );
235}
236
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200237int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
238 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300239{
Janos Follath24eed8d2019-11-22 13:21:35 +0000240 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300241 unsigned char len_block[16];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500242 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
243 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300244
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500245 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300246 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200247 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300248 }
249
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200250 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300251 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200252 ret = chachapoly_pad_aad( ctx );
253 if( ret != 0 )
254 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300255 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200256 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300257 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200258 ret = chachapoly_pad_ciphertext( ctx );
259 if( ret != 0 )
260 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300261 }
262
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200263 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300264
265 /* The lengths of the AAD and ciphertext are processed by
266 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
267 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200268 len_block[ 0] = (unsigned char)( ctx->aad_len );
269 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
270 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
271 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
272 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
273 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
274 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
275 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
276 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
277 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
278 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
279 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
280 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
281 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
282 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
283 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300284
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200285 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
286 if( ret != 0 )
287 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300288
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200289 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
290
291 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300292}
293
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200294static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
295 mbedtls_chachapoly_mode_t mode,
296 size_t length,
297 const unsigned char nonce[12],
298 const unsigned char *aad,
299 size_t aad_len,
300 const unsigned char *input,
301 unsigned char *output,
302 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300303{
Janos Follath24eed8d2019-11-22 13:21:35 +0000304 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300305
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200306 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
307 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300308 goto cleanup;
309
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200310 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
311 if( ret != 0 )
312 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300313
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200314 ret = mbedtls_chachapoly_update( ctx, length, input, output );
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_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300319
320cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200321 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300322}
323
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200324int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
325 size_t length,
326 const unsigned char nonce[12],
327 const unsigned char *aad,
328 size_t aad_len,
329 const unsigned char *input,
330 unsigned char *output,
331 unsigned char tag[16] )
332{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500333 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
334 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
335 CHACHAPOLY_VALIDATE_RET( tag != NULL );
336 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
337 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
338 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
339
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200340 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
341 length, nonce, aad, aad_len,
342 input, output, tag ) );
343}
344
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200345int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
346 size_t length,
347 const unsigned char nonce[12],
348 const unsigned char *aad,
349 size_t aad_len,
350 const unsigned char tag[16],
351 const unsigned char *input,
352 unsigned char *output )
353{
Janos Follath24eed8d2019-11-22 13:21:35 +0000354 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200355 unsigned char check_tag[16];
356 size_t i;
357 int diff;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500358 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
359 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
360 CHACHAPOLY_VALIDATE_RET( tag != NULL );
361 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
362 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
363 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200364
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200365 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200366 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
367 aad, aad_len, input, output, check_tag ) ) != 0 )
368 {
369 return( ret );
370 }
371
372 /* Check tag in "constant-time" */
373 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
374 diff |= tag[i] ^ check_tag[i];
375
376 if( diff != 0 )
377 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200378 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200379 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
380 }
381
382 return( 0 );
383}
384
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200385#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200386
Daniel Kingb8025c52016-05-17 14:43:01 -0300387#if defined(MBEDTLS_SELF_TEST)
388
389static const unsigned char test_key[1][32] =
390{
391 {
392 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
393 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
394 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
395 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
396 }
397};
398
399static const unsigned char test_nonce[1][12] =
400{
401 {
402 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
403 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
404 }
405};
406
407static const unsigned char test_aad[1][12] =
408{
409 {
410 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
411 0xc4, 0xc5, 0xc6, 0xc7
412 }
413};
414
415static const size_t test_aad_len[1] =
416{
417 12U
418};
419
420static const unsigned char test_input[1][114] =
421{
422 {
423 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
424 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
425 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
426 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
427 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
428 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
429 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
430 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
431 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
432 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
433 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
434 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
435 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
436 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
437 0x74, 0x2e
438 }
439};
440
441static const unsigned char test_output[1][114] =
442{
443 {
444 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
445 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
446 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
447 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
448 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
449 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
450 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
451 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
452 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
453 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
454 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
455 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
456 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
457 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
458 0x61, 0x16
459 }
460};
461
462static const size_t test_input_len[1] =
463{
464 114U
465};
466
467static const unsigned char test_mac[1][16] =
468{
469 {
470 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
471 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
472 }
473};
474
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200475#define ASSERT( cond, args ) \
476 do \
477 { \
478 if( ! ( cond ) ) \
479 { \
480 if( verbose != 0 ) \
481 mbedtls_printf args; \
482 \
483 return( -1 ); \
484 } \
485 } \
486 while( 0 )
487
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200488int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300489{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200490 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200491 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300493 unsigned char output[200];
494 unsigned char mac[16];
495
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200496 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300497 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200498 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200499 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300500
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200501 mbedtls_chachapoly_init( &ctx );
502
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200503 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
504 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200505
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200506 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
507 test_input_len[i],
508 test_nonce[i],
509 test_aad[i],
510 test_aad_len[i],
511 test_input[i],
512 output,
513 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300514
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200515 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300516
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200517 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
518 ( "failure (wrong output)\n" ) );
519
520 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
521 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300522
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200523 mbedtls_chachapoly_free( &ctx );
524
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200525 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300526 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300527 }
528
529 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300530 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300531
532 return( 0 );
533}
534
535#endif /* MBEDTLS_SELF_TEST */
536
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200537#endif /* MBEDTLS_CHACHAPOLY_C */