blob: f232190dfce290c3836578b2489980bcd719d3ce [file] [log] [blame]
Daniel Kingb8025c52016-05-17 14:43:01 -03001/**
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +02002 * \file chachapoly.c
Daniel Kingb8025c52016-05-17 14:43:01 -03003 *
4 * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
5 *
6 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
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 * **********
47 *
Daniel Kingb8025c52016-05-17 14:43:01 -030048 * This file is part of mbed TLS (https://tls.mbed.org)
49 */
50#if !defined(MBEDTLS_CONFIG_FILE)
51#include "mbedtls/config.h"
52#else
53#include MBEDTLS_CONFIG_FILE
54#endif
55
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020056#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030057
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020058#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020059#include "mbedtls/platform_util.h"
60
Daniel Kingb8025c52016-05-17 14:43:01 -030061#include <string.h>
62
63#if defined(MBEDTLS_SELF_TEST)
64#if defined(MBEDTLS_PLATFORM_C)
65#include "mbedtls/platform.h"
66#else
67#include <stdio.h>
68#define mbedtls_printf printf
69#endif /* MBEDTLS_PLATFORM_C */
70#endif /* MBEDTLS_SELF_TEST */
71
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020072#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030073
Hanno Becker305e4e42018-12-11 15:03:16 +000074/* Parameter validation macros */
75#define CHACHAPOLY_VALIDATE_RET( cond ) \
76 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
77#define CHACHAPOLY_VALIDATE( cond ) \
78 MBEDTLS_INTERNAL_VALIDATE( cond )
79
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020080#define CHACHAPOLY_STATE_INIT ( 0 )
81#define CHACHAPOLY_STATE_AAD ( 1 )
82#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
83#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030084
Daniel Kingb8025c52016-05-17 14:43:01 -030085/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020086 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030087 *
88 * \param ctx The ChaCha20-Poly1305 context.
89 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020090static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030091{
Daniel Kinge6e79682016-05-24 11:16:17 -030092 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030093 unsigned char zeroes[15];
94
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020095 if( partial_block_len == 0U )
96 return( 0 );
97
98 memset( zeroes, 0, sizeof( zeroes ) );
99
100 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
101 zeroes,
102 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300103}
104
105/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200106 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -0300107 *
108 * \param ctx The ChaCha20-Poly1305 context.
109 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +0200110static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300111{
Daniel Kinge6e79682016-05-24 11:16:17 -0300112 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -0300113 unsigned char zeroes[15];
114
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200115 if( partial_block_len == 0U )
116 return( 0 );
117
118 memset( zeroes, 0, sizeof( zeroes ) );
119 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
120 zeroes,
121 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300122}
123
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200124void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300125{
Hanno Becker305e4e42018-12-11 15:03:16 +0000126 CHACHAPOLY_VALIDATE( ctx != NULL );
127
128 mbedtls_chacha20_init( &ctx->chacha20_ctx );
129 mbedtls_poly1305_init( &ctx->poly1305_ctx );
130 ctx->aad_len = 0U;
131 ctx->ciphertext_len = 0U;
132 ctx->state = CHACHAPOLY_STATE_INIT;
133 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300134}
135
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200136void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300137{
Hanno Becker236ea162018-12-12 14:00:34 +0000138 if( ctx == NULL )
Hanno Becker305e4e42018-12-11 15:03:16 +0000139 return;
140
141 mbedtls_chacha20_free( &ctx->chacha20_ctx );
142 mbedtls_poly1305_free( &ctx->poly1305_ctx );
143 ctx->aad_len = 0U;
144 ctx->ciphertext_len = 0U;
145 ctx->state = CHACHAPOLY_STATE_INIT;
146 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300147}
148
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200149int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
150 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300151{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200152 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000153 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
154 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300157
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200158 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300159}
160
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200161int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
162 const unsigned char nonce[12],
163 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300164{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200165 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300166 unsigned char poly1305_key[64];
Hanno Becker305e4e42018-12-11 15:03:16 +0000167 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
168 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300169
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200170 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200171 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
172 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300173 goto cleanup;
174
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200175 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
176 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300177 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
178 * The other 256 bits are discarded.
179 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200180 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200181 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200182 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200183 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300184 goto cleanup;
185
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200186 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300187
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200188 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300189 {
190 ctx->aad_len = 0U;
191 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200192 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300193 ctx->mode = mode;
194 }
195
196cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200197 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200198 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300199}
200
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200201int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200202 const unsigned char *aad,
203 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300204{
Hanno Becker305e4e42018-12-11 15:03:16 +0000205 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
206 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
207
208 if( ctx->state != CHACHAPOLY_STATE_AAD )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200209 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300210
211 ctx->aad_len += aad_len;
212
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200213 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300214}
215
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200216int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
217 size_t len,
218 const unsigned char *input,
219 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300220{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200221 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000222 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
223 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
224 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200225
Hanno Becker305e4e42018-12-11 15:03:16 +0000226 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
227 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300228 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200229 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300230 }
231
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200232 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300233 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200234 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300235
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200236 ret = chachapoly_pad_aad( ctx );
237 if( ret != 0 )
238 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300239 }
240
241 ctx->ciphertext_len += len;
242
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200243 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300244 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200245 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
246 if( ret != 0 )
247 return( ret );
248
249 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
250 if( ret != 0 )
251 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300252 }
253 else /* DECRYPT */
254 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200255 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
256 if( ret != 0 )
257 return( ret );
258
259 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
260 if( ret != 0 )
261 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300262 }
263
264 return( 0 );
265}
266
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200267int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
268 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300269{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200270 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300271 unsigned char len_block[16];
Hanno Becker305e4e42018-12-11 15:03:16 +0000272 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
273 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300274
Hanno Becker305e4e42018-12-11 15:03:16 +0000275 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300276 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200277 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300278 }
279
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200280 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300281 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200282 ret = chachapoly_pad_aad( ctx );
283 if( ret != 0 )
284 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300285 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200286 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300287 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200288 ret = chachapoly_pad_ciphertext( ctx );
289 if( ret != 0 )
290 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300291 }
292
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200293 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300294
295 /* The lengths of the AAD and ciphertext are processed by
296 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
297 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200298 len_block[ 0] = (unsigned char)( ctx->aad_len );
299 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
300 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
301 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
302 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
303 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
304 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
305 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
306 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
307 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
308 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
309 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
310 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
311 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
312 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
313 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300314
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200315 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
316 if( ret != 0 )
317 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300318
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200319 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
320
321 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300322}
323
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200324static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
325 mbedtls_chachapoly_mode_t mode,
326 size_t length,
327 const unsigned char nonce[12],
328 const unsigned char *aad,
329 size_t aad_len,
330 const unsigned char *input,
331 unsigned char *output,
332 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300333{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200334 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300335
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200336 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
337 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300338 goto cleanup;
339
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200340 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
341 if( ret != 0 )
342 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300343
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200344 ret = mbedtls_chachapoly_update( ctx, length, input, output );
345 if( ret != 0 )
346 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300347
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200348 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300349
350cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200351 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300352}
353
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200354int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
355 size_t length,
356 const unsigned char nonce[12],
357 const unsigned char *aad,
358 size_t aad_len,
359 const unsigned char *input,
360 unsigned char *output,
361 unsigned char tag[16] )
362{
Hanno Becker305e4e42018-12-11 15:03:16 +0000363 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
364 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
365 CHACHAPOLY_VALIDATE_RET( tag != NULL );
366 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
367 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
368 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
369
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200370 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
371 length, nonce, aad, aad_len,
372 input, output, tag ) );
373}
374
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200375int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
376 size_t length,
377 const unsigned char nonce[12],
378 const unsigned char *aad,
379 size_t aad_len,
380 const unsigned char tag[16],
381 const unsigned char *input,
382 unsigned char *output )
383{
384 int ret;
385 unsigned char check_tag[16];
386 size_t i;
387 int diff;
Hanno Becker305e4e42018-12-11 15:03:16 +0000388 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
389 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
390 CHACHAPOLY_VALIDATE_RET( tag != NULL );
391 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
392 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
393 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200394
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200395 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200396 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
397 aad, aad_len, input, output, check_tag ) ) != 0 )
398 {
399 return( ret );
400 }
401
402 /* Check tag in "constant-time" */
403 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
404 diff |= tag[i] ^ check_tag[i];
405
406 if( diff != 0 )
407 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200408 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200409 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
410 }
411
412 return( 0 );
413}
414
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200415#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200416
Daniel Kingb8025c52016-05-17 14:43:01 -0300417#if defined(MBEDTLS_SELF_TEST)
418
419static const unsigned char test_key[1][32] =
420{
421 {
422 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
423 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
424 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
425 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
426 }
427};
428
429static const unsigned char test_nonce[1][12] =
430{
431 {
432 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
433 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
434 }
435};
436
437static const unsigned char test_aad[1][12] =
438{
439 {
440 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
441 0xc4, 0xc5, 0xc6, 0xc7
442 }
443};
444
445static const size_t test_aad_len[1] =
446{
447 12U
448};
449
450static const unsigned char test_input[1][114] =
451{
452 {
453 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
454 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
455 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
456 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
457 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
458 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
459 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
460 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
461 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
462 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
463 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
464 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
465 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
466 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
467 0x74, 0x2e
468 }
469};
470
471static const unsigned char test_output[1][114] =
472{
473 {
474 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
475 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
476 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
477 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
478 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
479 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
480 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
481 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
482 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
483 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
484 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
485 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
486 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
487 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
488 0x61, 0x16
489 }
490};
491
492static const size_t test_input_len[1] =
493{
494 114U
495};
496
497static const unsigned char test_mac[1][16] =
498{
499 {
500 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
501 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
502 }
503};
504
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200505#define ASSERT( cond, args ) \
506 do \
507 { \
508 if( ! ( cond ) ) \
509 { \
510 if( verbose != 0 ) \
511 mbedtls_printf args; \
512 \
513 return( -1 ); \
514 } \
515 } \
516 while( 0 )
517
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200518int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300519{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200520 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200521 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200522 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300523 unsigned char output[200];
524 unsigned char mac[16];
525
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200526 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300527 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200528 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200529 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300530
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200531 mbedtls_chachapoly_init( &ctx );
532
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200533 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
534 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200535
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200536 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
537 test_input_len[i],
538 test_nonce[i],
539 test_aad[i],
540 test_aad_len[i],
541 test_input[i],
542 output,
543 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300544
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200545 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300546
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200547 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
548 ( "failure (wrong output)\n" ) );
549
550 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
551 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300552
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200553 mbedtls_chachapoly_free( &ctx );
554
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200555 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300556 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300557 }
558
559 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300560 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300561
562 return( 0 );
563}
564
565#endif /* MBEDTLS_SELF_TEST */
566
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200567#endif /* MBEDTLS_CHACHAPOLY_C */