blob: 696d97bf01bb04139101146a4079090bddc46984 [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 Subbianiad1115a2021-07-16 14:27:50 +0100266 len_block[ 0] = MBEDTLS_BYTE_0( ctx->aad_len );
267 len_block[ 1] = MBEDTLS_BYTE_1( ctx->aad_len );
268 len_block[ 2] = MBEDTLS_BYTE_2( ctx->aad_len );
269 len_block[ 3] = MBEDTLS_BYTE_3( ctx->aad_len );
270 len_block[ 4] = MBEDTLS_BYTE_4( ctx->aad_len );
271 len_block[ 5] = MBEDTLS_BYTE_5( ctx->aad_len );
272 len_block[ 6] = MBEDTLS_BYTE_6( ctx->aad_len );
273 len_block[ 7] = MBEDTLS_BYTE_7( ctx->aad_len );
274 len_block[ 8] = MBEDTLS_BYTE_0( ctx->ciphertext_len );
275 len_block[ 9] = MBEDTLS_BYTE_1( ctx->ciphertext_len );
276 len_block[10] = MBEDTLS_BYTE_2( ctx->ciphertext_len );
277 len_block[11] = MBEDTLS_BYTE_3( ctx->ciphertext_len );
278 len_block[12] = MBEDTLS_BYTE_4( ctx->ciphertext_len );
279 len_block[13] = MBEDTLS_BYTE_5( ctx->ciphertext_len );
280 len_block[14] = MBEDTLS_BYTE_6( ctx->ciphertext_len );
281 len_block[15] = MBEDTLS_BYTE_7( ctx->ciphertext_len );
Daniel Kingb8025c52016-05-17 14:43:01 -0300282
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200283 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
284 if( ret != 0 )
285 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300286
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200287 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
288
289 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300290}
291
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200292static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
293 mbedtls_chachapoly_mode_t mode,
294 size_t length,
295 const unsigned char nonce[12],
296 const unsigned char *aad,
297 size_t aad_len,
298 const unsigned char *input,
299 unsigned char *output,
300 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300301{
Janos Follath24eed8d2019-11-22 13:21:35 +0000302 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300303
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200304 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
305 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300306 goto cleanup;
307
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200308 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
309 if( ret != 0 )
310 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300311
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200312 ret = mbedtls_chachapoly_update( ctx, length, input, output );
313 if( ret != 0 )
314 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300315
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200316 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300317
318cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200319 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300320}
321
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200322int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
323 size_t length,
324 const unsigned char nonce[12],
325 const unsigned char *aad,
326 size_t aad_len,
327 const unsigned char *input,
328 unsigned char *output,
329 unsigned char tag[16] )
330{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500331 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
332 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
333 CHACHAPOLY_VALIDATE_RET( tag != NULL );
334 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
335 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
336 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
337
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200338 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
339 length, nonce, aad, aad_len,
340 input, output, tag ) );
341}
342
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200343int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
344 size_t length,
345 const unsigned char nonce[12],
346 const unsigned char *aad,
347 size_t aad_len,
348 const unsigned char tag[16],
349 const unsigned char *input,
350 unsigned char *output )
351{
Janos Follath24eed8d2019-11-22 13:21:35 +0000352 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200353 unsigned char check_tag[16];
354 size_t i;
355 int diff;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500356 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
357 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
358 CHACHAPOLY_VALIDATE_RET( tag != NULL );
359 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
360 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
361 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200362
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200363 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200364 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
365 aad, aad_len, input, output, check_tag ) ) != 0 )
366 {
367 return( ret );
368 }
369
370 /* Check tag in "constant-time" */
371 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
372 diff |= tag[i] ^ check_tag[i];
373
374 if( diff != 0 )
375 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200376 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200377 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
378 }
379
380 return( 0 );
381}
382
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200383#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200384
Daniel Kingb8025c52016-05-17 14:43:01 -0300385#if defined(MBEDTLS_SELF_TEST)
386
387static const unsigned char test_key[1][32] =
388{
389 {
390 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
391 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
392 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
393 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
394 }
395};
396
397static const unsigned char test_nonce[1][12] =
398{
399 {
400 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
401 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
402 }
403};
404
405static const unsigned char test_aad[1][12] =
406{
407 {
408 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
409 0xc4, 0xc5, 0xc6, 0xc7
410 }
411};
412
413static const size_t test_aad_len[1] =
414{
415 12U
416};
417
418static const unsigned char test_input[1][114] =
419{
420 {
421 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
422 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
423 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
424 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
425 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
426 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
427 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
428 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
429 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
430 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
431 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
432 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
433 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
434 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
435 0x74, 0x2e
436 }
437};
438
439static const unsigned char test_output[1][114] =
440{
441 {
442 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
443 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
444 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
445 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
446 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
447 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
448 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
449 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
450 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
451 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
452 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
453 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
454 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
455 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
456 0x61, 0x16
457 }
458};
459
460static const size_t test_input_len[1] =
461{
462 114U
463};
464
465static const unsigned char test_mac[1][16] =
466{
467 {
468 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
469 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
470 }
471};
472
Ouss4e0b26872020-08-11 16:07:09 +0100473/* Make sure no other definition is already present. */
474#undef ASSERT
475
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200476#define ASSERT( cond, args ) \
477 do \
478 { \
479 if( ! ( cond ) ) \
480 { \
481 if( verbose != 0 ) \
482 mbedtls_printf args; \
483 \
484 return( -1 ); \
485 } \
486 } \
487 while( 0 )
488
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200489int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300490{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200491 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200492 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000493 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300494 unsigned char output[200];
495 unsigned char mac[16];
496
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200497 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300498 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200499 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200500 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300501
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200502 mbedtls_chachapoly_init( &ctx );
503
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200504 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
505 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200506
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200507 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
508 test_input_len[i],
509 test_nonce[i],
510 test_aad[i],
511 test_aad_len[i],
512 test_input[i],
513 output,
514 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300515
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200516 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300517
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200518 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
519 ( "failure (wrong output)\n" ) );
520
521 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
522 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300523
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200524 mbedtls_chachapoly_free( &ctx );
525
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200526 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300527 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300528 }
529
530 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300531 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300532
533 return( 0 );
534}
535
536#endif /* MBEDTLS_SELF_TEST */
537
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200538#endif /* MBEDTLS_CHACHAPOLY_C */