blob: ee5cc345e32e67772f4102ecb3a2903d65d14fb9 [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
7 * 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.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23#if !defined(MBEDTLS_CONFIG_FILE)
24#include "mbedtls/config.h"
25#else
26#include MBEDTLS_CONFIG_FILE
27#endif
28
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020029#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030030
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020031#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020032#include "mbedtls/platform_util.h"
33
Daniel Kingb8025c52016-05-17 14:43:01 -030034#include <string.h>
35
36#if defined(MBEDTLS_SELF_TEST)
37#if defined(MBEDTLS_PLATFORM_C)
38#include "mbedtls/platform.h"
39#else
40#include <stdio.h>
41#define mbedtls_printf printf
42#endif /* MBEDTLS_PLATFORM_C */
43#endif /* MBEDTLS_SELF_TEST */
44
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020045#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030046
Hanno Becker305e4e42018-12-11 15:03:16 +000047/* Parameter validation macros */
48#define CHACHAPOLY_VALIDATE_RET( cond ) \
49 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
50#define CHACHAPOLY_VALIDATE( cond ) \
51 MBEDTLS_INTERNAL_VALIDATE( cond )
52
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020053#define CHACHAPOLY_STATE_INIT ( 0 )
54#define CHACHAPOLY_STATE_AAD ( 1 )
55#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
56#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030057
Daniel Kingb8025c52016-05-17 14:43:01 -030058/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020059 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030060 *
61 * \param ctx The ChaCha20-Poly1305 context.
62 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020063static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030064{
Daniel Kinge6e79682016-05-24 11:16:17 -030065 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030066 unsigned char zeroes[15];
67
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020068 if( partial_block_len == 0U )
69 return( 0 );
70
71 memset( zeroes, 0, sizeof( zeroes ) );
72
73 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
74 zeroes,
75 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030076}
77
78/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020079 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030080 *
81 * \param ctx The ChaCha20-Poly1305 context.
82 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020083static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030084{
Daniel Kinge6e79682016-05-24 11:16:17 -030085 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030086 unsigned char zeroes[15];
87
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020088 if( partial_block_len == 0U )
89 return( 0 );
90
91 memset( zeroes, 0, sizeof( zeroes ) );
92 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
93 zeroes,
94 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030095}
96
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020097void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030098{
Hanno Becker305e4e42018-12-11 15:03:16 +000099 CHACHAPOLY_VALIDATE( ctx != NULL );
100
101 mbedtls_chacha20_init( &ctx->chacha20_ctx );
102 mbedtls_poly1305_init( &ctx->poly1305_ctx );
103 ctx->aad_len = 0U;
104 ctx->ciphertext_len = 0U;
105 ctx->state = CHACHAPOLY_STATE_INIT;
106 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300107}
108
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200109void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300110{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200111 if( ctx != NULL )
Hanno Becker305e4e42018-12-11 15:03:16 +0000112 return;
113
114 mbedtls_chacha20_free( &ctx->chacha20_ctx );
115 mbedtls_poly1305_free( &ctx->poly1305_ctx );
116 ctx->aad_len = 0U;
117 ctx->ciphertext_len = 0U;
118 ctx->state = CHACHAPOLY_STATE_INIT;
119 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300120}
121
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200122int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
123 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300124{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200125 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000126 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
127 CHACHAPOLY_VALIDATE_RET( key != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300128
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200129 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300130
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200131 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300132}
133
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200134int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
135 const unsigned char nonce[12],
136 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300137{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200138 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300139 unsigned char poly1305_key[64];
Hanno Becker305e4e42018-12-11 15:03:16 +0000140 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
141 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300142
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200143 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200144 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
145 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300146 goto cleanup;
147
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200148 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
149 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300150 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
151 * The other 256 bits are discarded.
152 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200153 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200154 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200155 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300157 goto cleanup;
158
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200159 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300160
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200161 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300162 {
163 ctx->aad_len = 0U;
164 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200165 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300166 ctx->mode = mode;
167 }
168
169cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200170 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200171 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300172}
173
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200174int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200175 const unsigned char *aad,
176 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300177{
Hanno Becker305e4e42018-12-11 15:03:16 +0000178 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
179 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
180
181 if( ctx->state != CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300182 {
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200183 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300184 }
185
186 ctx->aad_len += aad_len;
187
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200188 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300189}
190
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200191int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
192 size_t len,
193 const unsigned char *input,
194 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300195{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200196 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000197 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
198 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
199 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200200
Hanno Becker305e4e42018-12-11 15:03:16 +0000201 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
202 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300203 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200204 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300205 }
206
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200207 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300208 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200209 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300210
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200211 ret = chachapoly_pad_aad( ctx );
212 if( ret != 0 )
213 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300214 }
215
216 ctx->ciphertext_len += len;
217
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200218 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300219 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200220 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
221 if( ret != 0 )
222 return( ret );
223
224 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
225 if( ret != 0 )
226 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300227 }
228 else /* DECRYPT */
229 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200230 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
231 if( ret != 0 )
232 return( ret );
233
234 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
235 if( ret != 0 )
236 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300237 }
238
239 return( 0 );
240}
241
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200242int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
243 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300244{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200245 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300246 unsigned char len_block[16];
Hanno Becker305e4e42018-12-11 15:03:16 +0000247 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
248 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300249
Hanno Becker305e4e42018-12-11 15:03:16 +0000250 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300251 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200252 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300253 }
254
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200255 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300256 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200257 ret = chachapoly_pad_aad( ctx );
258 if( ret != 0 )
259 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300260 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200261 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300262 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200263 ret = chachapoly_pad_ciphertext( ctx );
264 if( ret != 0 )
265 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300266 }
267
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200268 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300269
270 /* The lengths of the AAD and ciphertext are processed by
271 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
272 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200273 len_block[ 0] = (unsigned char)( ctx->aad_len );
274 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
275 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
276 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
277 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
278 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
279 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
280 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
281 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
282 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
283 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
284 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
285 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
286 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
287 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
288 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300289
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200290 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
291 if( ret != 0 )
292 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300293
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200294 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
295
296 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300297}
298
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200299static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
300 mbedtls_chachapoly_mode_t mode,
301 size_t length,
302 const unsigned char nonce[12],
303 const unsigned char *aad,
304 size_t aad_len,
305 const unsigned char *input,
306 unsigned char *output,
307 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300308{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200309 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300310
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200311 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
312 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300313 goto cleanup;
314
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200315 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
316 if( ret != 0 )
317 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300318
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200319 ret = mbedtls_chachapoly_update( ctx, length, input, output );
320 if( ret != 0 )
321 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300322
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200323 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300324
325cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200326 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300327}
328
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200329int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
330 size_t length,
331 const unsigned char nonce[12],
332 const unsigned char *aad,
333 size_t aad_len,
334 const unsigned char *input,
335 unsigned char *output,
336 unsigned char tag[16] )
337{
Hanno Becker305e4e42018-12-11 15:03:16 +0000338 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
339 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
340 CHACHAPOLY_VALIDATE_RET( tag != NULL );
341 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
342 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
343 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
344
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200345 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
346 length, nonce, aad, aad_len,
347 input, output, tag ) );
348}
349
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200350int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
351 size_t length,
352 const unsigned char nonce[12],
353 const unsigned char *aad,
354 size_t aad_len,
355 const unsigned char tag[16],
356 const unsigned char *input,
357 unsigned char *output )
358{
359 int ret;
360 unsigned char check_tag[16];
361 size_t i;
362 int diff;
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 );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200369
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200370 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200371 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
372 aad, aad_len, input, output, check_tag ) ) != 0 )
373 {
374 return( ret );
375 }
376
377 /* Check tag in "constant-time" */
378 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
379 diff |= tag[i] ^ check_tag[i];
380
381 if( diff != 0 )
382 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200383 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200384 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
385 }
386
387 return( 0 );
388}
389
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200390#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200391
Daniel Kingb8025c52016-05-17 14:43:01 -0300392#if defined(MBEDTLS_SELF_TEST)
393
394static const unsigned char test_key[1][32] =
395{
396 {
397 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
398 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
399 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
400 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
401 }
402};
403
404static const unsigned char test_nonce[1][12] =
405{
406 {
407 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
408 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
409 }
410};
411
412static const unsigned char test_aad[1][12] =
413{
414 {
415 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
416 0xc4, 0xc5, 0xc6, 0xc7
417 }
418};
419
420static const size_t test_aad_len[1] =
421{
422 12U
423};
424
425static const unsigned char test_input[1][114] =
426{
427 {
428 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
429 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
430 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
431 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
432 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
433 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
434 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
435 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
436 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
437 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
438 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
439 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
440 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
441 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
442 0x74, 0x2e
443 }
444};
445
446static const unsigned char test_output[1][114] =
447{
448 {
449 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
450 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
451 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
452 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
453 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
454 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
455 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
456 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
457 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
458 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
459 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
460 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
461 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
462 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
463 0x61, 0x16
464 }
465};
466
467static const size_t test_input_len[1] =
468{
469 114U
470};
471
472static const unsigned char test_mac[1][16] =
473{
474 {
475 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
476 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
477 }
478};
479
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200480#define ASSERT( cond, args ) \
481 do \
482 { \
483 if( ! ( cond ) ) \
484 { \
485 if( verbose != 0 ) \
486 mbedtls_printf args; \
487 \
488 return( -1 ); \
489 } \
490 } \
491 while( 0 )
492
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200493int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300494{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200495 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200496 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200497 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300498 unsigned char output[200];
499 unsigned char mac[16];
500
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200501 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300502 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200504 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300505
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200506 mbedtls_chachapoly_init( &ctx );
507
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200508 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
509 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200510
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200511 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
512 test_input_len[i],
513 test_nonce[i],
514 test_aad[i],
515 test_aad_len[i],
516 test_input[i],
517 output,
518 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300519
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200520 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300521
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200522 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
523 ( "failure (wrong output)\n" ) );
524
525 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
526 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300527
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200528 mbedtls_chachapoly_free( &ctx );
529
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200530 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300531 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300532 }
533
534 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300535 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300536
537 return( 0 );
538}
539
540#endif /* MBEDTLS_SELF_TEST */
541
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200542#endif /* MBEDTLS_CHACHAPOLY_C */