blob: 4adf846857e88f9f6530a0f322d6170f00c2e51c [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
Daniel Kingb8025c52016-05-17 14:43:01 -030031#include "mbedtls/platform.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030032
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020033#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030034
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050035/* Parameter validation macros */
36#define CHACHAPOLY_VALIDATE_RET( cond ) \
37 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
38#define CHACHAPOLY_VALIDATE( cond ) \
39 MBEDTLS_INTERNAL_VALIDATE( cond )
40
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020041#define CHACHAPOLY_STATE_INIT ( 0 )
42#define CHACHAPOLY_STATE_AAD ( 1 )
43#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
44#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030045
Daniel Kingb8025c52016-05-17 14:43:01 -030046/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020047 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030048 *
49 * \param ctx The ChaCha20-Poly1305 context.
50 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020051static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030052{
Daniel Kinge6e79682016-05-24 11:16:17 -030053 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030054 unsigned char zeroes[15];
55
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020056 if( partial_block_len == 0U )
57 return( 0 );
58
59 memset( zeroes, 0, sizeof( zeroes ) );
60
61 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
62 zeroes,
63 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030064}
65
66/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020067 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030068 *
69 * \param ctx The ChaCha20-Poly1305 context.
70 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020071static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030072{
Daniel Kinge6e79682016-05-24 11:16:17 -030073 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030074 unsigned char zeroes[15];
75
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020076 if( partial_block_len == 0U )
77 return( 0 );
78
79 memset( zeroes, 0, sizeof( zeroes ) );
80 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
81 zeroes,
82 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030083}
84
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020085void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030086{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050087 CHACHAPOLY_VALIDATE( ctx != NULL );
88
89 mbedtls_chacha20_init( &ctx->chacha20_ctx );
90 mbedtls_poly1305_init( &ctx->poly1305_ctx );
91 ctx->aad_len = 0U;
92 ctx->ciphertext_len = 0U;
93 ctx->state = CHACHAPOLY_STATE_INIT;
94 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030095}
96
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020097void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030098{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050099 if( ctx == NULL )
100 return;
101
102 mbedtls_chacha20_free( &ctx->chacha20_ctx );
103 mbedtls_poly1305_free( &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 +0200110int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
111 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300112{
Janos Follath24eed8d2019-11-22 13:21:35 +0000113 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500114 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
115 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300116
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200117 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300118
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200119 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300120}
121
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200122int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
123 const unsigned char nonce[12],
124 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300125{
Janos Follath24eed8d2019-11-22 13:21:35 +0000126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300127 unsigned char poly1305_key[64];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500128 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
129 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300130
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200131 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200132 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
133 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300134 goto cleanup;
135
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200136 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
137 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300138 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
139 * The other 256 bits are discarded.
140 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200141 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200142 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200143 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200144 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300145 goto cleanup;
146
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200147 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300148
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200149 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300150 {
151 ctx->aad_len = 0U;
152 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200153 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300154 ctx->mode = mode;
155 }
156
157cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200158 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200159 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300160}
161
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200162int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200163 const unsigned char *aad,
164 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300165{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500166 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
167 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
168
169 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200170 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300171
172 ctx->aad_len += aad_len;
173
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200174 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300175}
176
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200177int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
178 size_t len,
179 const unsigned char *input,
180 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300181{
Janos Follath24eed8d2019-11-22 13:21:35 +0000182 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500183 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
184 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
185 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200186
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500187 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
188 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300189 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200190 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300191 }
192
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200193 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300194 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200195 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300196
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200197 ret = chachapoly_pad_aad( ctx );
198 if( ret != 0 )
199 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300200 }
201
202 ctx->ciphertext_len += len;
203
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200204 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300205 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200206 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
207 if( ret != 0 )
208 return( ret );
209
210 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
211 if( ret != 0 )
212 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300213 }
214 else /* DECRYPT */
215 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200216 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
217 if( ret != 0 )
218 return( ret );
219
220 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
221 if( ret != 0 )
222 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300223 }
224
225 return( 0 );
226}
227
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200228int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
229 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300230{
Janos Follath24eed8d2019-11-22 13:21:35 +0000231 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300232 unsigned char len_block[16];
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500233 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
234 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300235
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500236 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300237 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200238 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300239 }
240
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200241 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300242 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200243 ret = chachapoly_pad_aad( ctx );
244 if( ret != 0 )
245 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300246 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200247 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300248 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200249 ret = chachapoly_pad_ciphertext( ctx );
250 if( ret != 0 )
251 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300252 }
253
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200254 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300255
256 /* The lengths of the AAD and ciphertext are processed by
257 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
258 */
Joe Subbiani6627fb22021-07-16 15:02:55 +0100259 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
260 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300261
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200262 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
263 if( ret != 0 )
264 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300265
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200266 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
267
268 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300269}
270
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200271static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
272 mbedtls_chachapoly_mode_t mode,
273 size_t length,
274 const unsigned char nonce[12],
275 const unsigned char *aad,
276 size_t aad_len,
277 const unsigned char *input,
278 unsigned char *output,
279 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300280{
Janos Follath24eed8d2019-11-22 13:21:35 +0000281 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300282
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200283 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
284 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300285 goto cleanup;
286
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200287 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
288 if( ret != 0 )
289 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300290
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200291 ret = mbedtls_chachapoly_update( ctx, length, input, output );
292 if( ret != 0 )
293 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300294
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200295 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300296
297cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200298 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300299}
300
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200301int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
302 size_t length,
303 const unsigned char nonce[12],
304 const unsigned char *aad,
305 size_t aad_len,
306 const unsigned char *input,
307 unsigned char *output,
308 unsigned char tag[16] )
309{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500310 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
311 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
312 CHACHAPOLY_VALIDATE_RET( tag != NULL );
313 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
314 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
315 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
316
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200317 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
318 length, nonce, aad, aad_len,
319 input, output, tag ) );
320}
321
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200322int mbedtls_chachapoly_auth_decrypt( 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 tag[16],
328 const unsigned char *input,
329 unsigned char *output )
330{
Janos Follath24eed8d2019-11-22 13:21:35 +0000331 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200332 unsigned char check_tag[16];
333 size_t i;
334 int diff;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500335 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
336 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
337 CHACHAPOLY_VALIDATE_RET( tag != NULL );
338 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
339 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
340 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200341
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200342 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200343 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
344 aad, aad_len, input, output, check_tag ) ) != 0 )
345 {
346 return( ret );
347 }
348
349 /* Check tag in "constant-time" */
350 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
351 diff |= tag[i] ^ check_tag[i];
352
353 if( diff != 0 )
354 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200355 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200356 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
357 }
358
359 return( 0 );
360}
361
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200362#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200363
Daniel Kingb8025c52016-05-17 14:43:01 -0300364#if defined(MBEDTLS_SELF_TEST)
365
366static const unsigned char test_key[1][32] =
367{
368 {
369 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
370 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
371 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
372 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
373 }
374};
375
376static const unsigned char test_nonce[1][12] =
377{
378 {
379 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
380 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
381 }
382};
383
384static const unsigned char test_aad[1][12] =
385{
386 {
387 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
388 0xc4, 0xc5, 0xc6, 0xc7
389 }
390};
391
392static const size_t test_aad_len[1] =
393{
394 12U
395};
396
397static const unsigned char test_input[1][114] =
398{
399 {
400 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
401 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
402 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
403 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
404 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
405 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
406 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
407 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
408 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
409 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
410 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
411 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
412 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
413 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
414 0x74, 0x2e
415 }
416};
417
418static const unsigned char test_output[1][114] =
419{
420 {
421 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
422 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
423 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
424 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
425 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
426 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
427 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
428 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
429 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
430 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
431 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
432 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
433 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
434 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
435 0x61, 0x16
436 }
437};
438
439static const size_t test_input_len[1] =
440{
441 114U
442};
443
444static const unsigned char test_mac[1][16] =
445{
446 {
447 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
448 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
449 }
450};
451
Ouss4e0b26872020-08-11 16:07:09 +0100452/* Make sure no other definition is already present. */
453#undef ASSERT
454
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200455#define ASSERT( cond, args ) \
456 do \
457 { \
458 if( ! ( cond ) ) \
459 { \
460 if( verbose != 0 ) \
461 mbedtls_printf args; \
462 \
463 return( -1 ); \
464 } \
465 } \
466 while( 0 )
467
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200468int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300469{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200470 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200471 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000472 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300473 unsigned char output[200];
474 unsigned char mac[16];
475
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200476 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300477 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200478 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200479 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300480
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200481 mbedtls_chachapoly_init( &ctx );
482
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200483 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
484 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200485
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200486 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
487 test_input_len[i],
488 test_nonce[i],
489 test_aad[i],
490 test_aad_len[i],
491 test_input[i],
492 output,
493 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300494
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200495 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300496
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200497 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
498 ( "failure (wrong output)\n" ) );
499
500 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
501 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300502
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200503 mbedtls_chachapoly_free( &ctx );
504
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200505 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300506 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300507 }
508
509 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300510 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300511
512 return( 0 );
513}
514
515#endif /* MBEDTLS_SELF_TEST */
516
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200517#endif /* MBEDTLS_CHACHAPOLY_C */