blob: 860f8776538b98bd4ec142a64b08fe755ba8f068 [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
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020047#define CHACHAPOLY_STATE_INIT ( 0 )
48#define CHACHAPOLY_STATE_AAD ( 1 )
49#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
50#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030051
Daniel Kingb8025c52016-05-17 14:43:01 -030052/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020053 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030054 *
55 * \param ctx The ChaCha20-Poly1305 context.
56 */
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020057static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030058{
Daniel Kinge6e79682016-05-24 11:16:17 -030059 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030060 unsigned char zeroes[15];
61
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020062 if( partial_block_len == 0U )
63 return( 0 );
64
65 memset( zeroes, 0, sizeof( zeroes ) );
66
67 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
68 zeroes,
69 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030070}
71
72/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020073 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030074 *
75 * \param ctx The ChaCha20-Poly1305 context.
76 */
Manuel Pégourié-Gonnard26c3b0a2018-06-04 12:06:23 +020077static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030078{
Daniel Kinge6e79682016-05-24 11:16:17 -030079 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030080 unsigned char zeroes[15];
81
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020082 if( partial_block_len == 0U )
83 return( 0 );
84
85 memset( zeroes, 0, sizeof( zeroes ) );
86 return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
87 zeroes,
88 16U - partial_block_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -030089}
90
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020091void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030092{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020093 if( ctx != NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -030094 {
95 mbedtls_chacha20_init( &ctx->chacha20_ctx );
96 mbedtls_poly1305_init( &ctx->poly1305_ctx );
97 ctx->aad_len = 0U;
98 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020099 ctx->state = CHACHAPOLY_STATE_INIT;
100 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300101 }
102}
103
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200104void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300105{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200106 if( ctx != NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -0300107 {
108 mbedtls_chacha20_free( &ctx->chacha20_ctx );
109 mbedtls_poly1305_free( &ctx->poly1305_ctx );
110 ctx->aad_len = 0U;
111 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200112 ctx->state = CHACHAPOLY_STATE_INIT;
113 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300114 }
115}
116
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200117int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
118 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300119{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200120 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300121
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200122 if( ( ctx == NULL ) || ( key == NULL ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300123 {
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200124 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300125 }
126
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200127 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300128
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200129 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300130}
131
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200132int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
133 const unsigned char nonce[12],
134 mbedtls_chachapoly_mode_t mode )
Daniel Kingb8025c52016-05-17 14:43:01 -0300135{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200136 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300137 unsigned char poly1305_key[64];
138
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200139 if( ( ctx == NULL ) || ( nonce == NULL ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300140 {
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200141 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300142 }
143
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200144 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200145 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
146 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300147 goto cleanup;
148
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200149 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
150 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300151 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
152 * The other 256 bits are discarded.
153 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200154 memset( poly1305_key, 0, sizeof( poly1305_key ) );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200155 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200156 poly1305_key, poly1305_key );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200157 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300158 goto cleanup;
159
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200160 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300161
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200162 if( ret == 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300163 {
164 ctx->aad_len = 0U;
165 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200166 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300167 ctx->mode = mode;
168 }
169
170cleanup:
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200171 mbedtls_platform_zeroize( poly1305_key, 64U );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200172 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300173}
174
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200175int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200176 const unsigned char *aad,
177 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300178{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200179 if( ctx == NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -0300180 {
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200181 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300182 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200183 else if( ( aad_len > 0U ) && ( aad == NULL ) )
Daniel Kinga310c5e2016-05-17 15:56:26 -0300184 {
185 /* aad pointer is allowed to be NULL if aad_len == 0 */
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200186 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kinga310c5e2016-05-17 15:56:26 -0300187 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200188 else if( ctx->state != CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300189 {
Manuel Pégourié-Gonnardc7bc9e12018-06-18 10:30:30 +0200190 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300191 }
192
193 ctx->aad_len += aad_len;
194
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200195 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300196}
197
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200198int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
199 size_t len,
200 const unsigned char *input,
201 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300202{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200203 int ret;
204
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200205 if( ctx == NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -0300206 {
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200207 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300208 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200209 else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
Daniel Kinga310c5e2016-05-17 15:56:26 -0300210 {
211 /* input and output pointers are allowed to be NULL if len == 0 */
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200212 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kinga310c5e2016-05-17 15:56:26 -0300213 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200214 else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200215 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300216 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200217 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300218 }
219
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200220 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300221 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200222 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300223
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200224 ret = chachapoly_pad_aad( ctx );
225 if( ret != 0 )
226 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300227 }
228
229 ctx->ciphertext_len += len;
230
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200231 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300232 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200233 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
234 if( ret != 0 )
235 return( ret );
236
237 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
238 if( ret != 0 )
239 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300240 }
241 else /* DECRYPT */
242 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200243 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
244 if( ret != 0 )
245 return( ret );
246
247 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
248 if( ret != 0 )
249 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300250 }
251
252 return( 0 );
253}
254
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200255int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
256 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300257{
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200258 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300259 unsigned char len_block[16];
260
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200261 if( ( ctx == NULL ) || ( mac == NULL ) )
Daniel Kingb8025c52016-05-17 14:43:01 -0300262 {
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200263 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300264 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200265 else if( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300266 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200267 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300268 }
269
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200270 if( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300271 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200272 ret = chachapoly_pad_aad( ctx );
273 if( ret != 0 )
274 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300275 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200276 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300277 {
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200278 ret = chachapoly_pad_ciphertext( ctx );
279 if( ret != 0 )
280 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300281 }
282
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200283 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300284
285 /* The lengths of the AAD and ciphertext are processed by
286 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
287 */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200288 len_block[ 0] = (unsigned char)( ctx->aad_len );
289 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
290 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
291 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
292 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
293 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
294 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
295 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
296 len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
297 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
298 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
299 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
300 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
301 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
302 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
303 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300304
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200305 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
306 if( ret != 0 )
307 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300308
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200309 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
310
311 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300312}
313
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200314static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
315 mbedtls_chachapoly_mode_t mode,
316 size_t length,
317 const unsigned char nonce[12],
318 const unsigned char *aad,
319 size_t aad_len,
320 const unsigned char *input,
321 unsigned char *output,
322 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300323{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200324 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300325
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200326 ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
327 if( ret != 0 )
Daniel Kingb8025c52016-05-17 14:43:01 -0300328 goto cleanup;
329
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200330 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
331 if( ret != 0 )
332 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300333
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200334 ret = mbedtls_chachapoly_update( ctx, length, input, output );
335 if( ret != 0 )
336 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300337
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200338 ret = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300339
340cleanup:
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200341 return( ret );
Daniel Kingb8025c52016-05-17 14:43:01 -0300342}
343
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200344int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
345 size_t length,
346 const unsigned char nonce[12],
347 const unsigned char *aad,
348 size_t aad_len,
349 const unsigned char *input,
350 unsigned char *output,
351 unsigned char tag[16] )
352{
353 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
354 length, nonce, aad, aad_len,
355 input, output, tag ) );
356}
357
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200358int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
359 size_t length,
360 const unsigned char nonce[12],
361 const unsigned char *aad,
362 size_t aad_len,
363 const unsigned char tag[16],
364 const unsigned char *input,
365 unsigned char *output )
366{
367 int ret;
368 unsigned char check_tag[16];
369 size_t i;
370 int diff;
371
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200372 if( tag == NULL )
Manuel Pégourié-Gonnard3798b6b2018-05-24 13:27:45 +0200373 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200374
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200375 if( ( ret = chachapoly_crypt_and_tag( ctx,
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200376 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
377 aad, aad_len, input, output, check_tag ) ) != 0 )
378 {
379 return( ret );
380 }
381
382 /* Check tag in "constant-time" */
383 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
384 diff |= tag[i] ^ check_tag[i];
385
386 if( diff != 0 )
387 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200388 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200389 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
390 }
391
392 return( 0 );
393}
394
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200395#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200396
Daniel Kingb8025c52016-05-17 14:43:01 -0300397#if defined(MBEDTLS_SELF_TEST)
398
399static const unsigned char test_key[1][32] =
400{
401 {
402 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
403 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
404 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
405 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
406 }
407};
408
409static const unsigned char test_nonce[1][12] =
410{
411 {
412 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
413 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
414 }
415};
416
417static const unsigned char test_aad[1][12] =
418{
419 {
420 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
421 0xc4, 0xc5, 0xc6, 0xc7
422 }
423};
424
425static const size_t test_aad_len[1] =
426{
427 12U
428};
429
430static const unsigned char test_input[1][114] =
431{
432 {
433 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
434 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
435 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
436 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
437 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
438 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
439 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
440 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
441 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
442 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
443 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
444 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
445 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
446 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
447 0x74, 0x2e
448 }
449};
450
451static const unsigned char test_output[1][114] =
452{
453 {
454 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
455 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
456 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
457 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
458 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
459 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
460 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
461 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
462 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
463 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
464 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
465 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
466 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
467 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
468 0x61, 0x16
469 }
470};
471
472static const size_t test_input_len[1] =
473{
474 114U
475};
476
477static const unsigned char test_mac[1][16] =
478{
479 {
480 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
481 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
482 }
483};
484
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200485#define ASSERT( cond, args ) \
486 do \
487 { \
488 if( ! ( cond ) ) \
489 { \
490 if( verbose != 0 ) \
491 mbedtls_printf args; \
492 \
493 return( -1 ); \
494 } \
495 } \
496 while( 0 )
497
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200498int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300499{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200500 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200501 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200502 int ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300503 unsigned char output[200];
504 unsigned char mac[16];
505
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200506 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300507 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200508 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200509 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300510
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200511 mbedtls_chachapoly_init( &ctx );
512
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200513 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
514 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200515
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200516 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
517 test_input_len[i],
518 test_nonce[i],
519 test_aad[i],
520 test_aad_len[i],
521 test_input[i],
522 output,
523 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300524
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200525 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300526
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200527 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
528 ( "failure (wrong output)\n" ) );
529
530 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
531 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300532
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200533 mbedtls_chachapoly_free( &ctx );
534
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200535 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300536 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300537 }
538
539 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300540 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300541
542 return( 0 );
543}
544
545#endif /* MBEDTLS_SELF_TEST */
546
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200547#endif /* MBEDTLS_CHACHAPOLY_C */