blob: dc643dd618900958d1c7ca06195cba1c568909fa [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{
Hanno Becker236ea162018-12-12 14:00:34 +0000111 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 )
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200182 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300183
184 ctx->aad_len += aad_len;
185
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200186 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300187}
188
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200189int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
190 size_t len,
191 const unsigned char *input,
192 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300193{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200194 int ret;
Hanno Becker305e4e42018-12-11 15:03:16 +0000195 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
196 CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
197 CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200198
Hanno Becker305e4e42018-12-11 15:03:16 +0000199 if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
200 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300201 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200202 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300203 }
204
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200205 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300206 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200207 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300208
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200209 ret = chachapoly_pad_aad( ctx );
210 if( ret != 0 )
211 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300212 }
213
214 ctx->ciphertext_len += len;
215
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200216 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300217 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200218 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
219 if( ret != 0 )
220 return( ret );
221
222 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
223 if( ret != 0 )
224 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300225 }
226 else /* DECRYPT */
227 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200228 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
229 if( ret != 0 )
230 return( ret );
231
232 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
233 if( ret != 0 )
234 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300235 }
236
237 return( 0 );
238}
239
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200240int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
241 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300242{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200243 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300244 unsigned char len_block[16];
Hanno Becker305e4e42018-12-11 15:03:16 +0000245 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
246 CHACHAPOLY_VALIDATE_RET( mac != NULL );
Daniel Kingb8025c52016-05-17 14:43:01 -0300247
Hanno Becker305e4e42018-12-11 15:03:16 +0000248 if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300249 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200250 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300251 }
252
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200253 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300254 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200255 ret = chachapoly_pad_aad( ctx );
256 if( ret != 0 )
257 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300258 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200259 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300260 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200261 ret = chachapoly_pad_ciphertext( ctx );
262 if( ret != 0 )
263 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300264 }
265
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200266 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300267
268 /* The lengths of the AAD and ciphertext are processed by
269 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
270 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200271 len_block[ 0] = (unsigned char)( ctx->aad_len );
272 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
273 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
274 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
275 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
276 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
277 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
278 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
279 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
280 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
281 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
282 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
283 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
284 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
285 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
286 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300287
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200288 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
289 if( ret != 0 )
290 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300291
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200292 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
293
294 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300295}
296
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200297static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
298 mbedtls_chachapoly_mode_t mode,
299 size_t length,
300 const unsigned char nonce[12],
301 const unsigned char *aad,
302 size_t aad_len,
303 const unsigned char *input,
304 unsigned char *output,
305 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300306{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200307 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300308
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200309 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
310 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300311 goto cleanup;
312
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200313 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
314 if( ret != 0 )
315 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300316
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200317 ret = mbedtls_chachapoly_update( ctx, length, input, output );
318 if( ret != 0 )
319 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300320
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200321 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300322
323cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200324 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300325}
326
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200327int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
328 size_t length,
329 const unsigned char nonce[12],
330 const unsigned char *aad,
331 size_t aad_len,
332 const unsigned char *input,
333 unsigned char *output,
334 unsigned char tag[16] )
335{
Hanno Becker305e4e42018-12-11 15:03:16 +0000336 CHACHAPOLY_VALIDATE_RET( ctx != NULL );
337 CHACHAPOLY_VALIDATE_RET( nonce != NULL );
338 CHACHAPOLY_VALIDATE_RET( tag != NULL );
339 CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
340 CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
341 CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
342
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200343 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
344 length, nonce, aad, aad_len,
345 input, output, tag ) );
346}
347
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200348int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
349 size_t length,
350 const unsigned char nonce[12],
351 const unsigned char *aad,
352 size_t aad_len,
353 const unsigned char tag[16],
354 const unsigned char *input,
355 unsigned char *output )
356{
357 int ret;
358 unsigned char check_tag[16];
359 size_t i;
360 int diff;
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 );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200367
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200368 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200369 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
370 aad, aad_len, input, output, check_tag ) ) != 0 )
371 {
372 return( ret );
373 }
374
375 /* Check tag in "constant-time" */
376 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
377 diff |= tag[i] ^ check_tag[i];
378
379 if( diff != 0 )
380 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200381 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200382 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
383 }
384
385 return( 0 );
386}
387
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200388#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200389
Daniel Kingb8025c52016-05-17 14:43:01 -0300390#if defined(MBEDTLS_SELF_TEST)
391
392static const unsigned char test_key[1][32] =
393{
394 {
395 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
396 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
397 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
398 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
399 }
400};
401
402static const unsigned char test_nonce[1][12] =
403{
404 {
405 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
406 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
407 }
408};
409
410static const unsigned char test_aad[1][12] =
411{
412 {
413 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
414 0xc4, 0xc5, 0xc6, 0xc7
415 }
416};
417
418static const size_t test_aad_len[1] =
419{
420 12U
421};
422
423static const unsigned char test_input[1][114] =
424{
425 {
426 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
427 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
428 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
429 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
430 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
431 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
432 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
433 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
434 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
435 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
436 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
437 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
438 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
439 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
440 0x74, 0x2e
441 }
442};
443
444static const unsigned char test_output[1][114] =
445{
446 {
447 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
448 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
449 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
450 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
451 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
452 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
453 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
454 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
455 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
456 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
457 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
458 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
459 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
460 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
461 0x61, 0x16
462 }
463};
464
465static const size_t test_input_len[1] =
466{
467 114U
468};
469
470static const unsigned char test_mac[1][16] =
471{
472 {
473 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
474 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
475 }
476};
477
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200478#define ASSERT( cond, args ) \
479 do \
480 { \
481 if( ! ( cond ) ) \
482 { \
483 if( verbose != 0 ) \
484 mbedtls_printf args; \
485 \
486 return( -1 ); \
487 } \
488 } \
489 while( 0 )
490
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200491int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300492{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200493 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200494 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200495 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300496 unsigned char output[200];
497 unsigned char mac[16];
498
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200499 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300500 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200501 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200502 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300503
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200504 mbedtls_chachapoly_init( &ctx );
505
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200506 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
507 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200508
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200509 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
510 test_input_len[i],
511 test_nonce[i],
512 test_aad[i],
513 test_aad_len[i],
514 test_input[i],
515 output,
516 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300517
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200518 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300519
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200520 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
521 ( "failure (wrong output)\n" ) );
522
523 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
524 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300525
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200526 mbedtls_chachapoly_free( &ctx );
527
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200528 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300529 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300530 }
531
532 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300533 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300534
535 return( 0 );
536}
537
538#endif /* MBEDTLS_SELF_TEST */
539
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200540#endif /* MBEDTLS_CHACHAPOLY_C */