blob: c8b5bba4b2352133c745e7a6c004f6e5992ceccf [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útia2947ac2020-08-19 16:37:36 +02006 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02007 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
8 *
9 * This file is provided under the Apache License 2.0, or the
10 * GNU General Public License v2.0 or later.
11 *
12 * **********
13 * Apache License 2.0:
Daniel Kingb8025c52016-05-17 14:43:01 -030014 *
15 * Licensed under the Apache License, Version 2.0 (the "License"); you may
16 * not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
23 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020027 * **********
28 *
29 * **********
30 * GNU General Public License v2.0 or later:
31 *
32 * This program is free software; you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation; either version 2 of the License, or
35 * (at your option) any later version.
36 *
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License along
43 * with this program; if not, write to the Free Software Foundation, Inc.,
44 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
45 *
46 * **********
Daniel Kingb8025c52016-05-17 14:43:01 -030047 */
48#if !defined(MBEDTLS_CONFIG_FILE)
49#include "mbedtls/config.h"
50#else
51#include MBEDTLS_CONFIG_FILE
52#endif
53
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020054#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030055
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020056#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020057#include "mbedtls/platform_util.h"
58
Daniel Kingb8025c52016-05-17 14:43:01 -030059#include <string.h>
60
61#if defined(MBEDTLS_SELF_TEST)
62#if defined(MBEDTLS_PLATFORM_C)
63#include "mbedtls/platform.h"
64#else
65#include <stdio.h>
66#define mbedtls_printf printf
67#endif /* MBEDTLS_PLATFORM_C */
68#endif /* MBEDTLS_SELF_TEST */
69
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020070#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030071
Hanno Becker305e4e42018-12-11 15:03:16 +000072/* Parameter validation macros */
73#define CHACHAPOLY_VALIDATE_RET( cond ) \
74 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
75#define CHACHAPOLY_VALIDATE( cond ) \
76 MBEDTLS_INTERNAL_VALIDATE( cond )
77
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020078#define CHACHAPOLY_STATE_INIT ( 0 )
79#define CHACHAPOLY_STATE_AAD ( 1 )
80#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
81#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030082
Daniel Kingb8025c52016-05-17 14:43:01 -030083/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020084 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030085 *
86 * \param ctx The ChaCha20-Poly1305 context.
87 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020088static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030089{
Daniel Kinge6e79682016-05-24 11:16:17 -030090 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030091 unsigned char zeroes[15];
92
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020093 if( partial_block_len == 0U )
94 return( 0 );
95
96 memset( zeroes, 0, sizeof( zeroes ) );
97
98 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
99 zeroes,
100 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300101}
102
103/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200104 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -0300105 *
106 * \param ctx The ChaCha20-Poly1305 context.
107 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +0200108static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300109{
Daniel Kinge6e79682016-05-24 11:16:17 -0300110 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -0300111 unsigned char zeroes[15];
112
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200113 if( partial_block_len == 0U )
114 return( 0 );
115
116 memset( zeroes, 0, sizeof( zeroes ) );
117 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
118 zeroes,
119 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300120}
121
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200122void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300123{
Hanno Becker305e4e42018-12-11 15:03:16 +0000124 CHACHAPOLY_VALIDATE( ctx != NULL );
125
126 mbedtls_chacha20_init( &ctx->chacha20_ctx );
127 mbedtls_poly1305_init( &ctx->poly1305_ctx );
128 ctx->aad_len = 0U;
129 ctx->ciphertext_len = 0U;
130 ctx->state = CHACHAPOLY_STATE_INIT;
131 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300132}
133
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200134void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300135{
Hanno Becker236ea162018-12-12 14:00:34 +0000136 if( ctx == NULL )
Hanno Becker305e4e42018-12-11 15:03:16 +0000137 return;
138
139 mbedtls_chacha20_free( &ctx->chacha20_ctx );
140 mbedtls_poly1305_free( &ctx->poly1305_ctx );
141 ctx->aad_len = 0U;
142 ctx->ciphertext_len = 0U;
143 ctx->state = CHACHAPOLY_STATE_INIT;
144 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300145}
146
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200147int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
148 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300149{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200150 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000151 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
152 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300153
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200154 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300157}
158
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200159int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
160 const unsigned char nonce[12],
161 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300162{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200163 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300164 unsigned char poly1305_key[64];
Hanno Becker305e4e42018-12-11 15:03:16 +0000165 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
166 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300167
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200168 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200169 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
170 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300171 goto cleanup;
172
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200173 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
174 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300175 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
176 * The other 256 bits are discarded.
177 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200178 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200179 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200180 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200181 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300182 goto cleanup;
183
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200184 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300185
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200186 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300187 {
188 ctx->aad_len = 0U;
189 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200190 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300191 ctx->mode = mode;
192 }
193
194cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200195 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200196 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300197}
198
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200199int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200200 const unsigned char *aad,
201 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300202{
Hanno Becker305e4e42018-12-11 15:03:16 +0000203 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
204 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
205
206 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200207 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300208
209 ctx->aad_len += aad_len;
210
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200211 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300212}
213
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200214int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
215 size_t len,
216 const unsigned char *input,
217 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300218{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200219 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000220 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
221 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
222 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200223
Hanno Becker305e4e42018-12-11 15:03:16 +0000224 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
225 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300226 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200227 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300228 }
229
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200230 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300231 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200232 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300233
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200234 ret = chachapoly_pad_aad( ctx );
235 if( ret != 0 )
236 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300237 }
238
239 ctx->ciphertext_len += len;
240
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200241 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300242 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200243 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
244 if( ret != 0 )
245 return( ret );
246
247 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
248 if( ret != 0 )
249 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300250 }
251 else /* DECRYPT */
252 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200253 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
254 if( ret != 0 )
255 return( ret );
256
257 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
258 if( ret != 0 )
259 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300260 }
261
262 return( 0 );
263}
264
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200265int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
266 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300267{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200268 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300269 unsigned char len_block[16];
Hanno Becker305e4e42018-12-11 15:03:16 +0000270 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
271 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300272
Hanno Becker305e4e42018-12-11 15:03:16 +0000273 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300274 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200275 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300276 }
277
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200278 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300279 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200280 ret = chachapoly_pad_aad( ctx );
281 if( ret != 0 )
282 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300283 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200284 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300285 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200286 ret = chachapoly_pad_ciphertext( ctx );
287 if( ret != 0 )
288 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300289 }
290
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200291 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300292
293 /* The lengths of the AAD and ciphertext are processed by
294 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
295 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200296 len_block[ 0] = (unsigned char)( ctx->aad_len );
297 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
298 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
299 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
300 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
301 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
302 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
303 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
304 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
305 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
306 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
307 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
308 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
309 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
310 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
311 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300312
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200313 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
314 if( ret != 0 )
315 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300316
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200317 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
318
319 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300320}
321
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200322static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
323 mbedtls_chachapoly_mode_t mode,
324 size_t length,
325 const unsigned char nonce[12],
326 const unsigned char *aad,
327 size_t aad_len,
328 const unsigned char *input,
329 unsigned char *output,
330 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300331{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200332 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300333
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200334 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
335 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300336 goto cleanup;
337
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200338 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
339 if( ret != 0 )
340 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300341
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200342 ret = mbedtls_chachapoly_update( ctx, length, input, output );
343 if( ret != 0 )
344 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300345
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200346 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300347
348cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200349 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300350}
351
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200352int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
353 size_t length,
354 const unsigned char nonce[12],
355 const unsigned char *aad,
356 size_t aad_len,
357 const unsigned char *input,
358 unsigned char *output,
359 unsigned char tag[16] )
360{
Hanno Becker305e4e42018-12-11 15:03:16 +0000361 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
362 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
363 CHACHAPOLY_VALIDATE_RET( tag != NULL );
364 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
365 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
366 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
367
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200368 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
369 length, nonce, aad, aad_len,
370 input, output, tag ) );
371}
372
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200373int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
374 size_t length,
375 const unsigned char nonce[12],
376 const unsigned char *aad,
377 size_t aad_len,
378 const unsigned char tag[16],
379 const unsigned char *input,
380 unsigned char *output )
381{
382 int ret;
383 unsigned char check_tag[16];
384 size_t i;
385 int diff;
Hanno Becker305e4e42018-12-11 15:03:16 +0000386 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
387 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
388 CHACHAPOLY_VALIDATE_RET( tag != NULL );
389 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
390 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
391 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200392
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200393 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200394 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
395 aad, aad_len, input, output, check_tag ) ) != 0 )
396 {
397 return( ret );
398 }
399
400 /* Check tag in "constant-time" */
401 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
402 diff |= tag[i] ^ check_tag[i];
403
404 if( diff != 0 )
405 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200406 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200407 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
408 }
409
410 return( 0 );
411}
412
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200413#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200414
Daniel Kingb8025c52016-05-17 14:43:01 -0300415#if defined(MBEDTLS_SELF_TEST)
416
417static const unsigned char test_key[1][32] =
418{
419 {
420 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
421 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
422 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
423 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
424 }
425};
426
427static const unsigned char test_nonce[1][12] =
428{
429 {
430 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
431 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
432 }
433};
434
435static const unsigned char test_aad[1][12] =
436{
437 {
438 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
439 0xc4, 0xc5, 0xc6, 0xc7
440 }
441};
442
443static const size_t test_aad_len[1] =
444{
445 12U
446};
447
448static const unsigned char test_input[1][114] =
449{
450 {
451 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
452 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
453 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
454 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
455 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
456 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
457 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
458 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
459 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
460 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
461 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
462 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
463 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
464 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
465 0x74, 0x2e
466 }
467};
468
469static const unsigned char test_output[1][114] =
470{
471 {
472 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
473 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
474 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
475 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
476 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
477 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
478 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
479 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
480 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
481 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
482 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
483 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
484 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
485 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
486 0x61, 0x16
487 }
488};
489
490static const size_t test_input_len[1] =
491{
492 114U
493};
494
495static const unsigned char test_mac[1][16] =
496{
497 {
498 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
499 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
500 }
501};
502
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503#define ASSERT( cond, args ) \
504 do \
505 { \
506 if( ! ( cond ) ) \
507 { \
508 if( verbose != 0 ) \
509 mbedtls_printf args; \
510 \
511 return( -1 ); \
512 } \
513 } \
514 while( 0 )
515
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200516int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300517{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200518 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200519 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200520 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300521 unsigned char output[200];
522 unsigned char mac[16];
523
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200524 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300525 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200526 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200527 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300528
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200529 mbedtls_chachapoly_init( &ctx );
530
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200531 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
532 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200533
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200534 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
535 test_input_len[i],
536 test_nonce[i],
537 test_aad[i],
538 test_aad_len[i],
539 test_input[i],
540 output,
541 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300542
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200543 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300544
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200545 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
546 ( "failure (wrong output)\n" ) );
547
548 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
549 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300550
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200551 mbedtls_chachapoly_free( &ctx );
552
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200553 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300554 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300555 }
556
557 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300558 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300559
560 return( 0 );
561}
562
563#endif /* MBEDTLS_SELF_TEST */
564
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200565#endif /* MBEDTLS_CHACHAPOLY_C */