blob: dc75b2030a480b8c921546eab44c844200aa82ee [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 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02006 * Copyright The Mbed TLS Contributors
Daniel Kingb8025c52016-05-17 14:43:01 -03007 * 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.
Daniel Kingb8025c52016-05-17 14:43:01 -030020 */
Gilles Peskinedb09ef62020-06-03 01:43:33 +020021#include "common.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030022
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020023#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030024
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020025#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020026#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000027#include "mbedtls/error.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028
Daniel Kingb8025c52016-05-17 14:43:01 -030029#include <string.h>
30
31#if defined(MBEDTLS_SELF_TEST)
32#if defined(MBEDTLS_PLATFORM_C)
33#include "mbedtls/platform.h"
34#else
35#include <stdio.h>
36#define mbedtls_printf printf
37#endif /* MBEDTLS_PLATFORM_C */
38#endif /* MBEDTLS_SELF_TEST */
39
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020040#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030041
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050042/* Parameter validation macros */
43#define CHACHAPOLY_VALIDATE_RET( cond ) \
44 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
45#define CHACHAPOLY_VALIDATE( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE( cond )
47
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020048#define CHACHAPOLY_STATE_INIT ( 0 )
49#define CHACHAPOLY_STATE_AAD ( 1 )
50#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
51#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030052
Daniel Kingb8025c52016-05-17 14:43:01 -030053/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020054 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030055 *
56 * \param ctx The ChaCha20-Poly1305 context.
57 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020058static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030059{
Daniel Kinge6e79682016-05-24 11:16:17 -030060 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030061 unsigned char zeroes[15];
62
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020063 if( partial_block_len == 0U )
64 return( 0 );
65
66 memset( zeroes, 0, sizeof( zeroes ) );
67
68 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
69 zeroes,
70 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030071}
72
73/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020074 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030075 *
76 * \param ctx The ChaCha20-Poly1305 context.
77 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020078static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030079{
Daniel Kinge6e79682016-05-24 11:16:17 -030080 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030081 unsigned char zeroes[15];
82
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020083 if( partial_block_len == 0U )
84 return( 0 );
85
86 memset( zeroes, 0, sizeof( zeroes ) );
87 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
88 zeroes,
89 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030090}
91
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020092void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030093{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050094 CHACHAPOLY_VALIDATE( ctx != NULL );
95
96 mbedtls_chacha20_init( &ctx->chacha20_ctx );
97 mbedtls_poly1305_init( &ctx->poly1305_ctx );
98 ctx->aad_len = 0U;
99 ctx->ciphertext_len = 0U;
100 ctx->state = CHACHAPOLY_STATE_INIT;
101 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300102}
103
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200104void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300105{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500106 if( ctx == NULL )
107 return;
108
109 mbedtls_chacha20_free( &ctx->chacha20_ctx );
110 mbedtls_poly1305_free( &ctx->poly1305_ctx );
111 ctx->aad_len = 0U;
112 ctx->ciphertext_len = 0U;
113 ctx->state = CHACHAPOLY_STATE_INIT;
114 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300115}
116
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200117int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
118 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300119{
Janos Follath24eed8d2019-11-22 13:21:35 +0000120 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500121 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
122 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300123
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200124 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300125
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200126 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300127}
128
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200129int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
130 const unsigned char nonce[12],
131 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300132{
Janos Follath24eed8d2019-11-22 13:21:35 +0000133 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300134 unsigned char poly1305_key[64];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500135 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
136 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300137
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200138 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200139 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
140 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300141 goto cleanup;
142
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200143 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
144 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300145 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
146 * The other 256 bits are discarded.
147 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200148 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200149 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200150 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200151 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300152 goto cleanup;
153
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200154 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300157 {
158 ctx->aad_len = 0U;
159 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200160 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300161 ctx->mode = mode;
162 }
163
164cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200165 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200166 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300167}
168
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200169int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200170 const unsigned char *aad,
171 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300172{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500173 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
174 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
175
176 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200177 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300178
179 ctx->aad_len += aad_len;
180
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200181 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300182}
183
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200184int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
185 size_t len,
186 const unsigned char *input,
187 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300188{
Janos Follath24eed8d2019-11-22 13:21:35 +0000189 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500190 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
191 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
192 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200193
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500194 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
195 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300196 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200197 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300198 }
199
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200200 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300201 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200202 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300203
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200204 ret = chachapoly_pad_aad( ctx );
205 if( ret != 0 )
206 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300207 }
208
209 ctx->ciphertext_len += len;
210
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200211 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300212 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200213 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
214 if( ret != 0 )
215 return( ret );
216
217 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
218 if( ret != 0 )
219 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300220 }
221 else /* DECRYPT */
222 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200223 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
224 if( ret != 0 )
225 return( ret );
226
227 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
228 if( ret != 0 )
229 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300230 }
231
232 return( 0 );
233}
234
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200235int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
236 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300237{
Janos Follath24eed8d2019-11-22 13:21:35 +0000238 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300239 unsigned char len_block[16];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500240 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
241 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300242
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500243 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300244 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200245 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300246 }
247
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200248 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300249 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200250 ret = chachapoly_pad_aad( ctx );
251 if( ret != 0 )
252 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300253 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200254 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300255 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200256 ret = chachapoly_pad_ciphertext( ctx );
257 if( ret != 0 )
258 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300259 }
260
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200261 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300262
263 /* The lengths of the AAD and ciphertext are processed by
264 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
265 */
Joe Subbianib6511b02021-07-16 15:02:55 +0100266 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
267 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300268
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200269 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
270 if( ret != 0 )
271 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300272
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200273 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
274
275 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300276}
277
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200278static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
279 mbedtls_chachapoly_mode_t mode,
280 size_t length,
281 const unsigned char nonce[12],
282 const unsigned char *aad,
283 size_t aad_len,
284 const unsigned char *input,
285 unsigned char *output,
286 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300287{
Janos Follath24eed8d2019-11-22 13:21:35 +0000288 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300289
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200290 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
291 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300292 goto cleanup;
293
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200294 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
295 if( ret != 0 )
296 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300297
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200298 ret = mbedtls_chachapoly_update( ctx, length, input, output );
299 if( ret != 0 )
300 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300301
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200302 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300303
304cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200305 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300306}
307
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200308int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
309 size_t length,
310 const unsigned char nonce[12],
311 const unsigned char *aad,
312 size_t aad_len,
313 const unsigned char *input,
314 unsigned char *output,
315 unsigned char tag[16] )
316{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500317 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
318 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
319 CHACHAPOLY_VALIDATE_RET( tag != NULL );
320 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
321 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
322 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
323
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200324 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
325 length, nonce, aad, aad_len,
326 input, output, tag ) );
327}
328
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200329int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
330 size_t length,
331 const unsigned char nonce[12],
332 const unsigned char *aad,
333 size_t aad_len,
334 const unsigned char tag[16],
335 const unsigned char *input,
336 unsigned char *output )
337{
Janos Follath24eed8d2019-11-22 13:21:35 +0000338 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200339 unsigned char check_tag[16];
340 size_t i;
341 int diff;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500342 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
343 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
344 CHACHAPOLY_VALIDATE_RET( tag != NULL );
345 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
346 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
347 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200348
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200349 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200350 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
351 aad, aad_len, input, output, check_tag ) ) != 0 )
352 {
353 return( ret );
354 }
355
356 /* Check tag in "constant-time" */
357 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
358 diff |= tag[i] ^ check_tag[i];
359
360 if( diff != 0 )
361 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200362 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200363 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
364 }
365
366 return( 0 );
367}
368
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200369#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200370
Daniel Kingb8025c52016-05-17 14:43:01 -0300371#if defined(MBEDTLS_SELF_TEST)
372
373static const unsigned char test_key[1][32] =
374{
375 {
376 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
377 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
378 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
379 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
380 }
381};
382
383static const unsigned char test_nonce[1][12] =
384{
385 {
386 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
387 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
388 }
389};
390
391static const unsigned char test_aad[1][12] =
392{
393 {
394 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
395 0xc4, 0xc5, 0xc6, 0xc7
396 }
397};
398
399static const size_t test_aad_len[1] =
400{
401 12U
402};
403
404static const unsigned char test_input[1][114] =
405{
406 {
407 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
408 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
409 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
410 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
411 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
412 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
413 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
414 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
415 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
416 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
417 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
418 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
419 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
420 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
421 0x74, 0x2e
422 }
423};
424
425static const unsigned char test_output[1][114] =
426{
427 {
428 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
429 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
430 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
431 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
432 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
433 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
434 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
435 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
436 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
437 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
438 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
439 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
440 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
441 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
442 0x61, 0x16
443 }
444};
445
446static const size_t test_input_len[1] =
447{
448 114U
449};
450
451static const unsigned char test_mac[1][16] =
452{
453 {
454 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
455 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
456 }
457};
458
Ouss4e0b26872020-08-11 16:07:09 +0100459/* Make sure no other definition is already present. */
460#undef ASSERT
461
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200462#define ASSERT( cond, args ) \
463 do \
464 { \
465 if( ! ( cond ) ) \
466 { \
467 if( verbose != 0 ) \
468 mbedtls_printf args; \
469 \
470 return( -1 ); \
471 } \
472 } \
473 while( 0 )
474
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200475int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300476{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200477 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200478 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000479 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300480 unsigned char output[200];
481 unsigned char mac[16];
482
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200483 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300484 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200485 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200486 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300487
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200488 mbedtls_chachapoly_init( &ctx );
489
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200490 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
491 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200492
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200493 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
494 test_input_len[i],
495 test_nonce[i],
496 test_aad[i],
497 test_aad_len[i],
498 test_input[i],
499 output,
500 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300501
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200502 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300503
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200504 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
505 ( "failure (wrong output)\n" ) );
506
507 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
508 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300509
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200510 mbedtls_chachapoly_free( &ctx );
511
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200512 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300513 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300514 }
515
516 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300517 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300518
519 return( 0 );
520}
521
522#endif /* MBEDTLS_SELF_TEST */
523
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200524#endif /* MBEDTLS_CHACHAPOLY_C */