blob: ebf25bbbbb1fd85d7e685218e81712e43beea712 [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"
Daniel Kingb8025c52016-05-17 14:43:01 -030032#include <string.h>
33
34#if defined(MBEDTLS_SELF_TEST)
35#if defined(MBEDTLS_PLATFORM_C)
36#include "mbedtls/platform.h"
37#else
38#include <stdio.h>
39#define mbedtls_printf printf
40#endif /* MBEDTLS_PLATFORM_C */
41#endif /* MBEDTLS_SELF_TEST */
42
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020043#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030044
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020045#define CHACHAPOLY_STATE_INIT ( 0 )
46#define CHACHAPOLY_STATE_AAD ( 1 )
47#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
48#define CHACHAPOLY_STATE_FINISHED ( 3 )
Daniel Kingb8025c52016-05-17 14:43:01 -030049
50/* Implementation that should never be optimized out by the compiler */
51static void mbedtls_zeroize( void *v, size_t n ) {
52 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
53}
54
55/**
56 * \brief Adds padding bytes (zeroes) to pad the AAD for Poly1305.
57 *
58 * \param ctx The ChaCha20-Poly1305 context.
59 */
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020060static void mbedtls_chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030061{
Daniel Kinge6e79682016-05-24 11:16:17 -030062 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030063 unsigned char zeroes[15];
64
65 if ( partial_block_len > 0U )
66 {
Daniel Kinge6e79682016-05-24 11:16:17 -030067 memset( zeroes, 0, sizeof( zeroes ) );
68 (void) mbedtls_poly1305_update( &ctx->poly1305_ctx,
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +020069 zeroes,
70 16U - partial_block_len );
Daniel Kingb8025c52016-05-17 14:43:01 -030071 }
72}
73
74/**
75 * \brief Adds padding bytes (zeroes) to pad the ciphertext for Poly1305.
76 *
77 * \param ctx The ChaCha20-Poly1305 context.
78 */
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020079static void mbedtls_chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030080{
Daniel Kinge6e79682016-05-24 11:16:17 -030081 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
Daniel Kingb8025c52016-05-17 14:43:01 -030082 unsigned char zeroes[15];
83
84 if ( partial_block_len > 0U )
85 {
Daniel Kinge6e79682016-05-24 11:16:17 -030086 memset( zeroes, 0, sizeof( zeroes ) );
87 (void) mbedtls_poly1305_update( &ctx->poly1305_ctx,
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +020088 zeroes,
89 16U - partial_block_len );
Daniel Kingb8025c52016-05-17 14:43:01 -030090 }
91}
92
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020093void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -030094{
95 if ( ctx != NULL )
96 {
97 mbedtls_chacha20_init( &ctx->chacha20_ctx );
98 mbedtls_poly1305_init( &ctx->poly1305_ctx );
99 ctx->aad_len = 0U;
100 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200101 ctx->state = CHACHAPOLY_STATE_INIT;
102 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300103 }
104}
105
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200106void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
Daniel Kingb8025c52016-05-17 14:43:01 -0300107{
108 if ( ctx != NULL )
109 {
110 mbedtls_chacha20_free( &ctx->chacha20_ctx );
111 mbedtls_poly1305_free( &ctx->poly1305_ctx );
112 ctx->aad_len = 0U;
113 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200114 ctx->state = CHACHAPOLY_STATE_INIT;
115 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300116 }
117}
118
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200119int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
120 const unsigned char key[32] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300121{
122 int result;
123
124 if ( ( ctx == NULL ) || ( key == NULL ) )
125 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200126 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300127 }
128
129 result = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
130
131 return( result );
132}
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{
138 int result;
139 unsigned char poly1305_key[64];
140
141 if ( ( ctx == NULL ) || ( nonce == NULL ) )
142 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200143 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300144 }
145
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200146 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
147 result = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
Daniel Kingb8025c52016-05-17 14:43:01 -0300148 if ( result != 0 )
149 goto cleanup;
150
151 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with counter = 0.
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200152 * This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300153 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
154 * The other 256 bits are discarded.
155 */
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200156 memset( poly1305_key, 0, sizeof( poly1305_key ) );
157 result = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
158 poly1305_key, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300159 if ( result != 0 )
160 goto cleanup;
161
Manuel Pégourié-Gonnard4edd51b2018-05-07 10:21:56 +0200162 result = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
Daniel Kingb8025c52016-05-17 14:43:01 -0300163
164 if ( result == 0 )
165 {
166 ctx->aad_len = 0U;
167 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200168 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300169 ctx->mode = mode;
170 }
171
172cleanup:
173 mbedtls_zeroize( poly1305_key, 64U );
174 return( result );
175}
176
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200177int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200178 const unsigned char *aad,
179 size_t aad_len )
Daniel Kingb8025c52016-05-17 14:43:01 -0300180{
Daniel Kinga310c5e2016-05-17 15:56:26 -0300181 if ( ctx == NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -0300182 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200183 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300184 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300185 else if ( ( aad_len > 0U ) && ( aad == NULL ) )
186 {
187 /* aad pointer is allowed to be NULL if aad_len == 0 */
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200188 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kinga310c5e2016-05-17 15:56:26 -0300189 }
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200190 else if ( ctx->state != CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300191 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200192 return(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300193 }
194
195 ctx->aad_len += aad_len;
196
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200197 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300198}
199
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200200int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
201 size_t len,
202 const unsigned char *input,
203 unsigned char *output )
Daniel Kingb8025c52016-05-17 14:43:01 -0300204{
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200205 if ( ctx == NULL )
Daniel Kingb8025c52016-05-17 14:43:01 -0300206 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200207 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300208 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300209 else if ( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
210 {
211 /* input and output pointers are allowed to be NULL if len == 0 */
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200212 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kinga310c5e2016-05-17 15:56:26 -0300213 }
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200214 else if ( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
215 ( 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é-Gonnarddca3a5d2018-05-07 10:43:27 +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é-Gonnarddca3a5d2018-05-07 10:43:27 +0200224 mbedtls_chachapoly_pad_aad( ctx );
Daniel Kingb8025c52016-05-17 14:43:01 -0300225 }
226
227 ctx->ciphertext_len += len;
228
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200229 if ( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300230 {
231 /* Note: the following functions return an error only if one or more of
232 * the input pointers are NULL. Since we have checked their validity
233 * above, we can safety ignore the return value.
234 */
Daniel Kinge6e79682016-05-24 11:16:17 -0300235 (void) mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200236 (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
Daniel Kingb8025c52016-05-17 14:43:01 -0300237 }
238 else /* DECRYPT */
239 {
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200240 (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
Daniel Kinge6e79682016-05-24 11:16:17 -0300241 (void) mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
Daniel Kingb8025c52016-05-17 14:43:01 -0300242 }
243
244 return( 0 );
245}
246
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200247int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
248 unsigned char mac[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300249{
250 unsigned char len_block[16];
251
252 if ( ( ctx == NULL ) || ( mac == NULL ) )
253 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200254 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
Daniel Kingb8025c52016-05-17 14:43:01 -0300255 }
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200256 else if ( ctx->state == CHACHAPOLY_STATE_INIT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300257 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200258 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
Daniel Kingb8025c52016-05-17 14:43:01 -0300259 }
260
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200261 if ( ctx->state == CHACHAPOLY_STATE_AAD )
Daniel Kingb8025c52016-05-17 14:43:01 -0300262 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200263 mbedtls_chachapoly_pad_aad( ctx );
Daniel Kingb8025c52016-05-17 14:43:01 -0300264 }
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200265 else if ( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
Daniel Kingb8025c52016-05-17 14:43:01 -0300266 {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200267 mbedtls_chachapoly_pad_ciphertext( ctx );
Daniel Kingb8025c52016-05-17 14:43:01 -0300268 }
269
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200270 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300271
272 /* The lengths of the AAD and ciphertext are processed by
273 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
274 */
Daniel Kinge6e79682016-05-24 11:16:17 -0300275 len_block[0] = (unsigned char) ctx->aad_len;
276 len_block[1] = (unsigned char) ( ctx->aad_len >> 8 );
277 len_block[2] = (unsigned char) ( ctx->aad_len >> 16 );
278 len_block[3] = (unsigned char) ( ctx->aad_len >> 24 );
279 len_block[4] = (unsigned char) ( ctx->aad_len >> 32 );
280 len_block[5] = (unsigned char) ( ctx->aad_len >> 40 );
281 len_block[6] = (unsigned char) ( ctx->aad_len >> 48 );
282 len_block[7] = (unsigned char) ( ctx->aad_len >> 56 );
283 len_block[8] = (unsigned char) ctx->ciphertext_len;
284 len_block[9] = (unsigned char) ( ctx->ciphertext_len >> 8 );
285 len_block[10] = (unsigned char) ( ctx->ciphertext_len >> 16 );
286 len_block[11] = (unsigned char) ( ctx->ciphertext_len >> 24 );
287 len_block[12] = (unsigned char) ( ctx->ciphertext_len >> 32 );
288 len_block[13] = (unsigned char) ( ctx->ciphertext_len >> 40 );
289 len_block[14] = (unsigned char) ( ctx->ciphertext_len >> 48 );
290 len_block[15] = (unsigned char) ( ctx->ciphertext_len >> 56 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300291
Manuel Pégourié-Gonnardb1ac5e72018-05-09 09:25:00 +0200292 (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
Daniel Kinge6e79682016-05-24 11:16:17 -0300293 (void) mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300294
295 return( 0 );
296}
297
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200298int mbedtls_chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
299 mbedtls_chachapoly_mode_t mode,
300 size_t length,
301 const unsigned char nonce[12],
302 const unsigned char *aad,
303 size_t aad_len,
304 const unsigned char *input,
305 unsigned char *output,
306 unsigned char tag[16] )
Daniel Kingb8025c52016-05-17 14:43:01 -0300307{
Daniel Kingb8025c52016-05-17 14:43:01 -0300308 int result;
309
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200310 result = mbedtls_chachapoly_starts( ctx, nonce, mode );
Daniel Kingb8025c52016-05-17 14:43:01 -0300311 if ( result != 0 )
312 goto cleanup;
313
Manuel Pégourié-Gonnard5ef92d32018-05-09 09:34:25 +0200314 result = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
Daniel Kingb8025c52016-05-17 14:43:01 -0300315 if ( result != 0 )
316 goto cleanup;
317
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200318 result = mbedtls_chachapoly_update( ctx, length, input, output );
Daniel Kingb8025c52016-05-17 14:43:01 -0300319 if ( result != 0 )
320 goto cleanup;
321
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200322 result = mbedtls_chachapoly_finish( ctx, tag );
Daniel Kingb8025c52016-05-17 14:43:01 -0300323
324cleanup:
Daniel Kingb8025c52016-05-17 14:43:01 -0300325 return( result );
326}
327
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200328int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
329 size_t length,
330 const unsigned char nonce[12],
331 const unsigned char *aad,
332 size_t aad_len,
333 const unsigned char tag[16],
334 const unsigned char *input,
335 unsigned char *output )
336{
337 int ret;
338 unsigned char check_tag[16];
339 size_t i;
340 int diff;
341
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200342 if( tag == NULL )
343 return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
344
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200345 if( ( ret = mbedtls_chachapoly_crypt_and_tag( ctx,
346 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
347 aad, aad_len, input, output, check_tag ) ) != 0 )
348 {
349 return( ret );
350 }
351
352 /* Check tag in "constant-time" */
353 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
354 diff |= tag[i] ^ check_tag[i];
355
356 if( diff != 0 )
357 {
358 mbedtls_zeroize( output, length );
359 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
360 }
361
362 return( 0 );
363}
364
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200365#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200366
Daniel Kingb8025c52016-05-17 14:43:01 -0300367#if defined(MBEDTLS_SELF_TEST)
368
369static const unsigned char test_key[1][32] =
370{
371 {
372 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
373 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
374 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
375 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
376 }
377};
378
379static const unsigned char test_nonce[1][12] =
380{
381 {
382 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
383 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
384 }
385};
386
387static const unsigned char test_aad[1][12] =
388{
389 {
390 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
391 0xc4, 0xc5, 0xc6, 0xc7
392 }
393};
394
395static const size_t test_aad_len[1] =
396{
397 12U
398};
399
400static const unsigned char test_input[1][114] =
401{
402 {
403 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
404 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
405 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
406 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
407 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
408 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
409 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
410 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
411 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
412 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
413 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
414 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
415 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
416 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
417 0x74, 0x2e
418 }
419};
420
421static const unsigned char test_output[1][114] =
422{
423 {
424 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
425 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
426 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
427 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
428 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
429 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
430 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
431 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
432 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
433 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
434 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
435 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
436 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
437 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
438 0x61, 0x16
439 }
440};
441
442static const size_t test_input_len[1] =
443{
444 114U
445};
446
447static const unsigned char test_mac[1][16] =
448{
449 {
450 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
451 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
452 }
453};
454
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200455#define ASSERT( cond, args ) \
456 do \
457 { \
458 if( ! ( cond ) ) \
459 { \
460 if( verbose != 0 ) \
461 mbedtls_printf args; \
462 \
463 return( -1 ); \
464 } \
465 } \
466 while( 0 )
467
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200468int mbedtls_chachapoly_self_test( int verbose )
Daniel Kingb8025c52016-05-17 14:43:01 -0300469{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200470 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200471 unsigned i;
Daniel Kingb8025c52016-05-17 14:43:01 -0300472 int result;
473 unsigned char output[200];
474 unsigned char mac[16];
475
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200476 for( i = 0U; i < 1U; i++ )
Daniel Kingb8025c52016-05-17 14:43:01 -0300477 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200478 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200479 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300480
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200481 mbedtls_chachapoly_init( &ctx );
482
483 result = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200484 ASSERT( 0 == result, ( "setkey() error code: %i\n", result ) );
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200485
486 result = mbedtls_chachapoly_crypt_and_tag( &ctx,
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200487 MBEDTLS_CHACHAPOLY_ENCRYPT,
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200488 test_input_len[i],
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200489 test_nonce[i],
490 test_aad[i],
491 test_aad_len[i],
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200492 test_input[i],
493 output,
494 mac );
Daniel Kingb8025c52016-05-17 14:43:01 -0300495
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200496 ASSERT( 0 == result, ( "crypt_and_tag() error code: %i\n", result ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300497
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200498 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
499 ( "failure (wrong output)\n" ) );
500
501 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
502 ( "failure (wrong MAC)\n" ) );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300503
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200504 mbedtls_chachapoly_free( &ctx );
505
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200506 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300507 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300508 }
509
510 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300511 mbedtls_printf( "\n" );
Daniel Kingb8025c52016-05-17 14:43:01 -0300512
513 return( 0 );
514}
515
516#endif /* MBEDTLS_SELF_TEST */
517
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200518#endif /* MBEDTLS_CHACHAPOLY_C */