Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8774 | rgimad | 1 | /** |
2 | * \file chachapoly.c |
||
3 | * |
||
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: GPL-2.0 |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or modify |
||
10 | * it under the terms of the GNU General Public License as published by |
||
11 | * the Free Software Foundation; either version 2 of the License, or |
||
12 | * (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU General Public License along |
||
20 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
22 | * |
||
23 | * This file is part of mbed TLS (https://tls.mbed.org) |
||
24 | */ |
||
25 | #if !defined(MBEDTLS_CONFIG_FILE) |
||
26 | #include "mbedtls/config.h" |
||
27 | #else |
||
28 | #include MBEDTLS_CONFIG_FILE |
||
29 | #endif |
||
30 | |||
31 | #if defined(MBEDTLS_CHACHAPOLY_C) |
||
32 | |||
33 | #include "mbedtls/chachapoly.h" |
||
34 | #include "mbedtls/platform_util.h" |
||
35 | |||
36 | #include |
||
37 | |||
38 | #if defined(MBEDTLS_SELF_TEST) |
||
39 | #if defined(MBEDTLS_PLATFORM_C) |
||
40 | #include "mbedtls/platform.h" |
||
41 | #else |
||
42 | #include |
||
43 | #define mbedtls_printf printf |
||
44 | #endif /* MBEDTLS_PLATFORM_C */ |
||
45 | #endif /* MBEDTLS_SELF_TEST */ |
||
46 | |||
47 | #if !defined(MBEDTLS_CHACHAPOLY_ALT) |
||
48 | |||
49 | /* Parameter validation macros */ |
||
50 | #define CHACHAPOLY_VALIDATE_RET( cond ) \ |
||
51 | MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) |
||
52 | #define CHACHAPOLY_VALIDATE( cond ) \ |
||
53 | MBEDTLS_INTERNAL_VALIDATE( cond ) |
||
54 | |||
55 | #define CHACHAPOLY_STATE_INIT ( 0 ) |
||
56 | #define CHACHAPOLY_STATE_AAD ( 1 ) |
||
57 | #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ |
||
58 | #define CHACHAPOLY_STATE_FINISHED ( 3 ) |
||
59 | |||
60 | /** |
||
61 | * \brief Adds nul bytes to pad the AAD for Poly1305. |
||
62 | * |
||
63 | * \param ctx The ChaCha20-Poly1305 context. |
||
64 | */ |
||
65 | static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) |
||
66 | { |
||
67 | uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); |
||
68 | unsigned char zeroes[15]; |
||
69 | |||
70 | if( partial_block_len == 0U ) |
||
71 | return( 0 ); |
||
72 | |||
73 | memset( zeroes, 0, sizeof( zeroes ) ); |
||
74 | |||
75 | return( mbedtls_poly1305_update( &ctx->poly1305_ctx, |
||
76 | zeroes, |
||
77 | 16U - partial_block_len ) ); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * \brief Adds nul bytes to pad the ciphertext for Poly1305. |
||
82 | * |
||
83 | * \param ctx The ChaCha20-Poly1305 context. |
||
84 | */ |
||
85 | static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) |
||
86 | { |
||
87 | uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); |
||
88 | unsigned char zeroes[15]; |
||
89 | |||
90 | if( partial_block_len == 0U ) |
||
91 | return( 0 ); |
||
92 | |||
93 | memset( zeroes, 0, sizeof( zeroes ) ); |
||
94 | return( mbedtls_poly1305_update( &ctx->poly1305_ctx, |
||
95 | zeroes, |
||
96 | 16U - partial_block_len ) ); |
||
97 | } |
||
98 | |||
99 | void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) |
||
100 | { |
||
101 | CHACHAPOLY_VALIDATE( ctx != NULL ); |
||
102 | |||
103 | mbedtls_chacha20_init( &ctx->chacha20_ctx ); |
||
104 | mbedtls_poly1305_init( &ctx->poly1305_ctx ); |
||
105 | ctx->aad_len = 0U; |
||
106 | ctx->ciphertext_len = 0U; |
||
107 | ctx->state = CHACHAPOLY_STATE_INIT; |
||
108 | ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; |
||
109 | } |
||
110 | |||
111 | void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) |
||
112 | { |
||
113 | if( ctx == NULL ) |
||
114 | return; |
||
115 | |||
116 | mbedtls_chacha20_free( &ctx->chacha20_ctx ); |
||
117 | mbedtls_poly1305_free( &ctx->poly1305_ctx ); |
||
118 | ctx->aad_len = 0U; |
||
119 | ctx->ciphertext_len = 0U; |
||
120 | ctx->state = CHACHAPOLY_STATE_INIT; |
||
121 | ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; |
||
122 | } |
||
123 | |||
124 | int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, |
||
125 | const unsigned char key[32] ) |
||
126 | { |
||
127 | int ret; |
||
128 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
129 | CHACHAPOLY_VALIDATE_RET( key != NULL ); |
||
130 | |||
131 | ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); |
||
132 | |||
133 | return( ret ); |
||
134 | } |
||
135 | |||
136 | int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, |
||
137 | const unsigned char nonce[12], |
||
138 | mbedtls_chachapoly_mode_t mode ) |
||
139 | { |
||
140 | int ret; |
||
141 | unsigned char poly1305_key[64]; |
||
142 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
143 | CHACHAPOLY_VALIDATE_RET( nonce != NULL ); |
||
144 | |||
145 | /* Set counter = 0, will be update to 1 when generating Poly1305 key */ |
||
146 | ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); |
||
147 | if( ret != 0 ) |
||
148 | goto cleanup; |
||
149 | |||
150 | /* Generate the Poly1305 key by getting the ChaCha20 keystream output with |
||
151 | * counter = 0. This is the same as encrypting a buffer of zeroes. |
||
152 | * Only the first 256-bits (32 bytes) of the key is used for Poly1305. |
||
153 | * The other 256 bits are discarded. |
||
154 | */ |
||
155 | memset( poly1305_key, 0, sizeof( poly1305_key ) ); |
||
156 | ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), |
||
157 | poly1305_key, poly1305_key ); |
||
158 | if( ret != 0 ) |
||
159 | goto cleanup; |
||
160 | |||
161 | ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); |
||
162 | |||
163 | if( ret == 0 ) |
||
164 | { |
||
165 | ctx->aad_len = 0U; |
||
166 | ctx->ciphertext_len = 0U; |
||
167 | ctx->state = CHACHAPOLY_STATE_AAD; |
||
168 | ctx->mode = mode; |
||
169 | } |
||
170 | |||
171 | cleanup: |
||
172 | mbedtls_platform_zeroize( poly1305_key, 64U ); |
||
173 | return( ret ); |
||
174 | } |
||
175 | |||
176 | int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, |
||
177 | const unsigned char *aad, |
||
178 | size_t aad_len ) |
||
179 | { |
||
180 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
181 | CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); |
||
182 | |||
183 | if( ctx->state != CHACHAPOLY_STATE_AAD ) |
||
184 | return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
||
185 | |||
186 | ctx->aad_len += aad_len; |
||
187 | |||
188 | return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); |
||
189 | } |
||
190 | |||
191 | int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, |
||
192 | size_t len, |
||
193 | const unsigned char *input, |
||
194 | unsigned char *output ) |
||
195 | { |
||
196 | int ret; |
||
197 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
198 | CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); |
||
199 | CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); |
||
200 | |||
201 | if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && |
||
202 | ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) |
||
203 | { |
||
204 | return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
||
205 | } |
||
206 | |||
207 | if( ctx->state == CHACHAPOLY_STATE_AAD ) |
||
208 | { |
||
209 | ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; |
||
210 | |||
211 | ret = chachapoly_pad_aad( ctx ); |
||
212 | if( ret != 0 ) |
||
213 | return( ret ); |
||
214 | } |
||
215 | |||
216 | ctx->ciphertext_len += len; |
||
217 | |||
218 | if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) |
||
219 | { |
||
220 | 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 ); |
||
227 | } |
||
228 | else /* DECRYPT */ |
||
229 | { |
||
230 | 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 ); |
||
237 | } |
||
238 | |||
239 | return( 0 ); |
||
240 | } |
||
241 | |||
242 | int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, |
||
243 | unsigned char mac[16] ) |
||
244 | { |
||
245 | int ret; |
||
246 | unsigned char len_block[16]; |
||
247 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
248 | CHACHAPOLY_VALIDATE_RET( mac != NULL ); |
||
249 | |||
250 | if( ctx->state == CHACHAPOLY_STATE_INIT ) |
||
251 | { |
||
252 | return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
||
253 | } |
||
254 | |||
255 | if( ctx->state == CHACHAPOLY_STATE_AAD ) |
||
256 | { |
||
257 | ret = chachapoly_pad_aad( ctx ); |
||
258 | if( ret != 0 ) |
||
259 | return( ret ); |
||
260 | } |
||
261 | else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) |
||
262 | { |
||
263 | ret = chachapoly_pad_ciphertext( ctx ); |
||
264 | if( ret != 0 ) |
||
265 | return( ret ); |
||
266 | } |
||
267 | |||
268 | ctx->state = CHACHAPOLY_STATE_FINISHED; |
||
269 | |||
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 | */ |
||
273 | 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 ); |
||
289 | |||
290 | ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); |
||
291 | if( ret != 0 ) |
||
292 | return( ret ); |
||
293 | |||
294 | ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); |
||
295 | |||
296 | return( ret ); |
||
297 | } |
||
298 | |||
299 | static 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] ) |
||
308 | { |
||
309 | int ret; |
||
310 | |||
311 | ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); |
||
312 | if( ret != 0 ) |
||
313 | goto cleanup; |
||
314 | |||
315 | ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); |
||
316 | if( ret != 0 ) |
||
317 | goto cleanup; |
||
318 | |||
319 | ret = mbedtls_chachapoly_update( ctx, length, input, output ); |
||
320 | if( ret != 0 ) |
||
321 | goto cleanup; |
||
322 | |||
323 | ret = mbedtls_chachapoly_finish( ctx, tag ); |
||
324 | |||
325 | cleanup: |
||
326 | return( ret ); |
||
327 | } |
||
328 | |||
329 | int 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 | { |
||
338 | 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 | |||
345 | return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, |
||
346 | length, nonce, aad, aad_len, |
||
347 | input, output, tag ) ); |
||
348 | } |
||
349 | |||
350 | int 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; |
||
363 | CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
||
364 | CHACHAPOLY_VALIDATE_RET( nonce != NULL ); |
||
365 | CHACHAPOLY_VALIDATE_RET( tag != NULL ); |
||
366 | CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); |
||
367 | CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); |
||
368 | CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); |
||
369 | |||
370 | if( ( ret = chachapoly_crypt_and_tag( ctx, |
||
371 | 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 | { |
||
383 | mbedtls_platform_zeroize( output, length ); |
||
384 | return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); |
||
385 | } |
||
386 | |||
387 | return( 0 ); |
||
388 | } |
||
389 | |||
390 | #endif /* MBEDTLS_CHACHAPOLY_ALT */ |
||
391 | |||
392 | #if defined(MBEDTLS_SELF_TEST) |
||
393 | |||
394 | static 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 | |||
404 | static 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 | |||
412 | static 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 | |||
420 | static const size_t test_aad_len[1] = |
||
421 | { |
||
422 | 12U |
||
423 | }; |
||
424 | |||
425 | static 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 | |||
446 | static 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 | |||
467 | static const size_t test_input_len[1] = |
||
468 | { |
||
469 | 114U |
||
470 | }; |
||
471 | |||
472 | static 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 | |||
480 | #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 | |||
493 | int mbedtls_chachapoly_self_test( int verbose ) |
||
494 | { |
||
495 | mbedtls_chachapoly_context ctx; |
||
496 | unsigned i; |
||
497 | int ret; |
||
498 | unsigned char output[200]; |
||
499 | unsigned char mac[16]; |
||
500 | |||
501 | for( i = 0U; i < 1U; i++ ) |
||
502 | { |
||
503 | if( verbose != 0 ) |
||
504 | mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); |
||
505 | |||
506 | mbedtls_chachapoly_init( &ctx ); |
||
507 | |||
508 | ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); |
||
509 | ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); |
||
510 | |||
511 | 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 ); |
||
519 | |||
520 | ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); |
||
521 | |||
522 | 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" ) ); |
||
527 | |||
528 | mbedtls_chachapoly_free( &ctx ); |
||
529 | |||
530 | if( verbose != 0 ) |
||
531 | mbedtls_printf( "passed\n" ); |
||
532 | } |
||
533 | |||
534 | if( verbose != 0 ) |
||
535 | mbedtls_printf( "\n" ); |
||
536 | |||
537 | return( 0 ); |
||
538 | } |
||
539 | |||
540 | #endif /* MBEDTLS_SELF_TEST */ |
||
541 | |||
542 | #endif /* MBEDTLS_CHACHAPOLY_C */>> |